This workflow corresponds to n8n.io template #15154 — we link there as the canonical source.
This workflow follows the Gmail → 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 →
{
"id": "W0kPXMdGxU4VwpZf",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Lead Gen Production Full Workflow_production",
"tags": [],
"nodes": [
{
"id": "5b2c9903-e962-4a4c-bab0-77ee4e1fa7e7",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1056,
-464
],
"parameters": {
"width": 480,
"height": 816,
"content": "## AI Lead Gen Production Full Workflow_production\n\n### How it works\n\n1. Receives input from Telegram and builds a query for Google Maps.\n2. Searches Google Maps and processes results with a focus on duplicates and pagination.\n3. Queries additional information using external searches and merges data.\n4. Validates and scores potential leads.\n5. Generates and sends emails with a follow-up process that includes reporting.\n\n### Setup steps\n\n- [ ] Set up Telegram credentials\n- [ ] Configure Google Maps API Key\n- [ ] Provide OpenAI API Key\n- [ ] Set up Google Sheets access for appending\n- [ ] Configure Gmail account for sending emails\n\n### Customization\n\nAdjust the scoring algorithm within the 'Lead Scoring' node to fit specific business requirements."
},
"typeVersion": 1
},
{
"id": "d2d7087b-fdfa-4fcc-8393-b1434f453d6d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
-144
],
"parameters": {
"color": 7,
"width": 416,
"height": 304,
"content": "## Trigger and query building\n\nInitial trigger from Telegram and builds a query for Google Maps API."
},
"typeVersion": 1
},
{
"id": "1a66b4b3-0900-42ed-9863-b652d4d7f4a7",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
-192
],
"parameters": {
"color": 7,
"width": 624,
"height": 464,
"content": "## Google Maps search\n\nHandles search requests to Google Maps including handling pagination and duplicate removal."
},
"typeVersion": 1
},
{
"id": "11aa9c19-825f-4c71-8966-f2b7a7d67a1e",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
-320
],
"parameters": {
"color": 7,
"width": 688,
"height": 672,
"content": "## Information enrichment\n\nPrepares keys and performs external API searches for additional data like emails and LinkedIn profiles."
},
"typeVersion": 1
},
{
"id": "92d23801-3649-437c-a86d-c057b12ebaa8",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1328,
-144
],
"parameters": {
"color": 7,
"width": 592,
"height": 496,
"content": "## Data merging and editing\n\nMerges data from different sources and sets fields for further processing."
},
"typeVersion": 1
},
{
"id": "51c55dcb-a1ad-4df9-8f30-1c4b9dfb014b",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
-464
],
"parameters": {
"color": 7,
"width": 896,
"height": 272,
"content": "## Data cleaning and validation\n\nCleans JSON data, validates contacts and scores leads for further action."
},
"typeVersion": 1
},
{
"id": "84020619-c7c0-443f-b496-dda3d0309668",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
2320,
-240
],
"parameters": {
"color": 7,
"width": 480,
"height": 496,
"content": "## Conditional lead processing\n\nEvaluates lead score and branches for further processing, including sheet appending or email generation."
},
"typeVersion": 1
},
{
"id": "c890d339-a5c1-4661-961e-045d08d6af8c",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
2928,
-80
],
"parameters": {
"color": 7,
"width": 384,
"height": 320,
"content": "## Email sending and waiting\n\nHandles email sending through Gmail and waits for a response period before generating follow-ups."
},
"typeVersion": 1
},
{
"id": "4c1e4f8f-13e1-4578-b932-a32eb5477241",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
3344,
-32
],
"parameters": {
"color": 7,
"width": 768,
"height": 272,
"content": "## Follow-up and report\n\nGenerates and sends follow-up emails, then reports back to Telegram."
},
"typeVersion": 1
},
{
"id": "b3bdcd4d-5f4f-4f8e-b6c2-85767f04df5b",
"name": "Telegram Message Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-448,
-16
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "21e2f865-1fd5-4463-bd9b-bface7537374",
"name": "Build Search Query",
"type": "n8n-nodes-base.function",
"onError": "continueRegularOutput",
"position": [
-224,
-16
],
"parameters": {
"functionCode": "const msg = $json.message;\n\n// 1. Check that this is a text message\nif (!msg?.text) {\n throw new Error('SKIP: not a text message');\n}\n\nconst text = msg.text.trim();\n\n// 2. Check minimum length\nif (text.length < 5) {\n throw new Error('SKIP: message too short');\n}\n\n// 3. Whitelist chat_id \u2014 only you can trigger the agent\nconst ALLOWED_CHAT_IDS = [\n YOUR_TELEGRAM_CHAT_ID // \u2190 replace with your real Telegram chat_id\n];\n\nif (!ALLOWED_CHAT_IDS.includes(msg.chat.id)) {\n throw new Error(`SKIP: unauthorized chat_id ${msg.chat.id}`);\n}\n\n// 4. Stop commands\nconst SKIP_COMMANDS = ['/start', '/help', '/status', '/stop'];\nif (SKIP_COMMANDS.includes(text.toLowerCase())) {\n throw new Error('SKIP: command, not a search query');\n}\n\n// 5. All good \u2014 collect data\nreturn {\n query: text,\n research_query: `${text} official website email linkedin contacts company`,\n chat_id: msg.chat.id,\n triggered_at: new Date().toISOString()\n};"
},
"typeVersion": 1
},
{
"id": "6adbeadf-8a0e-40c5-855a-7d2567b49fca",
"name": "AI Research Agent",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1440,
-352
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "",
"value": "gpt-4o-mini"
},
"options": {
"textFormat": {
"textOptions": {
"type": "json_object"
}
}
},
"simplify": false,
"responses": {
"values": [
{
"content": "=You are a Professional B2B Researcher. \n\n### COMPANY DOSSIER:\nName: {{ $json.company_name }}\nWebsite: {{ $json.website }}\nEmail: {{ $json.email }}\nLinkedIn: {{ $json.linkedin }}\nPhone: {{ $json.phone }}\n\nYOUR TASK:\n1. Identify 3 high-value automation opportunities for this specific business using n8n (e.g., appointment reminders, automated reviews, CRM sync).\n2. Write a personalized, short Ice-breaker in English.\n3. Be concise and professional.\n\nOUTPUT FORMAT (JSON ONLY, no markdown):\n{\n \"company_name\": \"{{ $json.company_name }}\",\n \"industry\": \"\",\n \"email\": \"{{ $json.email }}\",\n \"automation_opportunities\": [\"opt1\", \"opt2\", \"opt3\"],\n \"icebreaker\": \"\"\n}\n"
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "aba2ebde-3f53-4913-8a46-648239ce0390",
"name": "Check Lead Score",
"type": "n8n-nodes-base.if",
"position": [
2368,
-16
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{$json.lead_score}}",
"value2": 55,
"operation": "largerEqual"
}
]
}
},
"typeVersion": 1
},
{
"id": "3d785075-cd5f-48a2-ab6c-b08bbc421384",
"name": "Append Lead to Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
2656,
-112
],
"parameters": {
"columns": {
"value": {
"Date": "={{ $now.format('dd.MM.yyyy') }}",
"Email": "={{ $('Score Lead Data').item.json.email }}",
"Phone": "={{ $('Score Lead Data').item.json.phone }}",
"Company": "={{ $('Score Lead Data').item.json.company_name }}",
"Website": "={{ $('Score Lead Data').item.json.website }}",
"Industry": "={{ $('Score Lead Data').item.json.industry }}",
"Linkedin": "={{ $('Score Lead Data').item.json.linkedin }}",
"Lead Tier": "={{ $json.lead_tier }}",
"Email Sent": "no",
"Icebreaker": "={{ $('Score Lead Data').item.json.icebreaker }}",
"Lead Score": "={{ $('Score Lead Data').item.json.lead_score }}",
"Follow-up Date": "={{ $now.plus(3, 'days').format('dd.MM.yyyy') }}",
"Contact Quality": "={{ $json.contact_quality }}",
"Automation opportunities": "={{ $json.automation_opportunities }}"
},
"schema": [
{
"id": "Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Company",
"type": "string",
"display": true,
"required": false,
"displayName": "Company",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Industry",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Industry",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website",
"type": "string",
"display": true,
"required": false,
"displayName": "Website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Linkedin",
"type": "string",
"display": true,
"required": false,
"displayName": "Linkedin",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Automation opportunities",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Automation opportunities",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Icebreaker",
"type": "string",
"display": true,
"required": false,
"displayName": "Icebreaker",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Contact Quality",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Contact Quality",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lead Score",
"type": "string",
"display": true,
"required": false,
"displayName": "Lead Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lead Tier",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Lead Tier",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Sent",
"type": "string",
"display": true,
"required": false,
"displayName": "Email Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Follow-up Date",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Follow-up Date",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1mtXpSrTtnxWQ_H8Td6P1CicJQVXvhwwAoe2ZB5L42qE/edit#gid=0",
"cachedResultName": "\u041b\u0438\u0441\u04421"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1mtXpSrTtnxWQ_H8Td6P1CicJQVXvhwwAoe2ZB5L42qE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1mtXpSrTtnxWQ_H8Td6P1CicJQVXvhwwAoe2ZB5L42qE/edit?usp=drivesdk",
"cachedResultName": "\u041d\u043e\u0432\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "eca992ba-7413-49e9-9e77-7dc25c912de6",
"name": "Generate Email Content",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
2592,
80
],
"parameters": {
"modelId": "gpt-4o-mini",
"options": {},
"simplify": false,
"responses": {
"values": [
{
"content": "=You are a Senior B2B Outreach Specialist. Write a short, friendly cold email in English.\t\t\t\t\t\n\t\t\t\t\t\n### DATA:\t\t\t\t\t\nRecipient: {{ $json.company_name }}\t\t\t\t\t\nIndustry: {{ $json.industry }}\t\t\t\t\t\nKey Problem/Icebreaker: {{ $json.icebreaker }}\t\t\t\t\t\nProposed Solutions: {{ $json.automation_opportunities.join(', ') }}\t\t\t\t\t\n\t\t\t\t\t\n### GUIDELINES:\t\t\t\t\t\n1. Subject line: Question about {{ $json.industry }} automation for {{ $json.company_name }}\t\t\t\t\t\n2. Hook: Use the Icebreaker content naturally.\t\t\t\t\t\n3. Value: Mention ONE specific idea from the Solutions list (e.g. {{ $json.automation_opportunities[0] }}) and how it saves time.\t\t\t\t\t\n4. CTA: Ask for a brief 10-min chat next Thursday or Friday.\t\t\t\t\t\n5. Tone: Professional, helpful, concise. No \"hope this finds you well\" clich\u00e9s.\t\t\t\t\t\n6. Max 100 words.\t\nOUTPUT FORMAT:\nSUBJECT: Question about {{ $json.industry }} automation for {{ $json.company_name }}\n\n[body of the email]"
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "cf77d0d8-68f7-484f-9b92-e91ee114eeed",
"name": "Send Initial Email",
"type": "n8n-nodes-base.gmail",
"position": [
2976,
80
],
"parameters": {
"message": "={{ $json.output[0].content[0].text.split('\\n').slice(2).join('\\n').trim() }}",
"subject": "={{ $json.output[0].content[0].text.split('\\n')[0].replace('SUBJECT: ', '').trim() }}\n\n",
"additionalFields": {
"toList": [
"YOUR_EMAIL"
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "774ee998-bd05-4067-828b-0eb1832ef6ce",
"name": "Wait 3 Days",
"type": "n8n-nodes-base.wait",
"position": [
3168,
80
],
"parameters": {
"unit": "seconds",
"amount": 10
},
"typeVersion": 1
},
{
"id": "84feb42b-962c-4e6e-9d94-30e4c3c229e3",
"name": "Generate Follow-up Email",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
3392,
80
],
"parameters": {
"modelId": "gpt-4o-mini",
"options": {},
"simplify": false,
"responses": {
"values": [
{
"content": "=Write a very short follow-up email (max 50 words) to {{ $node[\"JSON Cleaner\"].json.company_name }}. \n\nContext: I sent them an email 3 days ago about n8n automation for {{ $node[\"JSON Cleaner\"].json.industry }}.\n\nGuidelines:\n1. Subject: Re: Question about {{ $node[\"JSON Cleaner\"].json.industry }} automation\n2. Message: \"Just checking if you saw my previous email. I'd love to hear your thoughts on those n8n ideas for {{ $node[\"JSON Cleaner\"].json.company_name }} when you have a moment.\"\n3. Tone: Friendly reminder, max 50 words. Language: English.\n"
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "2753ced0-8692-4aa1-9c49-332ee1879e8e",
"name": "Send Follow-up Email",
"type": "n8n-nodes-base.gmail",
"position": [
3744,
80
],
"parameters": {
"message": "={{ $json.output[0].content[0].text }}",
"subject": "=Quick follow-up for {{ $('Score Lead Data').item.json.company_name }}",
"additionalFields": {
"toList": [
"YOUR_EMAIL"
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "3bbbe816-ad57-4153-a39d-359c10b7a223",
"name": "Send Telegram Report",
"type": "n8n-nodes-base.telegram",
"position": [
3968,
80
],
"parameters": {
"text": "=\ud83d\ude80 TARGET ACQUIRED! \ud83c\udfe2 Company: {{ $('Score Lead Data').item.json.company_name }}\n\ud83d\udc8e Industry: {{ $('Score Lead Data').item.json.industry }}\n\ud83d\udcca Score: {{ $('Score Lead Data').item.json.lead_score }}/10\n\ud83d\udcdd Operation status:\n\u2705 Initial email draft created in Gmail\n\u2705 Follow-up scheduled in 3 days\n\u2705 Data saved to Google Sheets\n\ud83d\udd75\ufe0f\u200d\u2642\ufe0f Lead hunt continues...",
"chatId": "={{ $('Build Search Query').item.json.chat_id }}",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "afbe6fee-8eea-4986-94b2-801830e17efb",
"name": "Post to Maps API",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
0,
-16
],
"parameters": {
"url": "https://places.googleapis.com/v1/places:searchText",
"method": "POST",
"options": {},
"jsonBody": "={\n \"textQuery\": \"{{ $json.query }}\",\n \"maxResultCount\": 10\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"headerParameters": {
"parameters": [
{
"name": "X-Goog-FieldMask",
"value": "places.displayName,places.formattedAddress,places.websiteUri,places.nationalPhoneNumber"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpQueryAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "c121d694-2582-4e11-b83f-91e6cdfab6da",
"name": "Split Out Places",
"type": "n8n-nodes-base.splitOut",
"position": [
224,
-64
],
"parameters": {
"options": {},
"fieldToSplitOut": "places"
},
"typeVersion": 1
},
{
"id": "cdb4502f-0f8c-4094-8dfb-ab5fbf55d5ae",
"name": "Clean JSON Data",
"type": "n8n-nodes-base.code",
"position": [
1696,
-352
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const content = $json.output?.[0]?.content?.[0]?.text;\n\nlet data;\nif (typeof content === 'object' && content !== null) {\n data = content;\n} else if (typeof content === 'string') {\n try {\n data = JSON.parse(content.replace(/```json|```/g, '').trim());\n } catch(e) {\n data = {};\n }\n} else {\n data = {};\n}\n\nreturn {\n company_name: data?.company_name || \"Not found\",\n industry: data?.industry || \"Not found\",\n email: data?.email || \"Not found\",\n linkedin: data?.linkedin || \"Not found\",\n phone: $('Set Company Fields').item.json.phone || \"Not found\",\n website: $('Set Company Fields').item.json.website || \"Not found\",\n address: $('Set Company Fields').item.json.address || \"Not found\",\n automation_opportunities: Array.isArray(data?.automation_opportunities)\n ? data.automation_opportunities : [],\n icebreaker: data?.icebreaker || \"Not found\"\n};"
},
"typeVersion": 2
},
{
"id": "cd1d6c56-3a66-44c5-b4cc-3479ee294d08",
"name": "Validate Contact Info",
"type": "n8n-nodes-base.code",
"position": [
1920,
-352
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// In \"Each Item\" mode we work directly with the $json object\nconst data = $json;\nlet quality = 0;\n\n// 1. Check Email: exists, not \"Not found\", and contains @\nif (data.email && data.email !== 'Not found' && data.email.includes('@')) {\n quality += 50;\n}\n\n// 2. Check LinkedIn: profile URL exists and contains linkedin.com\nif (data.linkedin && data.linkedin !== 'Not found' && data.linkedin.includes('linkedin.com')) {\n quality += 50;\n}\n\n// Add contact quality score field (0 to 100)\ndata.contact_quality = quality;\n\nreturn data;"
},
"typeVersion": 2
},
{
"id": "2c1dee34-9be8-4b8a-94a9-e251e3bcb1ad",
"name": "Score Lead Data",
"type": "n8n-nodes-base.code",
"position": [
2144,
-352
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $json;\nlet score = 0;\nconst reasons = [];\n\n// 1. Email (0-40 points) \u2014 most important signal\nif (data.email && data.email !== 'Not found' && data.email.includes('@')) {\n const isPersonal = /gmail|yahoo|hotmail|outlook\\.com/.test(data.email);\n score += isPersonal ? 20 : 40;\n reasons.push(isPersonal ? 'personal email (+20)' : 'corporate email (+40)');\n}\n\n// 2. LinkedIn (0-25 points)\nif (data.linkedin && data.linkedin !== 'Not found' && data.linkedin.includes('linkedin.com')) {\n score += 25;\n reasons.push('linkedin found (+25)');\n}\n\n// 3. Website (0-15 points)\nif (data.website && data.website !== 'Not found') {\n score += 15;\n reasons.push('website found (+15)');\n}\n\n// 4. Phone (0-10 points)\nif (data.phone && data.phone !== 'Not found') {\n score += 10;\n reasons.push('phone found (+10)');\n}\n\n// 5. Icebreaker quality (0-10 points)\nif (data.icebreaker && data.icebreaker !== 'Not found' && data.icebreaker.length > 50) {\n score += 10;\n reasons.push('quality icebreaker (+10)');\n}\n\ndata.lead_score = score;\ndata.score_breakdown = reasons.join(', ');\n\nif (score >= 75) data.lead_tier = \"\ud83d\udd25\ud83d\udd25\ud83d\udd25 HOT\";\nelse if (score >= 55) data.lead_tier = \"\u2b50\u2b50 WARM\";\nelse if (score >= 30) data.lead_tier = \"\ud83c\udf21\ufe0f LUKEWARM\";\nelse data.lead_tier = \"\u2744\ufe0f COLD\";\n\nreturn data;"
},
"typeVersion": 2
},
{
"id": "b716a15a-7f79-4866-8517-2eeaf0fe2410",
"name": "Set Company Fields",
"type": "n8n-nodes-base.set",
"position": [
1776,
-16
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "6958234e-4b15-47e0-8240-ff65add9f169",
"name": "company_name",
"type": "string",
"value": "={{ $json.company_name }}"
},
{
"id": "846ef3c8-8086-4f5e-a58e-72974890caa7",
"name": "website",
"type": "string",
"value": "={{ $json.website }}"
},
{
"id": "3b830113-aa8b-4e57-90b9-d2bba80e4f77",
"name": "email",
"type": "string",
"value": "={{ $json.email }}"
},
{
"id": "31d98380-2ec4-4f83-81da-42f66cd00e42",
"name": "linkedin",
"type": "string",
"value": "={{ $json.linkedin }}"
},
{
"id": "0d05b3d3-5311-4243-8803-3c9c5b7f2429",
"name": "phone",
"type": "string",
"value": "={{ $json.phone }}"
},
{
"id": "0f846d8f-0d16-412e-87d0-9e62c58c7a74",
"name": "address",
"type": "string",
"value": "={{ $json.address }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "158d54c1-68c8-4e45-add2-d6b8832d50b2",
"name": "Post Email Search to API",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
800,
-192
],
"parameters": {
"url": "https://google.serper.dev/search",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $('Deduplicate All Fields').item.json.displayName.text }} {{ $('Deduplicate All Fields').item.json.formattedAddress.split(',').slice(-2).join(',') }} email"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.4
},
{
"id": "f34c14c4-1c64-463c-a09e-75ad41b4d729",
"name": "Post LinkedIn Search to API",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
800,
176
],
"parameters": {
"url": "https://google.serper.dev/search",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $('Deduplicate All Fields').item.json.displayName.text }} {{ $('Deduplicate All Fields').item.json.formattedAddress.split(',').slice(-2).join(',') }} site:linkedin.com\n"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.4
},
{
"id": "5bcca386-440c-47ad-977d-d2a61fa8003b",
"name": "Set Search Keys",
"type": "n8n-nodes-base.set",
"position": [
656,
112
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7c6bcfaa-5c4e-4b8b-9a4c-35d857dc7adf",
"name": "company_key",
"type": "string",
"value": "={{ $json.displayName.text + '_' + ($json.websiteUri || $json.nationalPhoneNumber || 'unknown') }}"
},
{
"id": "73277be5-cb19-42b2-be28-0a37ffc73462",
"name": "company_name",
"type": "string",
"value": "={{ $json.displayName.text }}"
},
{
"id": "005dd716-66cc-4019-9c13-be06b0fc3962",
"name": "website",
"type": "string",
"value": "={{ $json.websiteUri || \"Not found\" }}"
},
{
"id": "a013ac8c-9609-443d-b9f9-9effdf0d95e4",
"name": "phone",
"type": "string",
"value": "={{ $json.nationalPhoneNumber || \"Not found\" }}"
},
{
"id": "f6ba6d3f-f140-422e-a650-2b19dc9e6963",
"name": "address",
"type": "string",
"value": "={{ $json.formattedAddress || \"Not found\" }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f84aa4e9-a114-429f-aa00-596c9d0f1265",
"name": "Set Email Search Results",
"type": "n8n-nodes-base.set",
"position": [
992,
-192
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "182f71d6-1f09-4051-8a7e-57a564ecf284",
"name": "company_key",
"type": "string",
"value": "={{ $('Set Search Keys').item.json.company_key }}"
},
{
"id": "e72a16a7-411e-448d-b6e2-af8c2aff2cdb",
"name": "email",
"type": "string",
"value": "={{ $json.organic?.[0]?.snippet?.match(/[\\w.-]+@[\\w.-]+\\.\\w+/)?.[0] || \"Not found\" }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3401b304-edba-42f1-9c5a-6fefb67edee8",
"name": "Set LinkedIn Results",
"type": "n8n-nodes-base.set",
"position": [
1424,
176
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "15a02e35-f468-4414-b2cc-a9cd9dbe04a0",
"name": "company_key",
"type": "string",
"value": "={{ $('Set Search Keys').item.json.company_key }}"
},
{
"id": "0c267ecd-0e74-4c39-9385-dab7f852e03e",
"name": "linkedin",
"type": "string",
"value": "={{ $json.organic?.[0]?.link || \"Not found\" }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e074c19b-68bc-4f33-84e9-34e28987f809",
"name": "Merge Email and Keys",
"type": "n8n-nodes-base.merge",
"position": [
944,
0
],
"parameters": {
"mode": "combine",
"options": {},
"fieldsToMatchString": "company_key"
},
"typeVersion": 3.2
},
{
"id": "9e00f31e-bd07-43a6-97d0-cc284e4335d6",
"name": "Merge LinkedIn and Email",
"type": "n8n-nodes-base.merge",
"position": [
1632,
-16
],
"parameters": {
"mode": "combine",
"options": {},
"fieldsToMatchString": "company_key"
},
"typeVersion": 3.2
},
{
"id": "bfdacda0-8eaa-42cb-85b6-2667cb9afd5f",
"name": "Check for Next Page",
"type": "n8n-nodes-base.code",
"position": [
224,
96
],
"parameters": {
"jsCode": "const response = $json;\nconst places = response.places || [];\nconst nextPageToken = response.nextPageToken || null;\n\nreturn {\n places: places,\n nextPageToken: nextPageToken,\n hasNextPage: !!nextPageToken\n};"
},
"typeVersion": 2
},
{
"id": "f2d68887-268d-47f8-acc5-6554a9b12429",
"name": "If More Pages Exist",
"type": "n8n-nodes-base.if",
"position": [
384,
96
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "d65934cb-711b-4bfc-9062-d845e532888b",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.hasNextPage }}",
"rightValue": "true"
}
]
},
"looseTypeValidation": true
},
"typeVersion": 2.3
},
{
"id": "5c8c031a-f85e-44b0-bd27-92994498ff33",
"name": "Deduplicate All Fields",
"type": "n8n-nodes-base.removeDuplicates",
"position": [
432,
-64
],
"parameters": {
"options": {},
"operation": "removeItemsSeenInPreviousExecutions",
"dedupeValue": "={{ $json.displayName.text }}"
},
"typeVersion": 2
}
],
"active": true,
"settings": {
"binaryMode": "separate",
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": "k_G8ozcxzLRwhXdpTeqzU",
"timeSavedMode": "fixed",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "978bdbed-7aa4-47ba-9298-5d2e9b2b7dbc",
"connections": {
"Wait 3 Days": {
"main": [
[
{
"node": "Generate Follow-up Email",
"type": "main",
"index": 0
}
]
]
},
"Clean JSON Data": {
"main": [
[
{
"node": "Validate Contact Info",
"type": "main",
"index": 0
}
]
]
},
"Score Lead Data": {
"main": [
[
{
"node": "Check Lead Score",
"type": "main",
"index": 0
}
]
]
},
"Set Search Keys": {
"main": [
[
{
"node": "Post LinkedIn Search to API",
"type": "main",
"index": 0
},
{
"node": "Merge Email and Keys",
"type": "main",
"index": 1
},
{
"node": "Post Email Search to API",
"type": "main",
"index": 0
}
]
]
},
"Check Lead Score": {
"main": [
[
{
"node": "Append Lead to Sheets",
"type": "main",
"index": 0
},
{
"node": "Generate Email Content",
"type": "main",
"index": 0
}
],
[
{
"node": "Append Lead to Sheets",
"type": "main",
"index": 0
}
]
]
},
"Post to Maps API": {
"main": [
[
{
"node": "Check for Next Page",
"type": "main",
"index": 0
},
{
"node": "Split Out Places",
"type": "main",
"index": 0
}
]
]
},
"Split Out Places": {
"main": [
[
{
"node": "Deduplicate All Fields",
"type": "main",
"index": 0
}
]
]
},
"AI Research Agent": {
"main": [
[
{
"node": "Clean JSON Data",
"type": "main",
"index": 0
}
]
]
},
"Build Search Query": {
"main": [
[
{
"node": "Post to Maps API",
"type": "main",
"index": 0
}
]
]
},
"Send Initial Email": {
"main": [
[
{
"node": "Wait 3 Days",
"type": "main",
"index": 0
}
]
]
},
"Set Company Fields": {
"main": [
[
{
"node": "AI Research Agent",
"type": "main",
"index": 0
}
]
]
},
"Check for Next Page": {
"main": [
[
{
"node": "If More Pages Exist",
"type": "main",
"index": 0
}
]
]
},
"If More Pages Exist": {
"main": [
[
{
"node": "Post to Maps API",
"type": "main",
"index": 0
}
],
[]
]
},
"Merge Email and Keys": {
"main": [
[
{
"node": "Merge LinkedIn and Email",
"type": "main",
"index": 0
}
]
]
},
"Send Follow-up Email": {
"main": [
[
{
"node": "Send Telegram Report",
"type": "main",
"index": 0
}
]
]
},
"Set LinkedIn Results": {
"main": [
[
{
"node": "Merge LinkedIn and Email",
"type": "main",
"index": 1
}
]
]
},
"Validate Contact Info": {
"main": [
[
{
"node": "Score Lead Data",
"type": "main",
"index": 0
}
]
]
},
"Deduplicate All Fields": {
"main": [
[
{
"node": "Set Search Keys",
"type": "main",
"index": 0
}
]
]
},
"Generate Email Content": {
"main": [
[
{
"node": "Send Initial Email",
"type": "main",
"index": 0
}
]
]
},
"Generate Follow-up Email": {
"main": [
[
{
"node": "Send Follow-up Email",
"type": "main",
"index": 0
}
]
]
},
"Merge LinkedIn and Email": {
"main": [
[
{
"node": "Set Company Fields",
"type": "main",
"index": 0
}
]
]
},
"Post Email Search to API": {
"main": [
[
{
"node": "Set Email Search Results",
"type": "main",
"index": 0
}
]
]
},
"Set Email Search Results": {
"main": [
[
{
"node": "Merge Email and Keys",
"type": "main",
"index": 0
}
]
]
},
"Telegram Message Trigger": {
"main": [
[
{
"node": "Build Search Query",
"type": "main",
"index": 0
}
]
]
},
"Post LinkedIn Search to API": {
"main": [
[
{
"node": "Set LinkedIn Results",
"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.
gmailOAuth2googleSheetsOAuth2ApihttpHeaderAuthhttpQueryAuthopenAiApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Send a target niche and location via Telegram message Workflow discovers businesses via Google Maps API AI enriches contacts with email and LinkedIn data via Serper GPT-4o scores and qualifies each lead Personalized cold email sent automatically with follow-ups Import the…
Source: https://n8n.io/workflows/15154/ — 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.
💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.
💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.
Ask questions like “How much did I spend on food last month?” and get instant answers from your financial data — directly in Telegram.
> ⚠️ Disclaimer: This workflow uses Community Nodes and must be run on a self-hosted instance of n8n.
Viral Tik Tok Clone Finder. Uses httpRequest, telegramTrigger, openAi, googleSheets. Event-driven trigger; 41 nodes.