This workflow corresponds to n8n.io template #14199 — we link there as the canonical source.
This workflow follows the Google Sheets → OpenAI 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": "otH1aF0ejVvfCAt5",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Email List Personalization - Icebreaker And Subject Line Generator With OpenAI",
"tags": [],
"nodes": [
{
"id": "231d850b-d5b1-4717-99dc-96d91a5ecfaf",
"name": "Rate Limit Delay",
"type": "n8n-nodes-base.wait",
"position": [
2384,
-208
],
"parameters": {
"amount": 1
},
"typeVersion": 1.1,
"alwaysOutputData": false
},
{
"id": "114f3b67-0ad5-4445-a380-29beae9fae3c",
"name": "Write Results to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2160,
-272
],
"parameters": {
"columns": {
"value": {
"row_number": "={{ $('Needs Icebreaker?').item.json.row_number }}",
"icebreakers": "={{ $json.message.content.icebreaker }}"
},
"schema": [
{
"id": "icebreakers",
"type": "string",
"display": true,
"required": false,
"displayName": "icebreakers",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"row_number"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "your-google-sheet-id"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": false,
"typeVersion": 4.5,
"alwaysOutputData": true
},
{
"id": "81607b05-c805-470c-8dc4-b253592d974b",
"name": "Filter Empty Rows",
"type": "n8n-nodes-base.filter",
"position": [
912,
-208
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "filter-empty-icebreaker",
"operator": {
"type": "string",
"operation": "empty",
"singleValue": true
},
"leftValue": "={{ $json.icebreakers }}",
"rightValue": ""
},
{
"id": "1b9a3e6c-ef51-45e4-af52-50a4390aef5b",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.subjectLine }}",
"rightValue": ""
}
]
}
},
"retryOnFail": false,
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "df47db5f-686e-45f1-a7eb-949c8685574a",
"name": "Limit to 200 Leads",
"type": "n8n-nodes-base.limit",
"position": [
1136,
-208
],
"parameters": {
"maxItems": 200
},
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "77ee3852-5a6e-431d-822e-6d954cab755b",
"name": "Read Lead Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
688,
-208
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "your-google-sheet-id"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "c675c220-32dc-4b26-b6df-25ad6f0f2023",
"name": "Process One by One",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1360,
-208
],
"parameters": {
"options": {
"reset": false
}
},
"retryOnFail": false,
"typeVersion": 3,
"alwaysOutputData": true
},
{
"id": "32f41cbd-9d24-4134-8771-58a3285ef318",
"name": "Needs Icebreaker?",
"type": "n8n-nodes-base.if",
"position": [
1584,
-272
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "22b5a816-26b6-42bf-8544-1afc7a78c95a",
"operator": {
"type": "string",
"operation": "isEmpty",
"singleValue": true
},
"leftValue": "={{ $json.icebreakers }}",
"rightValue": ""
},
{
"id": "f9480eb5-c82b-4c20-bec7-f306c82b2fb3",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.subjectLine }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e5a3e768-1d2a-47cf-a4a3-639320297eda",
"name": "Generate Icebreaker",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1808,
-288
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {},
"messages": {
"values": [
{
"role": "system",
"content": "You are a helpful, intelligent writing assistant."
},
{
"content": "Your task is to take, as input, a bunch of information about a prospect, and then generate a customized, one-line email icebreaker to imply that the rest of my communique is personalized.\n\nYou'll return your icebreakers in the following JSON format:\n\n{\"verdict\":\"true or false, string\",\"subjectLine\":\"hey {name}, think I have something for you re: {thingAboutThem}\",\"icebreaker\":\"Hey {firstName}. Love {thing}, also work in {paraphrasedIndustry}. Wanted to run something by you.\", \"shortenedCompanyName\":\"Shortened version of company name (more on this in a moment)\"}\n\nRules:\n- Write in a spartan/laconic tone of voice.\n- Make sure to use the above format when constructing your icebreakers.\n- Sometimes, the data provided will not be of a person. Instead, it will be of a company. If this is the case, return a \"false\" string for \"verdict\"\n- Shorten the company name wherever possible (say, \"XYZ\" instead of \"XYZ Agency\"). More examples: \"Love AMS\" instead of \"Love AMS Professional Services\", \"Love Mayo\" instead of \"Love Mayo Inc.\", \"Love PCG\" instead of \"Pacific Creative Group LLC\", etc.\n- Do the same with locations. \"San Fran\" instead of \"San Francisco\", \"BC\" instead of \"British Columbia\", etc."
},
{
"content": "Aina Rakotoarinaly, CEO founder - Maki Agency / Ti'bouffe, Maki agency, outsourcing/offshoring, Antananarivo, Madagascar"
},
{
"role": "assistant",
"content": "{\"verdict\":\"true\",\"icebreaker\":\"Hey Aina,\\n\\nLove what you're doing at Maki. Also doing some outsourcing right now, wanted to run something by you.\",\"shortenedCompanyName\":\"Maki\"}"
},
{
"content": "Adam Greenwood, Visionary Agency Leader | Digital Strategy & AI | Middle East, UK & Global Markets, the human tech agency, information technology & services, Dubai, United Arab Emirates"
},
{
"role": "assistant",
"content": "{\"verdict\":\"true\",\"icebreaker\":\"Hey Adam,\\n\\nLove what you're doing at the human tech agency (branding in particular is fantastic). Just getting an agency off the ground, wanted to run something by you.\",\"shortenedCompanyName\":\"the human tech agency\"}"
},
{
"content": "=Write an icebreaker and subject line for this lead:\n\nName: {{ $json.first_name }} {{ $json.last_name }}\nTitle: {{ $json.job_title }}\nCompany: {{ $json.company }}\nIndustry: {{ $json.linkedin_industry }}\nLocation: {{ $json.location }}\nEmployees: {{ $json.linkedin_company_employee_count }}\nFounded: {{ $json.linkedin_founded_year }}\nAbout them: {{ $json.summary }}\nAbout the company: {{ $json.linkedin_description }}\nSpecialties: {{ $json.linkedin_specialities }}"
}
]
},
"jsonOutput": true
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "00868a39-6667-44e8-9da1-048b83233df1",
"name": "When clicking 'Execute workflow'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
448,
-208
],
"parameters": {},
"typeVersion": 1
},
{
"id": "5a9fb0d0-fe01-4e38-b094-b769bc07692c",
"name": "Main Description",
"type": "n8n-nodes-base.stickyNote",
"position": [
-160,
-896
],
"parameters": {
"color": "#565936",
"width": 528,
"height": 876,
"content": "## Email List Personalization - Icebreaker & Subject Line Generator\n\nReads an enriched lead list from Google Sheets, generates a personalized icebreaker and subject line for each lead using OpenAI, and writes results back to the same sheet.\n\n### How it works\n\n1. Reads all rows from your enriched lead sheet\n2. Filters to only rows missing an icebreaker or subject line (safe to re-run)\n3. Caps at 200 leads per run, then loops through one by one\n4. OpenAI generates a JSON response with icebreaker, subject line, shortened company name, and a verdict flag\n5. Writes results back to the same row via row_number match\n\n### Setup\n\n- [ ] Connect Google Sheets OAuth2 in both sheet nodes\n- [ ] Set your spreadsheet ID in \"Read Lead Sheet\" and \"Write Results to Sheet\"\n- [ ] Connect your OpenAI API key\n- [ ] Required columns: first_name, last_name, email, job_title, company, linkedin_industry, location, summary, linkedin_description, linkedin_specialities, linkedin_company_employee_count, linkedin_founded_year, icebreakers, subjectLine, row_number\n\n### Customization\n\n- Replace Manual Trigger with Schedule or Google Drive Trigger for automation\n- Adjust the Limit node to match your daily send volume\n- Swap GPT-4.1-mini (~$0.002/lead) for GPT-4o (~$0.01/lead) on premium campaigns\n- Edit the few-shot examples in the OpenAI node to match your voice"
},
"typeVersion": 1
},
{
"id": "c9f6417f-5511-4dc1-ad6c-b9f01ea1ab39",
"name": "Section - Load",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
-384
],
"parameters": {
"color": 4,
"width": 888,
"height": 360,
"content": "### Load leads\nReads the enriched lead sheet, filters to rows missing icebreakers or subject lines, and caps at 200 per run."
},
"typeVersion": 1
},
{
"id": "dc14ec18-a02d-415e-abac-b5c93d4d7817",
"name": "Section - Generate",
"type": "n8n-nodes-base.stickyNote",
"position": [
1296,
-384
],
"parameters": {
"color": 5,
"width": 776,
"height": 360,
"content": "### Generate icebreakers\nLoops through each lead one by one. Checks the row still needs an icebreaker, then calls OpenAI with few-shot examples to produce personalized copy."
},
"typeVersion": 1
},
{
"id": "d074dc09-9b38-4257-a1da-d60725335e6d",
"name": "Section - Save",
"type": "n8n-nodes-base.stickyNote",
"position": [
2112,
-384
],
"parameters": {
"color": 2,
"width": 432,
"height": 360,
"content": "### Save & loop\nWrites the generated icebreaker and subject line back to the same row via row_number match. Waits 1s between calls to avoid API throttling, then loops to the next lead."
},
"typeVersion": 1
},
{
"id": "0a3c0cbb-e401-41a8-92d3-5af3376b36e2",
"name": "Warning",
"type": "n8n-nodes-base.stickyNote",
"position": [
384,
-496
],
"parameters": {
"color": 3,
"width": 336,
"height": 100,
"content": "**Dont forget to** Connect your Google Sheets and OpenAI credentials, and set the correct spreadsheet ID in both sheet nodes before running."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "34b8826f-5f3b-49eb-b12f-446b653ec0b4",
"connections": {
"Read Lead Sheet": {
"main": [
[
{
"node": "Filter Empty Rows",
"type": "main",
"index": 0
}
]
]
},
"Rate Limit Delay": {
"main": [
[
{
"node": "Process One by One",
"type": "main",
"index": 0
}
]
]
},
"Filter Empty Rows": {
"main": [
[
{
"node": "Limit to 200 Leads",
"type": "main",
"index": 0
}
]
]
},
"Needs Icebreaker?": {
"main": [
[
{
"node": "Generate Icebreaker",
"type": "main",
"index": 0
}
]
]
},
"Limit to 200 Leads": {
"main": [
[
{
"node": "Process One by One",
"type": "main",
"index": 0
}
]
]
},
"Process One by One": {
"main": [
[],
[
{
"node": "Needs Icebreaker?",
"type": "main",
"index": 0
}
]
]
},
"Generate Icebreaker": {
"main": [
[
{
"node": "Write Results to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Write Results to Sheet": {
"main": [
[
{
"node": "Rate Limit Delay",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Read Lead Sheet",
"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.
googleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Reads an enriched lead list from Google Sheets, generates a personalized icebreaker + subject line for each lead using OpenAI, and writes results back to the same sheet -- ready for your email sequencer.
Source: https://n8n.io/workflows/14199/ — 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.
Ask questions like “How much did I spend on food last month?” and get instant answers from your financial data — directly in Telegram.
The Problem That it Solves
This intelligent email automation workflow helps you maximize engagement through domain-based outreach. It utilizes AI-powered personalization and strategic follow-ups to increase response rates. The
Note: Now includes an Apify alternative for Rapid API (Some users can't create new accounts on Rapid API, so I have added an alternative for you. But immediately you are able to get access to Rapid AP
Scrape ads – Pulls Facebook Ad Library data for "ai automation" keywords using Apify Filter & sort – Filters ads by page likes (>1,000) and separates into videos, images, and text ads Analyze creat