This workflow corresponds to n8n.io template #9881 — we link there as the canonical source.
This workflow follows the Google Sheets → OpenAI recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "vt26lV2qI3OlOvin",
"name": "Auto-tag and analyze customer feedback in Google Sheets with OpenAI",
"tags": [
{
"id": "GCoQbohMyJ7ZU01a",
"name": "Customer Support",
"createdAt": "2025-10-18T17:05:33.588Z",
"updatedAt": "2025-10-18T17:05:33.588Z"
},
{
"id": "nNjwOWFKi8QHbVYy",
"name": "User Experience",
"createdAt": "2025-10-18T17:05:19.693Z",
"updatedAt": "2025-10-18T17:05:19.693Z"
}
],
"nodes": [
{
"id": "20d919c3-088c-4748-bf11-31a8f1490c24",
"name": "When clicking 'Execute workflow'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
1616,
288
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d9064168-bf99-4066-89a7-0dbe19c8f3ae",
"name": "Fetch Allowed Tags",
"type": "n8n-nodes-base.googleSheets",
"position": [
2464,
272
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Tags"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "=GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "7f0ee6a9-cfd1-449d-96c7-5dcd180fc152",
"name": "Fetch New Feedbacks",
"type": "n8n-nodes-base.googleSheets",
"position": [
2464,
1152
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupColumn": "Status"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Feedbacks"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "=GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "dcf3888e-b2f4-4d35-acc2-48798368aee2",
"name": "Merge Tags & Feedbacks",
"type": "n8n-nodes-base.merge",
"position": [
3136,
720
],
"parameters": {
"mode": "chooseBranch"
},
"typeVersion": 2.1
},
{
"id": "086461e1-dc56-412a-a073-740af265b83e",
"name": "Attach Tags Array",
"type": "n8n-nodes-base.set",
"position": [
3552,
736
],
"parameters": {
"values": {
"string": [
{
"name": "tags",
"value": "={{ $items('Fetch Allowed Tags').map(i => i.json['Tags']) }}"
}
]
},
"options": {}
},
"typeVersion": 2
},
{
"id": "bce8aee5-89f5-423c-89f9-b6b0705a3d50",
"name": "Tag Feedbacks with AI",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
4784,
880
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"messages": {
"values": [
{
"role": "system",
"content": "=You are a tagging, sentiment, and emotion analysis assistant. \n\nInput format:\n- You will receive multiple feedbacks in an array under `feedbacks`.\n- Each feedback item has: `row_number` and `text`.\n- Feedback text may be multilingual (e.g., Persian/Farsi). Analyze natively.\n- You will also receive an `allowed_tags` array (may be empty).\n\nGeneral rules:\n- Analyze each feedback independently.\n- Detect and describe emotional tone naturally.\n- Identify one **primary emotion** that captures the dominant feeling.\n- Optionally include up to two **secondary emotions** that reflect additional nuances.\n- Output must be a **valid JSON array** only, with **no extra text** before or after.\n- Maintain the original input order.\n\n\u26a0\ufe0f CRITICAL TAGGING RULES (2-tier system with STRONG preference for allowed_tags):\n\n**TIER 1: ALWAYS TRY ALLOWED TAGS FIRST (Your Primary Responsibility)**\n- If `allowed_tags` is provided, you MUST thoroughly examine it for matches.\n- **Be creative and flexible in matching:**\n - Look for direct matches (e.g., \"Bug\" for bug reports)\n - Look for semantic matches (e.g., \"Payment\" tag for \"billing issue\" feedback)\n - Look for category matches (e.g., \"Performance\" for \"slow\", \"lag\", \"loading\")\n - Look for broader themes (e.g., \"User Experience\" for usability complaints)\n- **Think broadly:** A tag doesn't need to be a perfect word-for-word match.\n- Consider the **intent and topic** of the feedback, not just exact keywords.\n- Return up to **3** most relevant tags from `allowed_tags` (sorted by relevance).\n- **Only proceed to Tier 2 if you genuinely cannot find ANY relevant match** after careful analysis.\n\n**TIER 2: AI-Generated Tags (ONLY as a last resort)**\n- Use this ONLY when:\n - `allowed_tags` is completely empty, OR\n - After thorough analysis, absolutely NO tag in `allowed_tags` relates to the feedback topic\n- Generate up to **2 custom, descriptive tags** (short labels like \"UI Bug\", \"Pricing Question\").\n- Put these in `ai_tag_1` and `ai_tag_2`.\n- Use \"\" for empty AI tag fields.\n\n**Decision Flow:**\n1. Read the feedback carefully\n2. Review ALL allowed_tags thoroughly\n3. Can you match any tag semantically or thematically? \u2192 YES = Use allowed tags, set ai_tag_1=\"\", ai_tag_2=\"\"\n4. Still no match after careful review? \u2192 Use AI tags as fallback\n\nSentiment scale (choose one):\n[\"Very Negative\", \"Negative\", \"Neutral\", \"Positive\", \"Very Positive\"].\n\nEmotions:\n- primary_emotion: one clear emotional label (e.g., \"anger\", \"hope\", \"disappointment\", \"relief\", \"satisfaction\", \"gratitude\").\n- secondary_emotion: optional supporting emotional state (e.g., \"frustration\", \"trust\", \"curiosity\", \"anxiety\"). Use \"\" if none applies.\n\nResponse JSON schema (use exactly these keys):\n[\n {\n \"row_number\": <row_number from input>,\n \"tags\": [\"tag_from_allowed_list_1\", \"tag_from_allowed_list_2\"],\n \"ai_tag_1\": \"\",\n \"ai_tag_2\": \"\",\n \"sentiment\": \"Positive\",\n \"primary_emotion\": \"Gratitude\",\n \"secondary_emotion\": \"Relief\"\n }\n]\n\nExamples of GOOD matching behavior:\n\u2705 Feedback: \"The app crashes constantly\" + allowed_tags: [\"Bug\", \"Stability\", \"Feature\"] \u2192 tags: [\"Bug\", \"Stability\"]\n\u2705 Feedback: \"Can't complete checkout\" + allowed_tags: [\"Payment\", \"Technical Issue\", \"UI\"] \u2192 tags: [\"Payment\", \"Technical Issue\"]\n\u2705 Feedback: \"Love the new design!\" + allowed_tags: [\"Design\", \"Positive Feedback\", \"UI\"] \u2192 tags: [\"Design\", \"Positive Feedback\"]\n\u2705 Feedback: \"Too expensive for what it offers\" + allowed_tags: [\"Pricing\", \"Value\", \"Feature Request\"] \u2192 tags: [\"Pricing\", \"Value\"]\n\nExamples of when to use AI tags:\n\u274c Feedback: \"Bug in login\" + allowed_tags: [] \u2192 tags: [], ai_tag_1: \"Authentication Bug\", ai_tag_2: \"Login\"\n\u274c Feedback: \"Need dark mode\" + allowed_tags: [\"Pricing\", \"Support\", \"Payment\"] \u2192 tags: [], ai_tag_1: \"Feature Request\", ai_tag_2: \"UI Customization\"\n\nConstraints:\n- **STRONGLY PREFER allowed_tags** - exhaust all matching possibilities first\n- Do **not** invent tags in the `tags` array \u2014 only use exact names from `allowed_tags`\n- Generate creative tags for `ai_tag_1` and `ai_tag_2` ONLY when truly necessary\n- Use ASCII keys exactly as shown. Values must be strings or arrays of strings\n- Do not include reasoning, markdown, or comments \u2014 **JSON array only**"
},
{
"content": "={{ JSON.stringify({\n allowed_tags: $json.tags,\n feedbacks: $json.feedbackBatch\n}) }}"
}
]
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "ac43582f-ba7e-4941-91d1-e48ecb7e1944",
"name": "Update Google Sheet (Tagged)",
"type": "n8n-nodes-base.googleSheets",
"position": [
5760,
1024
],
"parameters": {
"columns": {
"value": {
"Tag 1": "={{ $json.tags[0] || ''}}",
"Tag 2": "={{ $json.tags[1] || ''}}",
"Tag 3": "={{ $json.tags[2] || ''}}",
"Status": "={{ $json.tags && $json.tags.length > 0 ? 'Updated' : 'Needs Review' }}",
"AI Tag 1": "={{ $json.ai_tag_1 }}",
"AI Tag 2": "={{ $json.ai_tag_2 }}",
"Sentiment": "={{ $json.sentiment }}",
"row_number": "={{ $json.row_number }}",
"Primary Emotion": "={{ $json.primary_emotion }}",
"Secondary Emotion": "={{ $json.secondary_emotion }}",
"Updated Date (N8N)": "={{ new Date().toISOString().split('T')[0] }}"
},
"schema": [
{
"id": "Sentiment",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Sentiment",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Feedbacks",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Feedbacks",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Tag 1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Tag 1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Tag 2",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Tag 2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Tag 3",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Tag 3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AI Tag 1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "AI Tag 1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AI Tag 2",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "AI Tag 2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Primary Emotion",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Primary Emotion",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Secondary Emotion",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Secondary Emotion",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Updated Date (N8N)",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Updated Date (N8N)",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"row_number"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "=Feedbacks"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "=GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "1234a97c-f663-454c-abd7-9e64b3098ef4",
"name": "Process Feedbacks in Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
3936,
848
],
"parameters": {
"options": {},
"batchSize": "=10"
},
"typeVersion": 3
},
{
"id": "12824491-a5d8-42ba-b602-5ad577d0108c",
"name": "Aggregate Batch Items",
"type": "n8n-nodes-base.code",
"position": [
4352,
864
],
"parameters": {
"jsCode": "// Aggregate all items in the current batch into a single item\nconst feedbackBatch = $input.all().map((item, index) => ({\n id: index,\n row_number: item.json.row_number,\n text: item.json.Feedbacks\n}));\n\nconst tags = $input.first().json.tags;\n\nreturn {\n json: {\n feedbackBatch,\n tags\n }\n};"
},
"typeVersion": 2
},
{
"id": "54ebf56d-27ec-411d-9973-10a717921e47",
"name": "Split Batch Results",
"type": "n8n-nodes-base.code",
"position": [
5312,
864
],
"parameters": {
"jsCode": "// Parse the OpenAI response and split it back into individual items\nconst response = JSON.parse($input.first().json.message.content);\n\n// Handle both array format and object with results property\nconst results = Array.isArray(response) ? response : response.results || [];\n\nreturn results.map(result => ({\n json: {\n row_number: result.row_number,\n tags: result.tags || [],\n sentiment: result.sentiment || \"\",\n ai_tag_1: result.ai_tag_1 || \"\",\n ai_tag_2: result.ai_tag_2 || \"\",\n primary_emotion: result.primary_emotion || \"\",\n secondary_emotion: result.secondary_emotion || \"\"\n }\n}));"
},
"typeVersion": 2
},
{
"id": "3240b804-444e-42ce-b594-166a7f41db4f",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
16
],
"parameters": {
"width": 768,
"height": 976,
"content": "## \ud83d\udcac **Auto-tag customer feedback in Google Sheets with OpenAI sentiment analysis**\n\nThis workflow automatically tags user feedback stored in Google Sheets using OpenAI with sentiment and emotion analysis. \nIt reads new feedback, analyzes them in **batches** with a single AI call, and returns relevant tags with detailed insights.\n\n---\n\n### \ud83e\udde0 What It Does\n- Fetches **allowed tags** from a Tags Sheet \n- Reads **new feedback** (Status = empty) from a Feedbacks Sheet \n- **Sends entire batches (e.g., 10 items) to OpenAI as a single request** \ud83d\ude80\n- Returns up to **3 most relevant tags** from allowed list (or AI-generated tags as fallback)\n- Analyzes **sentiment** (Very Negative to Very Positive)\n- Detects **emotions** (primary & secondary feelings)\n- Writes all results back to Google Sheets (tags, sentiment, emotions, status, timestamp)\n\n---\n\n### \ud83d\ude80 How to Set Up \n1. Duplicate the provided [Google Sheet template](https://docs.google.com/spreadsheets/d/1y7B3u5vgQLDidf-NdfPgAiBuQxP9Qa7RvdgsTPG14Fs/edit?usp=sharing).\n2. Connect your **Google Sheets** and **OpenAI** credentials in n8n. \n3. Update the Sheet URLs in the **Fetch Allowed Tags**, **Fetch New Feedbacks**, and **Update Google Sheet** nodes. \n4. Run manually with the **Manual Trigger** or enable the **Schedule Trigger** (runs every 60 minutes). \n\n---\n\n### \ud83c\udfa8 How to Customize \n- Adjust the **System Prompt** in the \"Tag Feedbacks with AI\" node to change tagging rules. \n- Edit the **batch size** (default: 10) in the \"Process Feedbacks in Batches\" node for performance optimization. \n- Change the **schedule interval** in the \"Schedule Trigger\" node (default: 60 minutes). \n- Extend the workflow to send results to Notion, Slack, or Airtable for real-time reporting.\n\n---\n\n#### \ud83d\udca1 Example Use Case\nIdeal for product and research teams who collect customer feedback and want to categorize it automatically into clear, actionable topics with sentiment and emotional insights."
},
"typeVersion": 1
},
{
"id": "22e35300-b79f-4b21-b2fb-47ee274141e2",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1600,
832
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 60
}
]
}
},
"typeVersion": 1.2
},
{
"id": "beb9af83-71d0-4cf1-8c33-3d891564d0ba",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2240,
80
],
"parameters": {
"color": 4,
"width": 560,
"height": 352,
"content": "### \ud83c\udff7\ufe0f **Fetch Allowed Tags**\n\nReads the list of available tag names from your **Tags Sheet**. \nEach tag is stored in an array and later passed to OpenAI as `allowed_tags`.\n\n\u2705 Make sure your Tags sheet has a single column named `Tags`."
},
"typeVersion": 1
},
{
"id": "cc4985d4-7dfd-4efb-965c-125f3ed881c9",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2256,
672
],
"parameters": {
"color": 4,
"width": 560,
"height": 656,
"content": "## \ud83d\udcac **Fetch New Feedbacks**\n\nReads feedback entries from **Feedbacks Sheet** where `Status` is empty.\n\n### Expected Columns\n- **Feedbacks:** The feedback text\n- **Status:** Empty = new | \"Updated\" = tagged | \"Needs Review\" = no tags found\n- **Tag 1, Tag 2, Tag 3:** Up to 3 tags from allowed list\n- **AI Tag 1, AI Tag 2:** Fallback tags when no allowed tags match\n- **Sentiment:** Very Negative to Very Positive\n- **Primary Emotion:** Dominant feeling (e.g., frustration, gratitude)\n- **Secondary Emotion:** Optional secondary feeling\n- **Updated Date (N8N):** Processing timestamp\n\n\u2705 All columns must exist with exact names."
},
"typeVersion": 1
},
{
"id": "f91dc3c9-4fc3-4f78-8cc2-f0e4a777d2e5",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
4656,
544
],
"parameters": {
"color": 6,
"width": 448,
"height": 480,
"content": "## \ud83e\udd16 **Tag Feedbacks with OpenAI**\n\nSends entire batch (10 items) as ONE OpenAI request. \ud83d\ude80\n\n**Output per feedback:**\n- Up to 3 tags from allowed_tags (preferred)\n- Up to 2 AI-generated tags (fallback only)\n- Sentiment: Very Negative to Very Positive\n- Primary & secondary emotions\n- Multilingual support (including Persian/Farsi)\n\n\u2705 Returns valid JSON array."
},
"typeVersion": 1
},
{
"id": "a8f0f7a3-2c1a-4e8f-a2f0-295cf7332b24",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
5648,
656
],
"parameters": {
"color": 4,
"width": 336,
"height": 576,
"content": "## \ud83d\udcca **Update Google Sheet (Tagged)**\n\nUpdates **Feedbacks Sheet** with:\n- `Tag 1-3` (from allowed list)\n- `AI Tag 1-2` (fallback tags)\n- `Sentiment`\n- `Primary Emotion` & `Secondary Emotion`\n- `Status` (\"Updated\" or \"Needs Review\")\n- `Updated Date (N8N)`\n\n\u2705 Ensure columns exist with exact names."
},
"typeVersion": 1
},
{
"id": "1a484a39-d4ad-4bb5-8a91-81aea0b218f1",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
3840,
544
],
"parameters": {
"color": 7,
"width": 320,
"height": 480,
"content": "## \ud83d\udd01 **Split In Batches**\n\nBreaks large feedback lists into smaller batches to avoid API rate limits. \nAfter each batch is processed, the loop continues automatically until all rows are tagged.\n\n\ud83d\udca1 Default batch size = 10 (you can adjust in config sheet)."
},
"typeVersion": 1
},
{
"id": "e97af0f1-1446-4c9a-9363-cb2674a1d211",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
3040,
368
],
"parameters": {
"color": 7,
"width": 320,
"height": 512,
"content": "## \ud83d\udd17 **Merge Tags & Feedbacks**\n\nThis node combines two input streams:\n- **Input 1:** Feedback items fetched from the Feedbacks Sheet \n- **Input 2:** Allowed tag list fetched from the Tags Sheet \n\nMode: `Choose Branch` \nOutput: Keeps Feedback data (Input 1) while waiting for Tags (Input 2) to arrive. \nEnsures each feedback item can access the full tag list before analysis."
},
"typeVersion": 1
},
{
"id": "20a6d6be-273c-48db-9a53-6dab6a0d6318",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
3440,
544
],
"parameters": {
"color": 7,
"width": 320,
"height": 336,
"content": "## \ud83e\udde9 **Attach Tags Array**\n\nAdds the list of tags from the Tags Sheet to each feedback item. \nThe result includes a field named `tags`, used by OpenAI for tagging."
},
"typeVersion": 1
},
{
"id": "640e7cd5-b2a8-4b5e-9b38-4b0e6f7f583a",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1488,
80
],
"parameters": {
"color": 7,
"width": 352,
"height": 368,
"content": "## \ud83d\uddb1\ufe0f **Manual Trigger**\n\nRuns the workflow manually when you click **\"Execute Workflow\"** inside n8n. \nUse this for quick testing or when setting up new credentials and connections.\n\n\ud83d\udca1 Best for testing small batches before enabling the automatic schedule."
},
"typeVersion": 1
},
{
"id": "d9ac75a8-f4e1-463b-83ce-2c41519f38c3",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
1488,
656
],
"parameters": {
"color": 7,
"width": 352,
"height": 336,
"content": "## \u23f0 **Schedule Trigger**\n\nRuns every **60 minutes** automatically.\n\nProcesses all feedback where Status = empty/blank."
},
"typeVersion": 1
},
{
"id": "9a24cb7c-fd3b-4e74-ab5c-95457d2658c3",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
6032,
1152
],
"parameters": {
"width": 336,
"height": 80,
"content": "**Created by:** [Parhum Khoshbakht](https://www.linkedin.com/in/parhumm/)\nProduct Manager & Leadership Coach"
},
"typeVersion": 1
},
{
"id": "fe170993-5489-4cbf-9489-bd622ca646a3",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
4224,
544
],
"parameters": {
"color": 7,
"width": 336,
"height": 480,
"content": "## \ud83d\udce6 **Aggregate Batch Items**\n\n**Collects all feedback items in the current batch and combines them into a single item.**\n\nThis allows us to send all 10 feedbacks (or configured batch size) as ONE request to OpenAI instead of 10 separate requests.\n\n\ud83d\udcb0 **Cost savings:** ~90% reduction in API calls!"
},
"typeVersion": 1
},
{
"id": "0ba2d396-07e4-45b5-aebd-7b2b23758630",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
5200,
560
],
"parameters": {
"color": 7,
"width": 336,
"height": 448,
"content": "## \ud83d\udd00 **Split Batch Results**\n\n**Parses the OpenAI response and splits it back into individual feedback items.**\n\nEach item contains:\n- `row_number`: To match with the original Google Sheet row\n- `tags`: Array of tag names (up to 3)\n- `sentiment`: Sentiment classification\n\nThese items are then sent to the Google Sheet update node one by one."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "4213cde2-0655-4e7a-ad52-47b312aacb8c",
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Fetch Allowed Tags",
"type": "main",
"index": 0
},
{
"node": "Fetch New Feedbacks",
"type": "main",
"index": 0
}
]
]
},
"Attach Tags Array": {
"main": [
[
{
"node": "Process Feedbacks in Batches",
"type": "main",
"index": 0
}
]
]
},
"Fetch Allowed Tags": {
"main": [
[
{
"node": "Merge Tags & Feedbacks",
"type": "main",
"index": 1
}
]
]
},
"Fetch New Feedbacks": {
"main": [
[
{
"node": "Merge Tags & Feedbacks",
"type": "main",
"index": 0
}
]
]
},
"Split Batch Results": {
"main": [
[
{
"node": "Update Google Sheet (Tagged)",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Batch Items": {
"main": [
[
{
"node": "Tag Feedbacks with AI",
"type": "main",
"index": 0
}
]
]
},
"Tag Feedbacks with AI": {
"main": [
[
{
"node": "Split Batch Results",
"type": "main",
"index": 0
}
]
]
},
"Merge Tags & Feedbacks": {
"main": [
[
{
"node": "Attach Tags Array",
"type": "main",
"index": 0
}
]
]
},
"Process Feedbacks in Batches": {
"main": [
[],
[
{
"node": "Aggregate Batch Items",
"type": "main",
"index": 0
}
]
]
},
"Update Google Sheet (Tagged)": {
"main": [
[
{
"node": "Process Feedbacks in Batches",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Fetch Allowed Tags",
"type": "main",
"index": 0
},
{
"node": "Fetch New Feedbacks",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
[](https://youtu.be/tbx5rTQqIKs)
Source: https://n8n.io/workflows/9881/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Ask questions like “How much did I spend on food last month?” and get instant answers from your financial data — directly in Telegram.
The Problem That it Solves
This intelligent email automation workflow helps you maximize engagement through domain-based outreach. It utilizes AI-powered personalization and strategic follow-ups to increase response rates. The
Note: Now includes an Apify alternative for Rapid API (Some users can't create new accounts on Rapid API, so I have added an alternative for you. But immediately you are able to get access to Rapid AP
Scrape ads – Pulls Facebook Ad Library data for "ai automation" keywords using Apify Filter & sort – Filters ads by page likes (>1,000) and separates into videos, images, and text ads Analyze creat