This workflow corresponds to n8n.io template #14084 — 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 →
{
"nodes": [
{
"id": "sticky-setup-1",
"name": "\ud83d\udccb WF1 Setup Guide",
"type": "n8n-nodes-base.stickyNote",
"position": [
2816,
1984
],
"parameters": {
"width": 672,
"height": 870,
"content": "## End-to-End Local Business Lead Generation, Enrichment and Outreach Pipeline with Decodo\n\nThis workflow finds local business leads on Google Maps, enriches them with website and AI analysis, and sends personalized cold emails to qualified prospects automatically.\n\n## Who\u2019s it for?\nThis template is for agencies, freelancers, B2B growth teams, and sales operators who want a repeatable outbound lead generation system for local business prospecting.\n\n## How it works\n1. The workflow starts on a schedule and loads the search, scoring, and sender settings from one configuration node.\n2. Decodo scrapes Google Maps search results for businesses that match your niche and city.\n3. The workflow extracts lead details such as business name, address, phone number, website, and rating, then stores each lead in Google Sheets.\n4. Each discovered lead is checked for a website. If no website is available, the lead is marked and skipped from enrichment.\n5. For leads with a website, Decodo scrapes the site and OpenAI scores the business, summarizes it, and suggests enrichment fields such as business type, pain points, and contact email.\n6. The workflow updates the lead in Google Sheets with the enrichment data.\n7. Enriched leads are filtered by score threshold, website presence, email availability, and contact status.\n8. For each qualified lead, the workflow scrapes more website content and uses OpenAI to write a personalized outreach email.\n9. Gmail sends the email, and the lead is marked as contacted in Google Sheets.\n\n## How to set up\nAdd credentials for Decodo, OpenAI, Google Sheets, and Gmail. Replace the placeholder Google Sheet ID in the configuration node. Create a `Leads` sheet with all required columns used in the workflow. Update the niche, city, geo, max leads, score threshold, and sender fields. This template uses the Decodo community node, so it is intended for self-hosted n8n only. Replace the placeholder image above with a real workflow screenshot before submission."
},
"typeVersion": 1
},
{
"id": "410c9e4f-b43b-48da-8a9b-bab5c411fe2e",
"name": "\ud83d\udccd Stage 1: Discovery",
"type": "n8n-nodes-base.stickyNote",
"position": [
3760,
2832
],
"parameters": {
"color": 5,
"width": 1384,
"height": 328,
"content": "## \ud83d\udccd Stage 1: Discovery\n\nScrapes Google Maps for business leads and saves them to Google Sheets with status='New'"
},
"typeVersion": 1
},
{
"id": "d0770492-2b2a-426a-85aa-85534b4cb981",
"name": "Schedule: Daily 10AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
3872,
2944
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 10 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "set-config-1",
"name": "Search Config",
"type": "n8n-nodes-base.set",
"position": [
4096,
2944
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cfg-niche",
"name": "niche",
"type": "string",
"value": "digital marketing agency"
},
{
"id": "cfg-city",
"name": "city",
"type": "string",
"value": "New York"
},
{
"id": "cfg-geo",
"name": "geo",
"type": "string",
"value": "United States"
},
{
"id": "cfg-sheet",
"name": "googleSheetId",
"type": "string",
"value": "YOUR_GOOGLE_SHEET_ID_HERE"
},
{
"id": "cfg-max",
"name": "maxLeads",
"type": "number",
"value": 15
},
{
"id": "cfg-threshold",
"name": "scoreThreshold",
"type": "number",
"value": 6
},
{
"id": "cfg-sender-name",
"name": "senderName",
"type": "string",
"value": "Alex"
},
{
"id": "cfg-sender-company",
"name": "senderCompany",
"type": "string",
"value": "GrowthLab Agency"
},
{
"id": "cfg-sender-offer",
"name": "senderOffer",
"type": "string",
"value": "helping local businesses grow their online presence"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "decodo-maps-1",
"name": "Decodo: Scrape Google Maps",
"type": "@decodo/n8n-nodes-decodo.decodo",
"position": [
4320,
2944
],
"parameters": {
"geo": "={{ $json.geo }}",
"url": "={{ 'https://www.google.com/maps/search/' + encodeURIComponent($json.niche + ' ' + $json.city) }}"
},
"typeVersion": 1
},
{
"id": "code-parse-1",
"name": "Parse Leads from Markdown",
"type": "n8n-nodes-base.code",
"position": [
4544,
2944
],
"parameters": {
"jsCode": "const decodoOut = $input.first().json;\nconst rawContent = decodoOut.markdown || decodoOut.content || decodoOut.body || decodoOut.data || JSON.stringify(decodoOut);\nconst config = $('Search Config').first().json;\nconst niche = config.niche;\nconst city = config.city;\nconst MAX = config.maxLeads || 15;\nconst phoneRx = /\\(?\\d{3}\\)?[\\s.\\-]?\\d{3}[\\s.\\-]?\\d{4}/;\nconst urlRx = /https?:\\/\\/[^\\s)>\"',]+/;\nconst ratingRx = /([0-9]\\.[0-9])\\s*(?:stars?|out of|\\(|\u00b7|rating)/i;\nconst addrWords = ['Ave','Avenue','St','Street','Blvd','Boulevard','Rd','Road','Dr','Drive','Lane','Ln','Way','Court','Ct','Plaza','Pl','Suite','Ste'];\nconst lines = rawContent.split('\\n').map(l => l.replace(/[*#`|]/g,'').trim()).filter(l => l.length > 3);\nconst leads = [];\nlet current = {};\nlet leadCount = 0;\nconst isAddress = (line) => addrWords.some(kw => line.includes(kw)) && /\\d/.test(line);\nconst flush = () => {\n if (current.businessName && (current.phone || current.website || current.address)) {\n leads.push({ json: { id: `lead_${Date.now()}_${leadCount}`, businessName: current.businessName || '', address: current.address || '', phone: current.phone || '', website: current.website || '', rating: current.rating || '', niche, city, status: 'New', aiScore: '', aiSummary: '', email: '', emailSent: 'No', scrapedAt: new Date().toISOString() } });\n leadCount++;\n }\n};\nfor (let i = 0; i < lines.length && leadCount < MAX; i++) {\n const line = lines[i];\n const pm = line.match(phoneRx);\n if (pm && current.businessName && !current.phone) { current.phone = pm[0]; continue; }\n const um = line.match(urlRx);\n if (um && current.businessName) { const u = um[0].replace(/[,.)]+$/,''); if (!u.includes('google') && !u.includes('goo.gl') && !u.includes('maps')) { current.website = u; continue; } }\n const rm = line.match(ratingRx);\n if (rm && current.businessName && !current.rating) { current.rating = parseFloat(rm[1]); continue; }\n if (isAddress(line) && current.businessName && !current.address) { current.address = line; continue; }\n if (/^[A-Z]/.test(line) && line.length >= 5 && line.length <= 75 && !line.includes('http') && !pm) { flush(); current = { businessName: line }; }\n}\nflush();\nif (leads.length === 0) { return [{ json: { error: 'No leads parsed', rawSample: rawContent.substring(0,800), niche, city } }]; }\nreturn leads;"
},
"typeVersion": 2
},
{
"id": "if-valid-lead-1",
"name": "Is Valid Lead?",
"type": "n8n-nodes-base.if",
"position": [
4768,
2944
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-has-name",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.businessName }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "sheets-save-1",
"name": "Save Lead to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
4992,
2944
],
"parameters": {
"columns": {
"value": {
"id": "={{ $json.id }}",
"city": "={{ $json.city }}",
"email": "={{ $json.email }}",
"niche": "={{ $json.niche }}",
"phone": "={{ $json.phone }}",
"rating": "={{ $json.rating }}",
"status": "={{ $json.status }}",
"address": "={{ $json.address }}",
"aiScore": "={{ $json.aiScore }}",
"website": "={{ $json.website }}",
"aiSummary": "={{ $json.aiSummary }}",
"emailSent": "={{ $json.emailSent }}",
"scrapedAt": "={{ $json.scrapedAt }}",
"businessName": "={{ $json.businessName }}"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Leads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Search Config').first().json.googleSheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "e6e50a51-5968-4090-992c-df02378df0c5",
"name": "Split In Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
5216,
2944
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "104b56fb-964f-4a6d-ae7f-7f0e205bcbf7",
"name": "Has Website?",
"type": "n8n-nodes-base.if",
"position": [
5440,
2864
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-website",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.website }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "800e38a5-faa1-41b2-b002-d9a636bbc15d",
"name": "Mark: No Website",
"type": "n8n-nodes-base.set",
"position": [
5664,
2960
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "nw-id",
"name": "id",
"type": "string",
"value": "={{ $json.id }}"
},
{
"id": "nw-status",
"name": "status",
"type": "string",
"value": "No Website"
},
{
"id": "nw-score",
"name": "aiScore",
"type": "number",
"value": 2
},
{
"id": "nw-summary",
"name": "aiSummary",
"type": "string",
"value": "No website found \u2014 lead skipped from AI enrichment."
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b7fbdc15-2f97-4872-8ecb-e707fa1e701f",
"name": "Decodo: Scrape Business Website",
"type": "@decodo/n8n-nodes-decodo.decodo",
"position": [
5664,
2768
],
"parameters": {
"geo": "United States",
"url": "={{ $json.website }}"
},
"typeVersion": 1
},
{
"id": "9b9e015e-6032-4417-9ff5-cfa163d6c8a7",
"name": "Update Lead (No Website)",
"type": "n8n-nodes-base.googleSheets",
"position": [
5888,
2960
],
"parameters": {
"columns": {
"value": {
"id": "={{ $json.id }}",
"status": "={{ $json.status }}",
"aiScore": "={{ $json.aiScore }}",
"aiSummary": "={{ $json.aiSummary }}"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Leads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Search Config').first().json.googleSheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "faec214f-6216-4ce7-a57d-6be36ef319b4",
"name": "Merge Website Content",
"type": "n8n-nodes-base.set",
"position": [
5888,
2768
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "m-id",
"name": "id",
"type": "string",
"value": "={{ $('Split In Batches').item.json.id }}"
},
{
"id": "m-name",
"name": "businessName",
"type": "string",
"value": "={{ $('Split In Batches').item.json.businessName }}"
},
{
"id": "m-website",
"name": "website",
"type": "string",
"value": "={{ $('Split In Batches').item.json.website }}"
},
{
"id": "m-niche",
"name": "niche",
"type": "string",
"value": "={{ $('Split In Batches').item.json.niche }}"
},
{
"id": "m-city",
"name": "city",
"type": "string",
"value": "={{ $('Split In Batches').item.json.city }}"
},
{
"id": "m-content",
"name": "websiteContent",
"type": "string",
"value": "={{ ($json.markdown || $json.content || $json.body || '').substring(0, 3000) }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "17253c4a-3d58-4961-b0a2-19c93e15fb51",
"name": "AI: Score & Enrich Lead",
"type": "n8n-nodes-base.openAi",
"position": [
6112,
2768
],
"parameters": {
"options": {
"maxTokens": 500,
"temperature": 0.2
},
"resource": "chat",
"requestOptions": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "2aecd8b5-884b-4f6a-9551-18d3e05d6732",
"name": "Parse AI Response",
"type": "n8n-nodes-base.code",
"position": [
6336,
2768
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const leadData = $('Split In Batches').item.json;\nconst aiRaw = $json.message?.content || $json.choices?.[0]?.message?.content || $json.content || '';\nlet aiResult = {};\ntry {\n const cleaned = aiRaw.replace(/```json?/gi,'').replace(/```/g,'').trim();\n aiResult = JSON.parse(cleaned);\n} catch(e) {\n aiResult = { aiScore: 5, aiSummary: 'AI parse failed: ' + aiRaw.substring(0,100), employeeCount: 'Unknown', businessType: 'Unknown', techSavviness: 'Unknown', painPoints: '', email: '' };\n}\nreturn { json: { id: leadData.id, businessName: leadData.businessName, address: leadData.address||'', phone: leadData.phone||'', website: leadData.website||'', rating: leadData.rating||'', niche: leadData.niche||'', city: leadData.city||'', status: 'Enriched', aiScore: aiResult.aiScore||'', aiSummary: aiResult.aiSummary||'', employeeCount: aiResult.employeeCount||'', businessType: aiResult.businessType||'', techSavviness: aiResult.techSavviness||'', painPoints: aiResult.painPoints||'', email: aiResult.email||leadData.email||'', emailSent: leadData.emailSent||'No', scrapedAt: leadData.scrapedAt||'' } };"
},
"typeVersion": 2
},
{
"id": "58747d01-57a5-42a2-9200-73dc11624591",
"name": "Update Lead (Enriched)",
"type": "n8n-nodes-base.googleSheets",
"position": [
6560,
2944
],
"parameters": {
"columns": {
"value": {
"id": "={{ $json.id }}",
"email": "={{ $json.email }}",
"status": "={{ $json.status }}",
"aiScore": "={{ $json.aiScore }}",
"aiSummary": "={{ $json.aiSummary }}",
"painPoints": "={{ $json.painPoints }}",
"businessType": "={{ $json.businessType }}",
"employeeCount": "={{ $json.employeeCount }}",
"techSavviness": "={{ $json.techSavviness }}"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Leads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Search Config').first().json.googleSheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "e0b90205-19eb-43cb-b320-6675c889a1ac",
"name": "Get Enriched Leads",
"type": "n8n-nodes-base.googleSheets",
"position": [
5440,
2528
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "Enriched",
"lookupColumn": "status"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Leads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Search Config').first().json.googleSheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 4.7
},
{
"id": "3bd6b600-155b-44e5-a6fb-837925bb7d4f",
"name": "Filter by Score Threshold",
"type": "n8n-nodes-base.code",
"position": [
5664,
2528
],
"parameters": {
"jsCode": "const config = $('Search Config').first().json;\nconst threshold = Number(config.scoreThreshold) || 6;\nconst qualifiedLeads = $input.all().filter(item => {\n const score = Number(item.json.aiScore) || 0;\n const hasEmail = item.json.email && item.json.email.trim().length > 3;\n const hasWebsite = item.json.website && item.json.website.trim().length > 5;\n const notContacted = item.json.emailSent !== 'Yes';\n return score >= threshold && hasEmail && hasWebsite && notContacted;\n});\nif (qualifiedLeads.length === 0) {\n return [{ json: { __noLeads: true, message: `No leads meet threshold: score >= ${threshold} with email` } }];\n}\nreturn qualifiedLeads;"
},
"typeVersion": 2
},
{
"id": "6af19658-76da-43a8-9fa7-982961e4668f",
"name": "Qualified Leads Exist?",
"type": "n8n-nodes-base.if",
"position": [
5888,
2528
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-no-leads",
"operator": {
"type": "boolean",
"operation": "notEquals"
},
"leftValue": "={{ $json.__noLeads }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "16a7ec75-61a4-41c0-99e5-8903b8fc47a8",
"name": "Split In Batches1",
"type": "n8n-nodes-base.splitInBatches",
"position": [
6112,
2528
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "79fae8e6-e9ef-4ed5-bef1-54955a8798f7",
"name": "Decodo: Deep Scrape Website",
"type": "@decodo/n8n-nodes-decodo.decodo",
"position": [
6336,
2272
],
"parameters": {
"geo": "United States",
"url": "={{ $json.website }}"
},
"typeVersion": 1
},
{
"id": "63c70c4d-210b-4afb-80cd-5bcda8abeba5",
"name": "Merge Lead + Content",
"type": "n8n-nodes-base.set",
"position": [
6560,
2272
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "mc-id",
"name": "id",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.id }}"
},
{
"id": "mc-name",
"name": "businessName",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.businessName }}"
},
{
"id": "mc-email",
"name": "recipientEmail",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.email }}"
},
{
"id": "mc-website",
"name": "website",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.website }}"
},
{
"id": "mc-summary",
"name": "aiSummary",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.aiSummary }}"
},
{
"id": "mc-pain",
"name": "painPoints",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.painPoints }}"
},
{
"id": "mc-niche",
"name": "niche",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.niche }}"
},
{
"id": "mc-city",
"name": "city",
"type": "string",
"value": "={{ $('Split In Batches1').item.json.city }}"
},
{
"id": "mc-sender",
"name": "senderName",
"type": "string",
"value": "={{ $('Search Config').first().json.senderName }}"
},
{
"id": "mc-company",
"name": "senderCompany",
"type": "string",
"value": "={{ $('Search Config').first().json.senderCompany }}"
},
{
"id": "mc-offer",
"name": "senderOffer",
"type": "string",
"value": "={{ $('Search Config').first().json.senderOffer }}"
},
{
"id": "mc-content",
"name": "websiteContent",
"type": "string",
"value": "={{ ($json.markdown || $json.content || $json.body || '').substring(0, 3500) }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "155ea4e9-aa18-4623-80a1-7052dfe309fc",
"name": "AI: Write Cold Email",
"type": "n8n-nodes-base.openAi",
"position": [
6784,
2272
],
"parameters": {
"options": {
"maxTokens": 600,
"temperature": 0.7
},
"resource": "chat",
"requestOptions": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "8a1f09c2-dbac-4d60-83a5-9a9df288f7ff",
"name": "Parse Email Content",
"type": "n8n-nodes-base.code",
"position": [
7008,
2272
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const lead = $('Merge Lead + Content').item.json;\nconst aiRaw = $json.message?.content || $json.choices?.[0]?.message?.content || $json.content || '';\nlet emailData = {};\ntry {\n const cleaned = aiRaw.replace(/```json?/gi,'').replace(/```/g,'').trim();\n emailData = JSON.parse(cleaned);\n} catch(e) {\n emailData = {\n emailSubject: `Quick question about ${lead.businessName}`,\n emailBodyHtml: `<p>Hi there,</p><p>I came across ${lead.businessName} and was impressed by what you've built. I specialize in ${lead.senderOffer} and thought there might be a fit.</p><p>Open to a quick 15-minute call?</p><p>Best,<br>${lead.senderName}<br>${lead.senderCompany}</p>`\n };\n}\nif (!emailData.emailSubject || emailData.emailSubject.length < 5) emailData.emailSubject = `Quick question, ${lead.businessName}`;\nif (!emailData.emailBodyHtml || emailData.emailBodyHtml.length < 20) emailData.emailBodyHtml = `<p>Hi there,</p><p>Loved your work at ${lead.businessName}. Would love to connect about ${lead.senderOffer}.</p><p>Worth a quick chat?</p><p>${lead.senderName}</p>`;\nreturn { json: { id: lead.id, businessName: lead.businessName, recipientEmail: lead.recipientEmail, website: lead.website, emailSubject: emailData.emailSubject, emailBodyHtml: emailData.emailBodyHtml, senderName: lead.senderName, senderCompany: lead.senderCompany } };"
},
"typeVersion": 2
},
{
"id": "10e90ee5-e213-4300-9e7d-0f4a75948479",
"name": "Valid Email Address?",
"type": "n8n-nodes-base.if",
"position": [
7232,
2272
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-email",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $json.recipientEmail }}",
"rightValue": "@"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "6f120d78-0ac2-4772-9592-6a6c6e4d2229",
"name": "Gmail: Send Cold Email",
"type": "n8n-nodes-base.gmail",
"position": [
7456,
2192
],
"parameters": {
"sendTo": "={{ $json.recipientEmail }}",
"message": "={{ $json.emailBodyHtml }}",
"options": {},
"subject": "={{ $json.emailSubject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "a28f7f8e-9572-4e1b-9093-0b4372d04bf8",
"name": "Mark: Invalid Email",
"type": "n8n-nodes-base.googleSheets",
"position": [
7456,
2384
],
"parameters": {
"columns": {
"value": {
"id": "={{ $json.id }}",
"status": "No Email"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Leads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Search Config').first().json.googleSheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "5642aa01-efab-40ce-b506-751d613ac5f7",
"name": "Mark as Contacted",
"type": "n8n-nodes-base.googleSheets",
"position": [
7680,
2336
],
"parameters": {
"columns": {
"value": {
"id": "={{ $('Parse Email Content').item.json.id }}",
"status": "Contacted",
"emailSent": "Yes",
"contactedAt": "={{ new Date().toISOString() }}",
"emailSubject": "={{ $('Parse Email Content').item.json.emailSubject }}"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Leads"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Search Config').first().json.googleSheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "92be83cc-542b-47be-be3f-ab298efdbfef",
"name": "\ud83d\udccd Stage 2: Enrichment",
"type": "n8n-nodes-base.stickyNote",
"position": [
5200,
2240
],
"parameters": {
"color": 7,
"width": 1544,
"height": 920,
"content": "## \ud83d\udccd Stage 2: Enrichment\n\nProcesses 'New' leads, scrapes websites, uses AI to score and enrich, updates status='Enriched'"
},
"typeVersion": 1
},
{
"id": "6ee2e8c7-57a1-4450-9602-26360f1af3a3",
"name": "\ud83d\udccd Stage 3: Outreach",
"type": "n8n-nodes-base.stickyNote",
"position": [
6768,
2096
],
"parameters": {
"color": 4,
"width": 1080,
"height": 488,
"content": "## \ud83d\udccd Stage 3: Outreach\n\nFilters enriched leads by score, generates personalized emails with AI, sends via Gmail, marks as 'Contacted'"
},
"typeVersion": 1
}
],
"connections": {
"Has Website?": {
"main": [
[
{
"node": "Decodo: Scrape Business Website",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark: No Website",
"type": "main",
"index": 0
}
]
]
},
"Search Config": {
"main": [
[
{
"node": "Decodo: Scrape Google Maps",
"type": "main",
"index": 0
}
]
]
},
"Is Valid Lead?": {
"main": [
[
{
"node": "Save Lead to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Mark: No Website": {
"main": [
[
{
"node": "Update Lead (No Website)",
"type": "main",
"index": 0
}
]
]
},
"Split In Batches": {
"main": [
[
{
"node": "Get Enriched Leads",
"type": "main",
"index": 0
}
],
[
{
"node": "Has Website?",
"type": "main",
"index": 0
}
]
]
},
"Mark as Contacted": {
"main": [
[
{
"node": "Split In Batches1",
"type": "main",
"index": 0
}
]
]
},
"Parse AI Response": {
"main": [
[
{
"node": "Update Lead (Enriched)",
"type": "main",
"index": 0
}
]
]
},
"Split In Batches1": {
"main": [
[],
[
{
"node": "Decodo: Deep Scrape Website",
"type": "main",
"index": 0
}
]
]
},
"Get Enriched Leads": {
"main": [
[
{
"node": "Filter by Score Threshold",
"type": "main",
"index": 0
}
]
]
},
"Mark: Invalid Email": {
"main": [
[
{
"node": "Split In Batches1",
"type": "main",
"index": 0
}
]
]
},
"Parse Email Content": {
"main": [
[
{
"node": "Valid Email Address?",
"type": "main",
"index": 0
}
]
]
},
"AI: Write Cold Email": {
"main": [
[
{
"node": "Parse Email Content",
"type": "main",
"index": 0
}
]
]
},
"Merge Lead + Content": {
"main": [
[
{
"node": "AI: Write Cold Email",
"type": "main",
"index": 0
}
]
]
},
"Schedule: Daily 10AM": {
"main": [
[
{
"node": "Search Config",
"type": "main",
"index": 0
}
]
]
},
"Valid Email Address?": {
"main": [
[
{
"node": "Gmail: Send Cold Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark: Invalid Email",
"type": "main",
"index": 0
}
]
]
},
"Merge Website Content": {
"main": [
[
{
"node": "AI: Score & Enrich Lead",
"type": "main",
"index": 0
}
]
]
},
"Gmail: Send Cold Email": {
"main": [
[
{
"node": "Mark as Contacted",
"type": "main",
"index": 0
}
]
]
},
"Qualified Leads Exist?": {
"main": [
[
{
"node": "Split In Batches1",
"type": "main",
"index": 0
}
]
]
},
"Update Lead (Enriched)": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"AI: Score & Enrich Lead": {
"main": [
[
{
"node": "Parse AI Response",
"type": "main",
"index": 0
}
]
]
},
"Update Lead (No Website)": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Filter by Score Threshold": {
"main": [
[
{
"node": "Qualified Leads Exist?",
"type": "main",
"index": 0
}
]
]
},
"Parse Leads from Markdown": {
"main": [
[
{
"node": "Is Valid Lead?",
"type": "main",
"index": 0
}
]
]
},
"Decodo: Scrape Google Maps": {
"main": [
[
{
"node": "Parse Leads from Markdown",
"type": "main",
"index": 0
}
]
]
},
"Save Lead to Google Sheets": {
"main": [
[
{
"node": "Split In Batches",
"type": "main",
"index": 0
}
]
]
},
"Decodo: Deep Scrape Website": {
"main": [
[
{
"node": "Merge Lead + Content",
"type": "main",
"index": 0
}
]
]
},
"Decodo: Scrape Business Website": {
"main": [
[
{
"node": "Merge Website Content",
"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.
gmailOAuth2googleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow finds local business leads on Google Maps, enriches them with website and AI analysis, and sends personalized cold emails to qualified prospects automatically.
Source: https://n8n.io/workflows/14084/ — 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.
Personalized Outreach & Follow-Up - Phase 2. Uses googleSheets, openAi, gmail, gmailTrigger. Scheduled trigger; 59 nodes.
This advanced workflow automates brand monitoring and media coverage tracking for musicians, bands, and music labels. The system uses multiple search queries (dorky) to discover mentions across the we
Stop wasting billable hours on manual time-tracking. AutoTimesheet Pro uses AI to collect emails, meetings, and GitHub work, then writes a clean timesheet straight into Google Sheets. Perfect for deve
Imagine a dedicated financial expert tirelessly working behind the scenes, sifting through every transaction, every investment move, and every accounting entry. That's exactly what this automated syst
Who is this for? AI creators, marketers, agencies, and researchers tracking YouTube trends who need weekly high-signal insights without 4+ hours manual research.