This workflow corresponds to n8n.io template #15153 โ we link there as the canonical source.
This workflow follows the Gmail โ Google Sheets recipe pattern โ see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide โ
{
"id": "i7GeLwsISBo5f98m",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Scrape leads from businesses with Claude and Apify to Gmail outreach - vide",
"tags": [],
"nodes": [
{
"id": "1b227368-1b6b-433e-807f-4c9f8e04e408",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-432,
-16
],
"parameters": {
"path": "1371918c-dcdd-4286-a02e-422a5ec37668",
"options": {}
},
"typeVersion": 2.1
},
{
"id": "89f93c2a-88e3-4bd5-9983-a45709d02aa9",
"name": "Split Out",
"type": "n8n-nodes-base.splitOut",
"position": [
-224,
-16
],
"parameters": {
"options": {},
"fieldToSplitOut": "body.restaurants"
},
"typeVersion": 1
},
{
"id": "6766d9bf-2c9f-4e99-b56c-842f3bed9f0c",
"name": "Outreach email copywriter",
"type": "@n8n/n8n-nodes-langchain.anthropic",
"position": [
480,
-32
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-6",
"cachedResultName": "claude-sonnet-4-6"
},
"options": {},
"messages": {
"values": [
{
"content": "=You are an outreach email copywriter for Dr. Firas, who provides AI automation and SEO services to businesses.\n\nWrite a short, personalized cold outreach email using the following information:\n\nBusiness Name: {{ $json['Business Name'] }}\nBusiness Description: {{ $json['Business Description'] || 'No description available' }}\nContact Status: {{ $json['Contact Status'] }} (This indicates whether the business already has an online booking system)\nInstructions\nIf the business already has an online booking system, propose SEO services to help improve their visibility, attract more customers, and increase bookings.\nIf the business does not have an online booking system, propose helping them implement an online booking systwem on their website.\nRules\nStart with a personalized opening referencing something specific from the Business Description\nKeep the email under 100 words\nUse a friendly, conversational tone (not overly salesy)\nEnd with a soft call to action (e.g., quick chat, short call, etc.)\nSign off as Dr. FIRAS\nDo not use generic phrases like \"I hope this email finds you well\"\nResponse Format\nRespond in exactly this format:\n\n|||SUBJECT|||\n[your subject line here]\n\n|||BODY|||\n[your email body here]"
}
]
}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "3ff53079-5278-4bf6-a873-b901cac2f3dd",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
192,
-16
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d1751c89-da47-4545-bf12-0b2fe1c98706",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json['Email Address'] }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "1260e0ad-2807-441e-b62e-c6198fc89eb2",
"name": "Send email to Leads",
"type": "n8n-nodes-base.gmail",
"onError": "continueRegularOutput",
"position": [
1040,
-32
],
"parameters": {
"sendTo": "={{ $('Append Leads in sheet').item.json['Email Address'] }}",
"message": "={{ $json.body }}",
"options": {},
"subject": "={{ $json.subject }}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "2d6e813d-a483-4d72-85c9-ec5481fbd4f7",
"name": "Split Email Text",
"type": "n8n-nodes-base.code",
"position": [
832,
-32
],
"parameters": {
"jsCode": "const items = $input.all();\n\nreturn items.map((item) => {\n \n // Get the full generated text\n const fullText = item.json.content[0].text;\n\n // Extract Subject\n const subject = fullText\n .split('|||SUBJECT|||')[1]\n .split('|||BODY|||')[0]\n .trim();\n\n // Extract Body\n const body = fullText\n .split('|||BODY|||')[1]\n .trim();\n\n // Return structured output\n return {\n json: {\n ...item.json,\n subject: subject,\n body: body\n }\n };\n});"
},
"typeVersion": 2
},
{
"id": "4599ec8b-95d6-4ae9-9f28-cc4153d7a268",
"name": "Append Leads in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-16,
-16
],
"parameters": {
"columns": {
"value": {
"City Name": "={{ $json.city_name }}",
"Website URL": "={{ $json.website_url }}",
"Phone Number": "={{ ($json.phone_number || '').replace(/\\D/g, '') }}",
"Business Name": "={{ $json.business_name }}",
"Email Address": "={{ $json.email_address }}",
"Contact Status": "={{ $json.contact_status }}",
"Region / State": "={{ $json.region_state }}",
"Street Address": "={{ $json.street_address }}",
"Customer Rating": "={{ $json.customer_rating }}",
"Business Category": "={{ $json.business_category }}",
"Business Description": "={{ $json.business_description }}",
"Data Collection Date": "={{ $json.collection_date }}"
},
"schema": [
{
"id": "Data Collection Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Data Collection Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Business Category",
"type": "string",
"display": true,
"required": false,
"displayName": "Business Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Region / State",
"type": "string",
"display": true,
"required": false,
"displayName": "Region / State",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "City Name",
"type": "string",
"display": true,
"required": false,
"displayName": "City Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Street Address",
"type": "string",
"display": true,
"required": false,
"displayName": "Street Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Business Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Business Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Business Description",
"type": "string",
"display": true,
"required": false,
"displayName": "Business Description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website URL",
"type": "string",
"display": true,
"required": false,
"displayName": "Website URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone Number",
"type": "string",
"display": true,
"required": false,
"displayName": "Phone Number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Rating",
"type": "string",
"display": true,
"required": false,
"displayName": "Customer Rating",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Address",
"type": "string",
"display": true,
"required": false,
"displayName": "Email Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Facebook Page",
"type": "string",
"display": true,
"required": false,
"displayName": "Facebook Page",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Instagram Profile",
"type": "string",
"display": true,
"required": false,
"displayName": "Instagram Profile",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Contact Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Contact Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Etat prospection",
"type": "string",
"display": true,
"required": false,
"displayName": "Etat prospection",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=YOUR_ID-sheet_GOOLE_SHEETS"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "=YOUR_ID_GOOLE_SHEETS"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "347e11ff-4f67-4e6c-9349-658c0f6683e4",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
-272
],
"parameters": {
"width": 704,
"height": 1120,
"content": "# Search Leads & Send Emails Automatically\n\n@[youtube](n84VK5rp39g)\n\n## Resources\n- Video Tutorial: https://youtu.be/n84VK5rp39g\n- Copy Google Sheets Template: https://docs.google.com/spreadsheets/u/2/d/1P8NTzIk7g2ng10OhtYIQscI2Qc87qqy2uM1u6eiSVko/copy\n- Full Documentation: https://automatisation.notion.site/Claude-Cowork-n8n-3423d6550fd98049a8c1eda298bbeb04?pvs=143\n\n## Use Case\nThis workflow helps automate lead generation and cold outreach.\n\nClaude Co-Work uses [Apify](https://www.apify.com/?fpr=udemy) to scrape business leads (emails, websites, phones, booking status), then automatically sends the data to n8n.\n\nn8n stores leads in Google Sheets, generates personalized outreach emails, and sends them automatically with Gmail.\n\n## Setup\n1. Connect Claude account \n2. Connect Gmail account \n3. Connect Google Sheets account \n4. Create an [Apify](https://www.apify.com/?fpr=udemy) account \n5. Add your Google Sheet IDs \n6. Run Claude Co-Work to trigger the webhook automatically"
},
"typeVersion": 1
},
{
"id": "aa8ebe4d-4367-4bbe-be6e-72b62e75e91c",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-448,
-176
],
"parameters": {
"color": 7,
"width": 592,
"height": 448,
"content": "# 1 - Lead Intake & Storage\n\nReceives scraped leads from Claude Co-Work via webhook, splits each lead into separate records, then saves all business data into Google Sheets."
},
"typeVersion": 1
},
{
"id": "0580af51-366c-4ce3-9be5-1233e3967503",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
416,
-176
],
"parameters": {
"color": 7,
"width": 832,
"height": 448,
"content": "# 2 - AI Outreach & Email Sending\n\nGenerates personalized cold emails with Claude AI, extracts subject/body automatically, then sends outreach emails through Gmail."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"callerPolicy": "workflowsFromSameOwner",
"timeSavedMode": "fixed",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "95e5281d-ebaa-4531-9276-d2e68cb8c3f5",
"connections": {
"If": {
"main": [
[
{
"node": "Outreach email copywriter",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Split Out": {
"main": [
[
{
"node": "Append Leads in sheet",
"type": "main",
"index": 0
}
]
]
},
"Split Email Text": {
"main": [
[
{
"node": "Send email to Leads",
"type": "main",
"index": 0
}
]
]
},
"Append Leads in sheet": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"Outreach email copywriter": {
"main": [
[
{
"node": "Split Email Text",
"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.
anthropicApigmailOAuth2googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
๐ Documentation: Notion Guide
Source: https://n8n.io/workflows/15153/ โ original creator credit. Request a take-down โ
More Email & Gmail workflows โ ยท Browse all categories โ
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automates personalized email outreach to a list of hospitals. It uses a chat-based interface to accept a region and a list of hospital names, looks up their specific contact details from
This workflow is a powerful, two-phase system designed to automate the entire passive candidate sourcing and engagement cycle.
Every weekday morning, the workflow reads your prospect list from Google Sheets and cross-checks it against a send log โ anyone already emailed is automatically skipped Each new contact is assigned on
How It Works Starts with a Manual Trigger Reads lead list from Google Sheet Filter rows where email wasnโt sent Generate personalized email body (AI) Generate email subject line (AI) Merge AI outputs
Discord Hunter. Uses formTrigger, googleSheets, gmail, discord. Event-driven trigger; 12 nodes.