AutomationFlowsAI & RAG › Generate and Qualify B2b Leads From Telegram with Google Maps, Serper,…

Generate and Qualify B2b Leads From Telegram with Google Maps, Serper,…

Original n8n title: Generate and Qualify B2b Leads From Telegram with Google Maps, Serper, Gpt‑4o, and Gmail

ByYevhenii @neolith2018 on n8n.io

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…

Event trigger★★★★★ complexityAI-powered36 nodesTelegram TriggerOpenAIGoogle SheetsGmailTelegramHTTP Request
AI & RAG Trigger: Event Nodes: 36 Complexity: ★★★★★ AI nodes: yes Added:
Generate and Qualify B2b Leads From Telegram with Google Maps, Serper,… — n8n workflow card showing Telegram Trigger, OpenAI, Google Sheets integration

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 →

Download .json
{
  "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.

Pro

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 →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.

Telegram Trigger, HTTP Request, Google Drive +6
AI & RAG

💥 Automate YouTube thumbnail creation from video links -vide. Uses telegramTrigger, httpRequest, googleDrive, gmail. Event-driven trigger; 25 nodes.

Telegram Trigger, HTTP Request, Google Drive +6
AI & RAG

Ask questions like “How much did I spend on food last month?” and get instant answers from your financial data — directly in Telegram.

Telegram Trigger, OpenAI, Google Sheets +2
AI & RAG

&gt; ⚠️ Disclaimer: This workflow uses Community Nodes and must be run on a self-hosted instance of n8n.

HTTP Request, Telegram Trigger, Telegram +2
AI & RAG

Viral Tik Tok Clone Finder. Uses httpRequest, telegramTrigger, openAi, googleSheets. Event-driven trigger; 41 nodes.

HTTP Request, Telegram Trigger, OpenAI +2