This workflow corresponds to n8n.io template #15849 — we link there as the canonical source.
This workflow follows the Chainllm → Gmail 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": "29coyIqym2oyD2M9",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Enterprise AI Outreach Automation",
"tags": [],
"nodes": [
{
"id": "4db22f0d-289f-4d7d-a8d8-0cc15bbc2d2a",
"name": "Scheduler",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
624,
80
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1
},
{
"id": "a17e5401-88f3-49e8-b8e9-8210e6b917b5",
"name": "Read Leads",
"type": "n8n-nodes-base.googleSheets",
"position": [
1776,
80
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Email Sheet"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
"cachedResultName": "AI Outreach Template Sheet"
}
},
"typeVersion": 4
},
{
"id": "f76c8d06-49fe-43bb-a2b1-1b07328d5d01",
"name": "Lead Filter Logic",
"type": "n8n-nodes-base.code",
"position": [
2000,
80
],
"parameters": {
"jsCode": "const blankRows = items.filter(item => {\n const status = String(item.json.Status || '').trim();\n return status === '';\n});\n\nreturn blankRows.slice(0, 1);"
},
"typeVersion": 2
},
{
"id": "40394211-78f8-41e3-8255-5073254a9591",
"name": "Website Scraper",
"type": "n8n-nodes-puppeteer.puppeteer",
"onError": "continueRegularOutput",
"position": [
2224,
80
],
"parameters": {
"url": "={{ $json.Website }}",
"options": {
"browserWSEndpoint": "ws://browserless:3000?token=YOUR_BROWSERLESS_TOKEN"
}
},
"retryOnFail": false,
"typeVersion": 1
},
{
"id": "ac24cab1-8b24-4749-ac2e-ee23581b5641",
"name": "Clean Website Data",
"type": "n8n-nodes-base.code",
"position": [
2496,
80
],
"parameters": {
"jsCode": "const items = $input.all();\n\nfunction decodeHtmlEntities(text) {\n return text\n .replace(/ /gi, ' ')\n .replace(/&/gi, '&')\n .replace(/</gi, '<')\n .replace(/>/gi, '>')\n .replace(/"/gi, '\"')\n .replace(/'/gi, \"'\")\n .replace(/'/gi, \"'\")\n .replace(///gi, \"/\");\n}\n\nfunction cleanHtmlToText(html) {\n if (!html || typeof html !== 'string') return '';\n\n let text = html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, ' ')\n .replace(/<svg[\\s\\S]*?<\\/svg>/gi, ' ')\n .replace(/<iframe[\\s\\S]*?<\\/iframe>/gi, ' ')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<\\/p>/gi, '\\n')\n .replace(/<\\/div>/gi, '\\n')\n .replace(/<\\/section>/gi, '\\n')\n .replace(/<\\/article>/gi, '\\n')\n .replace(/<\\/li>/gi, '\\n')\n .replace(/<\\/h[1-6]>/gi, '\\n')\n .replace(/<[^>]+>/g, ' ');\n\n text = decodeHtmlEntities(text);\n\n text = text\n .replace(/\\b(function|var|const|let|return|async|await|window|document|style|script|sourceURL)\\b/gi, ' ')\n .replace(/\\b(class|id|href|src|width|height|loading|decoding|aria-label|data-[\\w-]+)\\b/gi, ' ')\n .replace(/https?:\\/\\/\\S+/gi, ' ')\n .replace(/[{}[\\];=_<>]+/g, ' ')\n .replace(/\\b[a-zA-Z0-9_-]+\\.(js|css|png|jpg|jpeg|webp|svg|mp4)\\b/gi, ' ')\n .replace(/\\b(elementor|wp-|flaticon|swiper|wow|fa-|wpcf7|marqueeAnimation|translate3d|rotateX|opacity)\\b/gi, ' ')\n .replace(/\\s+\\n/g, '\\n')\n .replace(/\\n\\s+/g, '\\n')\n .replace(/[ \\t]{2,}/g, ' ')\n .replace(/\\n{2,}/g, '\\n\\n')\n .trim();\n\n const lines = text\n .split('\\n')\n .map(line => line.trim())\n .filter(line => line.length > 2)\n .filter(line => !/^(home|about|services|faqs|contact us|linkedin|instagram|facebook|behance)$/i.test(line));\n\n const uniqueLines = [];\n const seen = new Set();\n\n for (const line of lines) {\n const key = line.toLowerCase();\n if (!seen.has(key) && key.length > 2) {\n seen.add(key);\n uniqueLines.push(line);\n }\n }\n\n return uniqueLines.join('\\n');\n}\n\nreturn items.map(item => {\n const html =\n item.json.html ??\n item.json.content ??\n item.json.body ??\n item.json.data ??\n item.json.result ??\n '';\n\n return {\n json: {\n ...item.json,\n cleaned_text: cleanHtmlToText(html)\n }\n };\n});"
},
"typeVersion": 2
},
{
"id": "402d11e7-4e73-4d9c-8fda-6d50bd4b16c0",
"name": "Generate Website Summary",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"onError": "continueRegularOutput",
"position": [
2848,
80
],
"parameters": {
"text": "=You are an elite B2B sales researcher and outbound personalization expert.\n\nYour task is to deeply analyze a company's website content and extract highly actionable outreach intelligence.\n\nAnalyze:\n\n* what the company does\n* who they serve\n* industry\n* positioning\n* services\n* possible pain points\n* growth signals\n* technology maturity\n* marketing maturity\n* automation opportunities\n* weak points in sales/marketing/process\n\nThen create a highly personalized first-line opener for cold email outreach.\n\nIMPORTANT RULES:\n\n* Do NOT sound robotic\n* Do NOT hallucinate fake facts\n* Do NOT invent metrics\n* Use natural business language\n* Keep summaries concise\n* Personalized line should feel human and observant\n* Avoid generic phrases like:\n\n * \u201cI came across your website\u201d\n * \u201cI noticed your company\u201d\n * \u201cHope you're doing well\u201d\n\nWEBSITE CONTENT:\n{{ $json.cleaned_text }}\n\nRETURN STRICT JSON ONLY:\n\n{\n\"company_name\":\"\",\n\"industry\":\"\",\n\"company_summary\":\"\",\n\"target_audience\":\"\",\n\"main_services\":[],\n\"pain_points\":[],\n\"growth_signals\":[],\n\"marketing_maturity\":\"\",\n\"automation_opportunities\":[],\n\"personalized_line\":\"\",\n\"email_angle\":\"\",\n\"confidence_score\":\"\"\n}",
"promptType": "define",
"needsFallback": true
},
"typeVersion": 1.4
},
{
"id": "b4a24e7b-c5fd-4c3f-8af6-f176064efdde",
"name": "Parse Summary",
"type": "n8n-nodes-base.code",
"position": [
3200,
80
],
"parameters": {
"jsCode": "for (const item of items) {\n\n try {\n\n let raw = item.json.text || '{}';\n\n // remove markdown\n raw = raw.replace(/```json/g, '');\n raw = raw.replace(/```/g, '');\n raw = raw.trim();\n\n const parsed = JSON.parse(raw);\n\n item.json['Company Summary'] =\n parsed.company_summary || '';\n\n item.json['Industry'] =\n parsed.industry || '';\n\n item.json['Personalized Line'] =\n parsed.personalized_line || '';\n\n item.json['Pain Points'] =\n JSON.stringify(parsed.pain_points || []);\n\n item.json['Growth Signals'] =\n JSON.stringify(parsed.growth_signals || []);\n\n item.json['Email Angle'] =\n parsed.email_angle || '';\n\n item.json['Confidence Score'] =\n parsed.confidence_score || '';\n\n } catch (error) {\n\n item.json.parse_error = error.message;\n\n item.json.raw_response =\n item.json.text || '';\n\n }\n\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "1c089d0f-ecbe-4d42-af20-225f28046c9a",
"name": "Update Summary",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
3424,
80
],
"parameters": {
"columns": {
"value": {
"Website": "={{ $('Need Website Summary').item.json.Website }}",
"Industry": "={{ $json.Industry }}",
"Email Angle": "={{ $json['Email Angle'] }}",
"Pain Points": "={{ $json['Pain Points'] }}",
"Growth Signals": "={{ $json['Growth Signals'] }}",
"Website summary": "={{ $json['Company Summary'] }}",
"Confidence Score": "={{ $json['Confidence Score'] }}",
"Personalized Line": "={{ $json['Personalized Line'] }}"
},
"schema": [
{
"id": "No",
"type": "string",
"display": true,
"required": false,
"displayName": "No",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "FirstName",
"type": "string",
"display": true,
"required": false,
"displayName": "FirstName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LastName",
"type": "string",
"display": true,
"required": false,
"displayName": "LastName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website summary",
"type": "string",
"display": true,
"required": false,
"displayName": "Website summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Industry",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Industry",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Personalized Line",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Personalized Line",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Pain Points",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Pain Points",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Growth Signals",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Growth Signals",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Angle",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email Angle",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Confidence Score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Confidence Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-1",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject-1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-1",
"type": "string",
"display": true,
"required": false,
"displayName": "Email-1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E1-Send-date&time",
"type": "string",
"display": true,
"required": false,
"displayName": "E1-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-2",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject-2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-2",
"type": "string",
"display": true,
"required": false,
"displayName": "Email-2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E2-Send-date&time",
"type": "string",
"display": true,
"required": false,
"displayName": "E2-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-3",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject-3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-3",
"type": "string",
"display": true,
"required": false,
"displayName": "Email-3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E3-Send-date&time",
"type": "string",
"display": true,
"required": false,
"displayName": "E3-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-4",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject-4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-4",
"type": "string",
"display": true,
"required": false,
"displayName": "Email-4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E4-Send-date&time",
"type": "string",
"display": true,
"required": false,
"displayName": "E4-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-5",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject-5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-5",
"type": "string",
"display": true,
"required": false,
"displayName": "Email-5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E5-Send-date&time",
"type": "string",
"display": true,
"required": false,
"displayName": "E5-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-6",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject-6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-6",
"type": "string",
"display": true,
"required": false,
"displayName": "Email-6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E6-Send-date&time",
"type": "string",
"display": true,
"required": false,
"displayName": "E6-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Note",
"type": "string",
"display": true,
"required": false,
"displayName": "Note",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Website"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Email Sheet"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
"cachedResultName": "AI Outreach Template Sheet"
}
},
"typeVersion": 4
},
{
"id": "a323ef2f-6bbc-408a-bd57-bd5106b40347",
"name": "Mark Done",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
1072,
2704
],
"parameters": {
"columns": {
"value": {
"ID": "={{ $('Gmail Trigger').item.json.id }}",
"Note": "={{ $json.reply_text }}",
"Status": "={{ $json.reply_status }}",
"Thread ID": "={{ $json.threadId }}"
},
"schema": [
{
"id": "ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Thread ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Thread ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "No",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "No",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "FirstName",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "FirstName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LastName",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "LastName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Industry",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Industry",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Personalized Line",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Personalized Line",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Pain Points",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Pain Points",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Growth Signals",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Growth Signals",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Angle",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email Angle",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Confidence Score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Confidence Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Subject-1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E1-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E1-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 1 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 1 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-2",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E2-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E2-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 2 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 2 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-3",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E3-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E3-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 3 sent ",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 3 sent ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-4",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E4-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E4-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 4 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 4 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-5",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E5-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E5-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 5 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 5 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-6",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E6-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E6-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Note",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Note",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Thread ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Email Sheet"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
"cachedResultName": "AI Outreach Template Sheet"
}
},
"typeVersion": 4
},
{
"id": "c7d515f4-8ea4-48ec-9e06-a4ce0b726659",
"name": "Read Services",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
3648,
80
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 563293032,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=563293032",
"cachedResultName": "Our Services"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
"cachedResultName": "AI Outreach Template Sheet"
}
},
"typeVersion": 4
},
{
"id": "6db5420c-839a-42fb-a3a5-aab4af3fde2c",
"name": "Sequence Logic",
"type": "n8n-nodes-base.code",
"position": [
4096,
80
],
"parameters": {
"jsCode": "for (const item of items) {\n\n const current = Number(\n item.json['Sequence Step'] || 0\n );\n\n const stages = [\n 'initial',\n '3_day_followup',\n '5_day_followup',\n '7_day_followup',\n '15_day_followup',\n '30_day_followup'\n ];\n\n item.json.sequence_stage =\n stages[current] || 'completed';\n\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "c4915917-b142-4b0a-8fd0-388a1c61d87e",
"name": "Generate Email",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"onError": "continueRegularOutput",
"position": [
4320,
80
],
"parameters": {
"text": "=You are an elite B2B outbound copywriter specializing in highly personalized cold email sequences that generate replies and booked meetings.\n\nYour job is to generate a complete 6-email outbound sequence.\n\nThe sequence must:\n\n* feel human\n* feel manually written\n* sound intelligent but natural\n* progressively introduce our services\n* create curiosity\n* position us as experts\n* avoid sounding pushy or spammy\n\nThe emails should feel like they are coming from a thoughtful founder or consultant.\n\nNever sound:\n\n* robotic\n* corporate\n* hype-driven\n* desperate\n* AI-generated\n* overly polished\n\n---\n\n## LEAD INFORMATION\n\nFirst Name:\n{{ $('Read all data to make email').item.json.FirstName }}\n\nIndustry:\n{{ $('Read all data to make email').item.json.Industry }}\n\nCompany Summary:\n{{ $('Read all data to make email').item.json['Website summary'] }}\n\nPersonalized Observation:\n{{ $('Read all data to make email').item.json['Personalized Line'] }}\n\nPain Points:\n{{ $('Read all data to make email').item.json['Pain Points'] }}\n\nGrowth Signals:\n{{ $('Read all data to make email').item.json['Growth Signals'] }}\n\nOur Services:\n{{ $('Read Services').item.json.Services }}\n\n---\n\n## CORE OBJECTIVE\n\nThe sequence should naturally connect:\n\n* their business situation\n* their likely operational bottlenecks\n* our relevant services\n* realistic business outcomes\n\nDo NOT randomly mention all services.\n\nInstead:\n\n* intelligently match services to their likely pain points\n* gradually introduce capabilities across the sequence\n* make every email feel context-aware\n\n---\n\n## SEQUENCE STRUCTURE\n\nEMAIL 1:\n\n* personalized opener\n* introduce one relevant opportunity\n* lightly introduce service fit\n* curiosity-based CTA\n\nEMAIL 2:\n\n* focus on operational inefficiency\n* explain one automation/service angle\n* continue naturally from first email\n\nEMAIL 3:\n\n* introduce missed opportunity or scaling bottleneck\n* explain how our service solves it\n* slightly stronger positioning\n\nEMAIL 4:\n\n* focus on time savings, workflow efficiency, or team overload\n* establish expertise naturally\n* mention realistic operational improvements\n\nEMAIL 5:\n\n* ROI / business outcome angle\n* more commercially focused\n* demonstrate practical implementation thinking\n\nEMAIL 6:\n\n* respectful closing email\n* no pressure\n* acknowledge timing may not be right\n* leave door open professionally\n\n---\n\n## FOLLOWUP RULES\n\n* ONLY Email 1 should have a subject line\n* Followups should NOT generate new subjects\n* Followups will be sent as replies in same Gmail thread\n* Every email must feel different\n* Never repeat same structure\n* Never repeat same CTA\n* Never repeat same opening\n* Followups should become shorter over time\n* Final email should be shortest\n\n---\n\n## WRITING RULES\n\n* Use conversational English\n* Write at 6th grade reading level\n* Use short paragraphs\n* Maximum 2 sentences per paragraph\n* Avoid walls of text\n* Keep emails mobile-friendly\n\nDO NOT USE:\n\n* \u201cHope you're doing well\u201d\n* \u201cJust following up\u201d\n* \u201cChecking in\u201d\n* \u201cCircling back\u201d\n* \u201cTouching base\u201d\n* \u201cRevolutionize\u201d\n* \u201cUnlock\u201d\n* \u201cLeverage\u201d\n* \u201cSynergy\u201d\n\nAvoid:\n\n* corporate jargon\n* fake excitement\n* exaggerated promises\n* spam wording\n* marketing fluff\n\n---\n\n## EMAIL FORMAT\n\nEach email must include:\n\nHi {{ $('Read all data to make email').item.json.FirstName }},\n\nand end with:\n\nBest,\nRavi\n\n---\n\n## LENGTH RULES\n\nEmail 1:\n80-120 words\n\nEmail 2-5:\n50-90 words\n\nEmail 6:\n30-60 words\n\n---\n\n## RETURN FORMAT\n\nRETURN RAW JSON ONLY.\n\nDO NOT WRAP IN MARKDOWN.\n\n{\n\"email_1\": {\n\"subject\": \"\",\n\"body\": \"\",\n\"angle_used\": \"\"\n},\n\n\"email_2\": {\n\"body\": \"\",\n\"angle_used\": \"\"\n},\n\n\"email_3\": {\n\"body\": \"\",\n\"angle_used\": \"\"\n},\n\n\"email_4\": {\n\"body\": \"\",\n\"angle_used\": \"\"\n},\n\n\"email_5\": {\n\"body\": \"\",\n\"angle_used\": \"\"\n},\n\n\"email_6\": {\n\"body\": \"\",\n\"angle_used\": \"\"\n}\n}\n",
"promptType": "define",
"needsFallback": true
},
"typeVersion": 1.4
},
{
"id": "eef48d4a-eaa3-4e03-82ca-e02415abf361",
"name": "Parse Email JSON",
"type": "n8n-nodes-base.code",
"position": [
4672,
80
],
"parameters": {
"jsCode": "const DAILY_LIMIT = 40;\n\nfor (const item of items) {\n\n try {\n\n // DAILY LIMIT CHECK\n const sentToday =\n Number(item.json['Sent Count'] || 0);\n\n if (sentToday >= DAILY_LIMIT) {\n\n console.log(\n `Daily limit reached: ${sentToday}`\n );\n\n return [];\n\n }\n\n // TRACKING\n item.json['Daily Limit'] =\n DAILY_LIMIT;\n\n item.json['Today Sent Count'] =\n sentToday;\n\n item.json['Remaining Daily Limit'] =\n DAILY_LIMIT - sentToday;\n\n // RAW AI RESPONSE\n let raw =\n item.json.text || '{}';\n\n // CLEAN MARKDOWN\n raw = raw\n .replace(/```json/g, '')\n .replace(/```/g, '')\n .trim();\n\n // PARSE JSON\n const parsed =\n JSON.parse(raw);\n\n // FIRST NAME\n const firstName =\n item.json.FirstName || 'there';\n\n // EMAIL FORMATTER\n const cleanEmail = (text) => {\n\n if (!text) return '';\n\n // REMOVE GREETINGS\n text = text\n .replace(/^hi\\s.+?,/i, '')\n .replace(/^hello\\s.+?,/i, '')\n .replace(/^hey\\s.+?,/i, '');\n\n // REMOVE SIGNATURES\n text = text\n .replace(/best,\\s*ravi/is, '')\n .replace(/regards,\\s*ravi/is, '');\n\n // CLEAN SPACING\n text = text\n .replace(/\\r/g, '')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n // CLEAN PARAGRAPHS\n const paragraphs =\n text\n .split('\\n\\n')\n .map(p => p.trim())\n .filter(Boolean);\n\n const formatted =\n paragraphs.join('\\n\\n');\n\n // FINAL EMAIL\n return `Hi ${firstName},\n\n${formatted}\n\n\nBest,\nRavi`;\n\n };\n\n // LOOP ALL EMAILS\n for (let i = 1; i <= 6; i++) {\n\n const emailKey =\n `email_${i}`;\n\n item.json[`Subject-${i}`] =\n parsed[emailKey]?.subject || '';\n\n item.json[`Email-${i}`] =\n cleanEmail(\n parsed[emailKey]?.body || ''\n );\n\n item.json[`Angle-${i}`] =\n parsed[emailKey]?.angle_used || '';\n\n }\n\n // SUCCESS STATUS\n item.json['Parse Status'] =\n 'success';\n\n } catch (error) {\n\n item.json['Parse Status'] =\n 'failed';\n\n item.json['Parse Error'] =\n error.message;\n\n item.json['Raw AI Response'] =\n item.json.text || '';\n\n item.json['Status'] =\n 'Failed';\n\n }\n\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "fb9626f3-f6c3-4dd5-8ce0-7b7038e2c572",
"name": "Update Lead",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
6112,
80
],
"parameters": {
"columns": {
"value": {
"ID": "={{ $json.id }}",
"Note": "={{ $json.Note }}",
"Email": "={{ $('Read all data to make email').item.json.Email }}",
"Status": "={{ $json.Status }}",
"Email-1": "={{ $('Parse Email JSON').item.json['Email-1'] }}",
"Email-2": "={{ $('Parse Email JSON').item.json['Email-2'] }}",
"Email-3": "={{ $('Parse Email JSON').item.json['Email-3'] }}",
"Email-4": "={{ $('Parse Email JSON').item.json['Email-4'] }}",
"Email-5": "={{ $('Parse Email JSON').item.json['Email-5'] }}",
"Email-6": "={{ $('Parse Email JSON').item.json['Email-6'] }}",
"Subject-1": "={{ $('Parse Email JSON').item.json['Subject-1'] }}",
"Thread ID": "={{ $json.threadId }}",
"row_number": 0,
"Email 1 Sent": "={{ $json['E1 Status'] }}",
"Email 2 Sent": "={{ $json['E2 Status'] }}",
"Email 4 Sent": "={{ $json['E4 Status'] }}",
"Email 5 Sent": "={{ $json['E5 Status'] }}",
"Email 3 sent ": "={{ $json['E3 Status'] }}",
"E1-Send-date&time": "={{ $json['Last Email Sent'] }}",
"E2-Send-date&time": "={{ $json['Followup 1 Date'] }}",
"E3-Send-date&time": "={{ $json['Followup 2 Date'] }}",
"E4-Send-date&time": "={{ $json['Followup 3 Date'] }}",
"E5-Send-date&time": "={{ $json['Followup 4 Date'] }}",
"E6-Send-date&time": "={{ $json['Followup 5 Date'] }}"
},
"schema": [
{
"id": "ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Thread ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Thread ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "No",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "No",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "FirstName",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "FirstName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LastName",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "LastName",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Industry",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Industry",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Personalized Line",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Personalized Line",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Pain Points",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Pain Points",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Growth Signals",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Growth Signals",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Angle",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email Angle",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Confidence Score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Confidence Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject-1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Subject-1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E1-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E1-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 1 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 1 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-2",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E2-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E2-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 2 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 2 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-3",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E3-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E3-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 3 sent ",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 3 sent ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-4",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E4-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E4-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 4 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 4 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-5",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E5-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E5-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email 5 Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email 5 Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email-6",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email-6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "E6-Send-date&time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "E6-Send-date&time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Note",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Note",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Email"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Email Sheet"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
"cachedResultName": "AI Outreach Template Sheet"
}
},
"typeVersion": 4
},
{
"id": "9a8daefa-5ec3-4857-a27b-4d6b833b7428",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2848,
304
],
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "54d93472-b7e0-4e47-88b1-cade593926e6",
"name": "Google Gemini Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
4336,
304
],
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "eeac1421-4136-4973-b3fa-12cff2fa2a3d",
"name": "Read all data to make email",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
3872,
80
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0",
"cachedResultName": "Email Sheet"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
"cachedResultName": "AI Outreach Template Sheet"
}
},
"typeVersion": 4.7
},
{
"id": "85c2fa4a-75e6-41cd-9e68-d2f0a2389fe5",
"name": "Gmail Trigger",
"type": "n8n-nodes-base.gmailTrigger",
"onError": "continueRegularOutput",
"position": [
544,
2704
],
"parameters": {
"filters": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"typeVersion": 1.4
},
{
"id": "ad27c9d0-2577-4aee-9240-a0b1c22ba473",
"name": "Reply Identifier",
"type": "n8n-nodes-base.code",
"position": [
768,
2704
],
"parameters": {
"jsCode": "const hasReply = !!$json.headers?.[\"in-reply-to\"];\n\nreturn [\n {\n json: {\n email: $json.from || \"\",\n threadId: $json.threadId || \"\",\n reply_status: hasReply ? \"active\" : \"Reply Received\",\n reply_text: $json.textPlain || $json.snippet || \"\",\n date: new Date().toISOString()\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "19d7d387-5001-45ea-8742-d2227cce6b1f",
"name": "Working Hours Protection",
"type": "n8n-nodes-base.code",
"position": [
848,
80
],
"parameters": {
"jsCode": "const now = new Date();\n\nconst hour = now.getHours();\n\nconst day = now.getDay();\n\n// Sunday = 0\n// Monday = 1\n// Friday = 5\n// Saturday = 6\n\nconst isWeekend =\n day === 0 || day === 6;\n\nconst isWorkingHours =\n hour >= 9 && hour < 20;\n\nconsole.log({\n serverTime: now.toISOString(),\n localServerTime: now.toString(),\n hour,\n day,\n isWeekend,\n isWorkingHours\n});\n\nif (isWeekend || !isWorkingHours) {\n\n console.log(\n 'Outside working hours'\n );\n\n return [];\n\n}\n\nreturn items;"
},
"typeVersion": 2
},
{
"id": "b63cbff7-c0d1-4cdc-b619-ca55df97e6fd",
"name": "email tracker",
"type": "n8n-nodes-base.code",
"position": [
5888,
80
],
"parameters": {
"jsCode": "for (const item of items) {\n\n // SERVER CURRENT TIME\n const now = new Date();\n\n // FOLLOWUP DAYS\n const delays = [3, 5, 7, 15, 30];\n\n // CURRENT SEQUENCE STEP\n const currentStep =\n Number(\n item.json['Sequence Step'] || 0\n );\n\n // NEXT EMAIL NUMBER\n const emailNumber =\n currentStep + 1;\n\n // STAGES\n const stages = [\n 'initial',\n '3_day_followup',\n '5_day_followup',\n '7_day_followup',\n '15_day_followup',\n '30_day_followup'\n ];\n\n // ISO FORMATTER\n const formatDate = (date) => {\n\n return new Date(date)\n .toISOString();\n\n };\n\n // CREATE FOLLOWUP DATES\n const followupDates = [];\n\n for (const delay of delays) {\n\n const futureDate =\n new Date(now);\n\n futureDate.setDate(\n futureDate.getDate() + delay\n );\n\n followupDates.push(\n formatDate(futureDate)\n );\n\n }\n\n // NEXT FOLLOWUP DATE\n const nextDelay =\n delays[currentStep] || 30;\n\n const nextDate =\n new Date(now);\n\n nextDate.setDate(\n nextDate.getDate() + nextDelay\n );\n\n // SENT COUNT\n const currentSent =\n Number(\n item.json['Sent Count'] || 0\n );\n\n item.json['Sent Count'] =\n currentSent + 1;\n\n // UPDATE STEP\n item.json['Sequence Step'] =\n emailNumber;\n\n // MAIN TRACKING\n item.json['Last Email Sent'] =\n formatDate(now);\n\n item.json['Next Followup Date'] =\n formatDate(nextDate);\n\n item.json['Last Email Number'] =\n emailNumber;\n\n item.json['Last Email Stage'] =\n stages[currentStep] ||\n 'completed';\n\n item.json['Emails Sent Count'] =\n emailNumber;\n\n // FOLLOWUP DATE TRACKING\n item.json['Followup 1 Date'] =\n followupDates[0];\n\n item.json['Followup 2 Date'] =\n followupDates[1];\n\n item.json['Followup 3 Date'] =\n followupDates[2];\n\n item.json['Followup 4 Date'] =\n followupDates[3];\n\n item.json['Followup 5 Date'] =\n followupDates[4];\n\n // EXISTING SHEET DATE FORMAT\n item.json['E2-Send-date&time'] =\n followupDates[0];\n\n item.json['E3-Send-date&time'] =\n followupDates[1];\n\n item.json['E4-Send-date&time'] =\n followupDates[2];\n\n item.json['E5-Send-date&time'] =\n followupDates[3];\n\n item.json['E6-Send-date&time'] =\n followupDates[4];\n\n // EMAIL STATUS\n item.json['E1 Status'] =\n emailNumber >= 1\n ? 'sent'\n : 'not sent';\n\n item.json['E2 Status'] =\n emailNumber >= 2\n ? 'sent'\n : 'not sent';\n\n item.json['E3 Status'] =\n emailNumber >= 3\n ? 'sent'\n : 'not sent';\n\n item.json['E4 Status'] =\n emailNumber >= 4\n ? 'sent'\n : 'not sent';\n\n item.json['E5 Status'] =\n emailNumber >= 5\n ? 'sent'\n : 'not sent';\n\n item.json['E6 Status'] =\n emailNumber >= 6\n ? 'sent'\n : 'not sent';\n\n // MAIN STATUS\n if (currentStep >= 5) {\n\n item.json['Status'] =\n 'Completed';\n\n item.json['Note'] =\n 'All followups completed';\n\n } else {\n\n item.json['Status'] =\
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.
googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow turns raw leads stored in Google Sheets into personalised cold emails sent via Gmail. It scrapes each company website, uses Gemini to summarise the content and generate tailored messaging, then writes the results back to the sheet before dispatching the emails. Sales teams and founders running regular outbound campaigns save hours of manual research and drafting while keeping every message grounded in real website data.
Use it when you have a steady list of prospects and want consistent personalisation at scale. Skip it for one-off sends or when your leads lack usable websites. Common variations include swapping the cron trigger for a manual start or adding extra qualification rules before the scraping step.
About this workflow
This n8n template demonstrates how to build a complete AI-powered outbound email system using Google Sheets, Gmail, Gemini, and website scraping. The workflow is designed to help you move from basic lead data to personalized cold outreach without manually researching each…
Source: https://n8n.io/workflows/15849/ — 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.
leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.
This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Categories Content Creation AI Automation Publishing Social Media
Automate your lead intake, scoring, and outreach pipeline. This workflow collects leads from forms, enriches and scores them using Relevance AI, routes them by quality, and triggers the right follow-u