This workflow corresponds to n8n.io template #7131 — we link there as the canonical source.
This workflow follows the Agent → Google Sheets 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 →
{
"nodes": [
{
"id": "2c0b215c-a4a7-4262-8c34-9f027656eee7",
"name": "When clicking \u2018Test workflow\u2019",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1056,
752
],
"parameters": {},
"typeVersion": 1
},
{
"id": "1d7bf16c-e641-4fd0-bbb0-c1837280e310",
"name": "Twitter Search by Keyword",
"type": "n8n-nodes-base.httpRequest",
"position": [
32,
912
],
"parameters": {
"url": "https://api.twitterapi.io/twitter/tweet/advanced_search",
"options": {
"redirect": {
"redirect": {
"maxRedirects": 5
}
}
},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $json.keyword }} within_time:4h"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "e4055a63-bce0-4e1e-a574-c51f0361e40e",
"name": "Split tweets",
"type": "n8n-nodes-base.code",
"position": [
240,
912
],
"parameters": {
"jsCode": "const out = [];\nlet passed = 0;\nconst postsCount = $('Code').first().json.postsCount\nconst limit = postsCount && postsCount == 15 ? 2 : 3\nfor (const item of items) {\n\tif (passed >= limit) break;\n\n\tconst tweets = Array.isArray(item.json.tweets) ? item.json.tweets : [];\n\n\tfor (const tweet of tweets) {\n\t\tif (passed >= limit) break;\n\n\t\tout.push({ json: tweet });\n\t\tpassed++;\n\t}\n}\n\nreturn out;"
},
"typeVersion": 2
},
{
"id": "5028b80c-05e3-4e92-b835-be6bd700e993",
"name": "Anthropic Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
432,
1072
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-20250514",
"cachedResultName": "Claude Sonnet 4"
},
"options": {
"thinking": true
}
},
"typeVersion": 1.3
},
{
"id": "59d75362-f229-4b3a-a7c9-127b71a5ca01",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1104,
384
],
"parameters": {
"width": 936,
"height": 292,
"content": "## How to configure the workflow\n- Connect your Google Account to all the Google Spreadsheets nodes (Tutorial: https://www.youtube.com/watch?v=pWGXlZBGu4k)\n- In Google Sheets, create Spreadsheet and select it in 'Document' field in n8n Google Sheets nodes\n- Connect your Twitter account to 'Post on Twitter' node (Tutorial: https://www.youtube.com/watch?v=jxKKwYZQF7Q)\n- Connect your twitterapi.io account to 'Twitter Search by Keyword' node (Tutorial: https://www.youtube.com/watch?v=lEo7IAgj0UY)\n- Connect your Anthropic account (Tutorial: https://www.youtube.com/watch?v=1jl_vBoVvq0)\n- In 'Compose Comment' node, change all the [PLACEHOLDERS] with your company/brand/platform info. That would be used to write a good promotion\n\n## Starting the workflow\nAfter all services are connected - make sure to enter your keyword into 'SET KEYWORD' node and activate the workflow!"
},
"typeVersion": 1
},
{
"id": "f1d0b207-c0bc-4166-8f75-a0500f350532",
"name": "Schedule Trigger (every 4 hours)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1056,
912
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 */4 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "59da790b-ea84-499d-96d7-268d1eae8ba2",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
2048,
928
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineAll"
},
"typeVersion": 3.1
},
{
"id": "ee824981-b9ad-4a9a-8f7a-6a260b52d206",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"position": [
1264,
1008
],
"parameters": {
"unit": "minutes",
"amount": 8
},
"typeVersion": 1.1
},
{
"id": "b9276e2c-91e3-4b5b-bca2-b1890bb764c4",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
848,
1008
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "17bc3f5d-d4d5-4312-9b14-3597325cdce4",
"name": "Code",
"type": "n8n-nodes-base.code",
"position": [
-416,
912
],
"parameters": {
"jsCode": "return [\n {\n json: {\n postsCount: items.length\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "556854ab-18e1-40dd-ab1a-3dcbcc4eefef",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1104,
688
],
"parameters": {
"color": 2,
"width": 1460,
"height": 524,
"content": "## Search twitter posts by keyword\n"
},
"typeVersion": 1
},
{
"id": "cb922ea9-28fd-4d6f-b3f4-aafdd3e8d4bb",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
688
],
"parameters": {
"width": 360,
"height": 524,
"content": "## Generate comments"
},
"typeVersion": 1
},
{
"id": "6fd07700-e18c-456d-90f9-66b720f543bc",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
960
],
"parameters": {
"color": 4,
"width": 680,
"height": 252,
"content": "## Post comments"
},
"typeVersion": 1
},
{
"id": "3e0109da-83dd-474d-8e7f-8bf40606f7f5",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
688
],
"parameters": {
"color": 5,
"width": 1200,
"height": 252,
"content": "## Add post URL and our response to Google Sheets or create a new Google Sheet"
},
"typeVersion": 1
},
{
"id": "033377fd-96f1-44f9-b233-f95f3a6ffba2",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
1984,
688
],
"parameters": {
"color": 6,
"width": 500,
"height": 524,
"content": "## Add post URL and our response to new Google Sheet"
},
"typeVersion": 1
},
{
"id": "217c57d4-ef8a-4bd8-b910-d410481e67c7",
"name": "Merge2",
"type": "n8n-nodes-base.merge",
"position": [
1632,
1008
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.1
},
{
"id": "83734eeb-360c-46f2-af58-2a4adebeb674",
"name": "Automaticaly set todays Date",
"type": "n8n-nodes-base.set",
"position": [
-864,
912
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8f57bd63-358c-4739-963f-0af7acdf8f49",
"name": "date",
"type": "string",
"value": "={{ $now.format('dd-MM-yyyy') }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "22c76bb7-c638-4e0d-99fe-96a90bf045d2",
"name": "Check if there's a Google Sheet for todays Date",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueErrorOutput",
"position": [
-640,
912
],
"parameters": {
"options": {
"dataLocationOnSheet": {
"values": {
"rangeDefinition": "detectAutomatically"
}
}
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "={{ $json.date }}"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.5
},
{
"id": "fdbf65b5-4bb2-42f7-9d98-560db70832b3",
"name": "SET KEYWORD",
"type": "n8n-nodes-base.set",
"position": [
-208,
912
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a2458504-ece3-425b-8338-17a197d7bd07",
"name": "keyword",
"type": "string",
"value": "=ENTER YOU KEYWORD HERE"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "4bd14543-f50b-4c3f-ab96-31e1ed3c2412",
"name": "Compose Comment",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
464,
912
],
"parameters": {
"text": "=You are an experienced social media strategist crafting authentic Twitter responses that naturally introduce [PLATFORM_NAME]. Your goal is to create genuine value while subtly building curiosity about the platform.\nAbout [PLATFORM_NAME]:\n<platform_info>\n[PLATFORM_DESCRIPTION_PLACEHOLDER - INSERT DETAILED DESCRIPTION OF THE PLATFORM, ITS FEATURES, TARGET AUDIENCE, VALUE PROPOSITION, AND KEY BENEFITS HERE]\n</platform_info>\nTwitter Post to Analyze:\n<post>\n{{ $json.text }}\n</post>\nCRITICAL INSTRUCTION: If the post content is empty, missing, unclear, or you cannot determine the context for ANY reason, you MUST still generate a response. Use this fallback response: \"Great post, thanks!\"\nStrategic Approach:\n\nDeep Psychological Analysis:\n\nIdentify the emotional state: Is the user frustrated, excited, curious, or seeking validation?\nSpot the underlying need: What are they really looking for beyond their surface question?\nApply reciprocity principle: Offer genuine value first before any mention\nUse social proof: Reference community experiences when relevant\n\nEngagement Psychology Techniques:\n\nPattern interrupt: Start with an unexpected but relevant insight\nCuriosity gap: Create intrigue without immediately satisfying it\nAuthority positioning: Share insights as someone \"in the know\"\nFear of missing out: Subtle implications of opportunity cost\nBandwagon effect: Reference what \"[TARGET_AUDIENCE_SMART_USERS]\" are doing\n\nResponse Structure (Choose ONE approach):\nOption A - Problem Agitation Solution:\n\nAcknowledge their pain point empathetically\nSlightly amplify the consequence of inaction\nIntroduce [PLATFORM_NAME] as the insider solution\nOption B - Social Proof Story:\nShare a brief, relatable \"I heard about...\" story\nConnect to their situation naturally\nMention [PLATFORM_NAME] as the source/solution\nOption C - Curiosity Hook:\nMake an intriguing observation about their situation\nDrop a hint about \"something most people don't know\"\nCasually reference [PLATFORM_NAME] discovery\n\nAdvanced Twitter Authenticity:\n\nTiming cues: Use phrases like \"just saw this\", \"been noticing\", \"recently discovered\"\nCasual errors: Occasional typos, lowercase starts, informal grammar\nTwitter vernacular: \"ngl\", \"tbh\", \"fr\", \"lowkey\", \"deadass\"\nCommunity insider language: Reference subreddit culture, memes\nVulnerable sharing: Admit small mistakes or learning moments\n\n[PLATFORM_NAME] Integration Strategies:\nStealth mentions:\n\n\"stumbled across [PLATFORM_NAME] while researching...\"\n\"someone mentioned [PLATFORM_NAME] in another thread...\"\n\"been using this thing called [PLATFORM_NAME] to...\"\nValue-first approaches:\n\"before you [RELEVANT_ACTION], maybe check if they're on [PLATFORM_NAME]?\"\n\"[PLATFORM_NAME] has saved me from [RELEVANT_PROBLEM] ngl\"\n\"[TARGET_USERS] with good [PLATFORM_NAME] [RELEVANT_METRICS] are usually worth it\"\nFOMO triggers:\n\"wish I knew about [PLATFORM_NAME] before I [RELEVANT_MISTAKE]...\"\n\"smart [TARGET_AUDIENCE] are using [PLATFORM_NAME] to [KEY_BENEFIT]\"\n\"the [TARGET_USERS] who promote their [PLATFORM_NAME] [RELEVANT_FEATURE] are usually the best\"\n\nConversion Psychology:\n\nScarcity: Imply limited time/opportunity\nAuthority: Position as coming from experience\nCommitment: Get small agreements before big asks\nSocial validation: Reference what others are doing\nFinal Output Requirements:\n1-3 sentences maximum\nNatural Twitter tone with strategic imperfections\nAddress their specific situation authentically\nPlant curiosity seeds about [PLATFORM_NAME]\nInclude ONE psychological trigger naturally\nMake them want to check it out WITHOUT asking directly\nAlways find a way to promote [PLATFORM_NAME]. There is no way you answer with \"[PLATFORM_NOT_RELEVANT_RESPONSE]\" or something similar.\nABSOLUTE RULE: You MUST ALWAYS generate a comment. Never explain that you can't see the post or need more information. If you cannot understand the post or it's empty, immediately output: \"Great post \u2014 thanks for sharing! If you'd like [KEY_VALUE_PROPOSITION], give [PLATFORM_NAME] a look!\"\nRemember: The best marketing doesn't feel like marketing. Your comment should feel like helpful advice from someone who genuinely cares about their success.\nWrite only the comment content - no explanations or meta-text.",
"options": {
"systemMessage": "You are a helpful twitter user that wants to share his good experience in using mentioned platform"
},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "fd836e42-b06e-4193-b06d-cee77ec32817",
"name": "Post on Twitter",
"type": "n8n-nodes-base.twitter",
"onError": "continueRegularOutput",
"maxTries": 2,
"position": [
1040,
1008
],
"parameters": {
"text": "={{ $json.output }}",
"additionalFields": {
"inReplyToStatusId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Split tweets').item.json.id }}"
}
}
},
"retryOnFail": true,
"typeVersion": 2,
"waitBetweenTries": 5000
},
{
"id": "3d6da3a0-2d1a-44a6-8257-37a4ba58af50",
"name": "Add info to the Report Table",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueErrorOutput",
"position": [
1184,
768
],
"parameters": {
"columns": {
"value": {
"Keyword": "={{ $('SET KEYWORD').item.json.keyword }}",
"Post URL": "={{ $('Split tweets').item.json.url }}",
"Our response": "={{ $('Compose Comment').item.json.output }}"
},
"schema": [
{
"id": "Post URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Post URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Our response",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Our response",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Keyword",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Keyword",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "={{ $now.format('dd-MM-yyyy') }}"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.5
},
{
"id": "3086ede8-79e3-4965-ab5f-371cb3c4674f",
"name": "Create new sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1408,
800
],
"parameters": {
"title": "={{ $now.format('dd-MM-yyyy') }}",
"options": {},
"operation": "create",
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.5
},
{
"id": "73f906ac-c96e-4230-bd70-e5b91e7c0bdc",
"name": "Define sheet headers",
"type": "n8n-nodes-base.set",
"position": [
1632,
768
],
"parameters": {
"values": {
"string": [
{
"name": "headers",
"value": "={{ [\n \"Post URL\",\n \"Our response\",\n\"Keyword\"\n] }}"
},
{
"name": "date",
"value": "={{ $now.format('dd-MM-yyyy') }}"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"id": "c31975c8-8667-48ae-90ac-c4d25d07491b",
"name": "Add headers to the Sheet",
"type": "n8n-nodes-base.httpRequest",
"position": [
1840,
768
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $('Define sheet headers').item.json.spreadsheetId }}/values/{{ $json.date }}!A:Z",
"method": "PUT",
"options": {},
"sendBody": true,
"sendQuery": true,
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "range",
"value": "={{ $json.date }}!A:Z"
},
{
"name": "values",
"value": "={{ [$json.headers] }}"
}
]
},
"queryParameters": {
"parameters": [
{
"name": "valueInputOption",
"value": "RAW"
}
]
},
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"typeVersion": 4.1
},
{
"id": "7b915f79-1299-4c33-a521-543bd2b1020d",
"name": "Add info to the Report Table1",
"type": "n8n-nodes-base.googleSheets",
"position": [
2272,
928
],
"parameters": {
"columns": {
"value": {
"Keyword": "={{ $('SET KEYWORD').item.json.keyword }}",
"Post URL": "={{ $('Split tweets').item.json.url }}",
"Our response": "={{ $('Compose Comment').item.json.output }}"
},
"schema": [
{
"id": "Post URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Post URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Our response",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Our response",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Keyword",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Keyword",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "={{ $now.format('dd-MM-yyyy') }}"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.5
}
],
"connections": {
"Code": {
"main": [
[
{
"node": "SET KEYWORD",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Add info to the Report Table1",
"type": "main",
"index": 0
}
]
]
},
"Merge2": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"SET KEYWORD": {
"main": [
[
{
"node": "Twitter Search by Keyword",
"type": "main",
"index": 0
}
]
]
},
"Split tweets": {
"main": [
[
{
"node": "Compose Comment",
"type": "main",
"index": 0
},
{
"node": "Merge2",
"type": "main",
"index": 0
}
]
]
},
"Compose Comment": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Merge2",
"type": "main",
"index": 1
},
{
"node": "Add info to the Report Table",
"type": "main",
"index": 0
}
],
[
{
"node": "Post on Twitter",
"type": "main",
"index": 0
}
]
]
},
"Post on Twitter": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Create new sheet": {
"main": [
[
{
"node": "Define sheet headers",
"type": "main",
"index": 0
}
]
]
},
"Anthropic Chat Model": {
"ai_languageModel": [
[
{
"node": "Compose Comment",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Define sheet headers": {
"main": [
[
{
"node": "Add headers to the Sheet",
"type": "main",
"index": 0
}
]
]
},
"Add headers to the Sheet": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Twitter Search by Keyword": {
"main": [
[
{
"node": "Split tweets",
"type": "main",
"index": 0
}
]
]
},
"Add info to the Report Table": {
"main": [
[],
[
{
"node": "Create new sheet",
"type": "main",
"index": 0
}
]
]
},
"Automaticaly set todays Date": {
"main": [
[
{
"node": "Check if there's a Google Sheet for todays Date",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger (every 4 hours)": {
"main": [
[
{
"node": "Automaticaly set todays Date",
"type": "main",
"index": 0
}
]
]
},
"Check if there's a Google Sheet for todays Date": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
],
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
The workflow is configured to maximize efficiency while minimizing costs and ensuring your Twitter account won't get banned or shadow-banned. Generating more than 17 comments per day would require a paid Twitter subscription plan. The User sets a keyword that would be used to…
Source: https://n8n.io/workflows/7131/ — 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.
This workflow is designed for marketers, content creators, agencies, and solo founders who want to publish long‑form posts with visuals on autopilot using n8n and AI agents.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
SMS Outreach Engine: Service providers. Uses agent, lmChatAnthropic, httpRequest, googleSheets. Event-driven trigger; 60 nodes.
SMS Outreach Engine: Property Managers. Uses agent, lmChatAnthropic, httpRequest, googleSheets. Event-driven trigger; 43 nodes.
This professional n8n workflow provides an end-to-end solution for small restaurants. It includes a Telegram Customer Bot for placing orders and an Automated Notification System that updates customers