Google Sheets + Apify: cold email icebreakers written
Your cold emails aren’t failing because your offer is bad. They fail because the “personalization” is shallow, rushed, and frankly looks automated (even when you did the work manually).
This Apify icebreakers setup hits agency owners hardest, but outbound SDRs and consultants running their own pipeline feel it too. The outcome is simple: multi-line icebreakers in Google Sheets that actually sound researched, so you can send fewer emails and still book more replies.
Below is the workflow, what it replaces, and how it turns a list of Apollo searches into ready-to-send openers without you living in a browser tab jungle.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Google Sheets + Apify: cold email icebreakers written
flowchart LR
subgraph sg0["When clicking ‘Test workflow’ Flow"]
direction LR
n0@{ icon: "mdi:cog", form: "rounded", label: "Remove Duplicate URLs", pos: "b", h: 48 }
n1@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking ‘Test workflow’", pos: "b", h: 48 }
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/html.dark.svg' width='40' height='40' /></div><br/>HTML"]
n3@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter", pos: "b", h: 48 }
n5["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Request web page for URL"]
n6["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/markdown.dark.svg' width='40' height='40' /></div><br/>Markdown"]
n7@{ icon: "mdi:robot", form: "rounded", label: "Summarize Website Page", pos: "b", h: 48 }
n8@{ icon: "mdi:cog", form: "rounded", label: "Limit", pos: "b", h: 48 }
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Scrape Home"]
n10@{ icon: "mdi:cog", form: "rounded", label: "Aggregate", pos: "b", h: 48 }
n11@{ icon: "mdi:robot", form: "rounded", label: "Generate Multiline Icebreaker", pos: "b", h: 48 }
n12@{ icon: "mdi:database", form: "rounded", label: "Add Row", pos: "b", h: 48 }
n13["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Call Apify Scraper"]
n14@{ icon: "mdi:database", form: "rounded", label: "Get Search URL", pos: "b", h: 48 }
n15@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields", pos: "b", h: 48 }
n16@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Only Websites & Emails", pos: "b", h: 48 }
n17@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n18["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code"]
n18 --> n0
n2 --> n15
n8 --> n5
n4 --> n18
n12 --> n17
n6 --> n7
n10 --> n11
n3 --> n4
n15 --> n17
n9 --> n2
n14 --> n13
n17 --> n3
n13 --> n16
n0 --> n8
n16 --> n9
n7 --> n10
n5 --> n6
n11 --> n12
n1 --> n14
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n1 trigger
class n7,n11 ai
class n4,n16 decision
class n12,n14 database
class n5,n9,n13 api
class n18 code
classDef customIcon fill:none,stroke:none
class n2,n5,n6,n9,n13,n18 customIcon
The Challenge: Personalization That Doesn’t Scale
Good cold email personalization takes real research. You click the site, skim the homepage, hunt for “About,” scan services, look for proof points, then try to compress all of that into two lines that don’t sound like a template. Do that 30 times and your brain turns to mush. Do it 300 times and it becomes impossible to keep quality consistent. The worst part is the hidden cost: you spend your best energy on repetitive digging, not on messaging, offer, or follow-up strategy.
It adds up fast. Here’s where it usually breaks down in the real world.
- Research turns into tab hoarding, and you still miss the interesting details buried on internal pages.
- You write “Loved your website” style openers because you’re out of time, so replies look like standard campaigns (1–2% on a good day).
- Copy-pasting leads into a sheet causes mismatched fields, duplicate rows, and the occasional email sent to the wrong person.
- Scaling means hiring help for manual research, which creates training overhead and wildly inconsistent quality.
The Fix: Deep Website Research → Icebreakers in Sheets
This workflow starts with Apollo search URLs stored in Google Sheets, pulls matching leads through Apify, and filters out low-quality rows (no email, no accessible website, junk results). Then it does what you would do manually, but with more stamina: it grabs the prospect’s homepage HTML, extracts internal links, cleans and normalizes those URLs, and visits a limited set of pages so it doesn’t hammer the site. Each page is converted into readable markdown, summarized with OpenAI, and combined into a single “prospect profile.” Finally, the workflow uses a more structured prompt to write a multi-line cold email icebreaker that references specific, non-obvious details. The finished opener lands back in your Google Sheets “Leads” tab next to the contact record.
The workflow begins when you run it in n8n and it reads the “Search URLs” sheet. Apify returns lead data, then the website gets scraped and summarized page by page. After the summaries are merged, OpenAI generates the final multiline_icebreaker and n8n appends it to your sheet.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you’re prepping 100 leads for an outbound campaign. Manually, you might spend about 10 minutes per lead researching the site and writing a decent opener, which is roughly 16 hours. With this workflow, you drop an Apollo search URL into Google Sheets, run n8n, and let it process in batches. Even if scraping and AI generation take a couple hours of waiting time in the background, your hands-on time usually drops to about 30 minutes for setup, spot checks, and final tweaks.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets to store search URLs and results.
- Apify for Apollo lead extraction at scale.
- OpenAI API key (get it from your OpenAI dashboard under API keys).
Skill level: Advanced. You’ll be connecting credentials, mapping sheet columns, and tuning prompts and scraping limits to fit your volume.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
Google Sheets kicks it off. You store one Apollo search URL per row in a “Search URLs” tab, then the workflow pulls those URLs and runs the matching searches automatically.
Apify gathers leads and n8n filters the junk. The Apify HTTP request returns contact data in bulk, and the workflow keeps only prospects that have an email address and a website worth attempting to scrape.
The website is scraped across multiple pages. n8n fetches the homepage HTML, extracts internal links, normalizes relative URLs, removes duplicates, and caps the number of pages it will request so you don’t trigger blocks.
OpenAI summarizes, then writes the icebreaker. Each page becomes markdown, gets summarized, and those summaries are merged into a single context blob that the final prompt uses to write a multi-line opener.
Google Sheets receives the final output. The workflow appends a row to the “Leads” tab with the contact fields plus multiline_icebreaker, ready for your outreach tool or a review pass.
You can easily modify the page cap and the icebreaker template to match your market. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Manual Trigger
This workflow starts manually and then pulls search URLs from Google Sheets.
- Add the Manual Run Trigger node as your starting point.
- Confirm the execution flow begins: Manual Run Trigger → Retrieve Search Links.
Step 2: Connect Google Sheets
Both the input source and output destination use Google Sheets.
- Open Retrieve Search Links and set Document to
Deep Icebreaker Generatorand Sheet toSearch URLs. - Open Append to Sheet and set Operation to
append, Document toMultiline Icebreaker Generator, and Sheet toLeads. - Credential Required: Connect your Google Sheets credentials in both Retrieve Search Links and Append to Sheet.
⚠️ Common Pitfall: If the Google Sheets credentials are missing, both the input and output steps will fail even if the nodes are configured correctly.
Step 3: Set Up Extraction and Lead Mapping
This stage enriches each search URL using Apify, filters results, and extracts site links for later processing.
- In Run Apify Extraction, set URL to
https://api.apify.com/v2/acts/jljBwyyQakqrL1wae/run-sync-get-dataset-itemsand Method toPOST. - Set JSON Body to
={ "getPersonalEmails": true, "getWorkEmails": true, "totalRecords": 500, "url": "{{ $json.URL }}" }. - In Run Apify Extraction, update the Authorization header value to your token (replace
Bearer [CONFIGURE_YOUR_TOKEN]). - In Filter Sites and Emails, keep the two checks that require
={{ $json.organization.website_url }}and={{ $json.email }}to exist. - In Fetch Homepage HTML, set URL to
={{ $json.organization.website_url }}. - In Extract Link Elements, use CSS Selector
awith Attributehrefand Return Array enabled. - In Map Lead Fields, map fields using expressions like
={{ $('Filter Sites and Emails').item.json.first_name }}and={{ $json.links }}.
Tip: The chain follows Retrieve Search Links → Run Apify Extraction → Filter Sites and Emails → Fetch Homepage HTML → Extract Link Elements → Map Lead Fields.
Step 4: Configure Output/Action Nodes
This workflow writes the final icebreaker output back to Google Sheets.
- In Append to Sheet, map columns to the fields using expressions such as
={{ $('Map Lead Fields').item.json.email }}and={{ $json.message.content.icebreaker }}. - Ensure Use Append is enabled so new rows are added without overwriting existing data.
Step 5: Set Up Page Processing and AI Summarization
This section expands links, normalizes paths, pulls page content, and generates AI summaries and icebreakers.
- Use Batch Processor to iterate through leads, then send links to Expand Link List using Field to Split Out
links. - In Filter Relative Links, keep only links that startsWith
/using={{ $json.links }}. - In Normalize URL Paths, paste the provided JavaScript to normalize relative and absolute paths.
- Pass the results through Deduplicate Links and Cap Page Requests with Max Items set to
3. - In Request Linked Page, set URL to
={{ $('Batch Processor').item.json.website_url }}{{ $json.links }}. - In Convert to Markdown, set HTML to
={{ $json.data ? $json.data : "<div>empty</div>" }}. - In Summarize Page Content, keep Model as
GPT-4.1and JSON Output enabled. - In Combine Abstracts, aggregate the field
message.content.abstractfor multi-page summaries. - In Create Email Icebreaker, keep Model as
GPT-4.1and Temperature at0.5. - Use the prompt expression
=Profile: {{ $('Batch Processor').item.json.first_name }} {{ $('Batch Processor').item.json.last_name }} {{ $('Batch Processor').item.json.headline }} Website: {{ $json.abstract.join("/n") }}to generate personalized icebreakers. - Credential Required: Connect your OpenAI credentials in both Summarize Page Content and Create Email Icebreaker.
⚠️ Common Pitfall: If OpenAI credentials are not set on the AI nodes, the workflow will stop before writing results to Google Sheets.
Step 6: Test and Activate Your Workflow
Run a manual test to validate the flow from input URLs to generated icebreakers and output rows.
- Click Execute Workflow starting from Manual Run Trigger.
- Verify Retrieve Search Links pulls URLs and Append to Sheet writes a new row with
multiline_icebreaker. - Check that Summarize Page Content returns JSON with an
abstractfield and Create Email Icebreaker returns JSON with anicebreakerfield. - When satisfied, set the workflow to Active to use it in production.
Watch Out For
- Google Sheets credentials can expire or need specific permissions. If things break, check the n8n credential connection status and your Google account access first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Common Questions
About 3–4 hours if your accounts and sheet are ready.
Yes, but it’s not “click and done.” You’ll connect credentials, confirm the Google Sheets columns match, and then test with a small batch first.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenAI API costs and your Apify plan.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
You can adjust how “deep” the research goes by changing the page cap in the Cap Page Requests step and tightening the filtering in Filter Sites and Emails. If you want different writing styles, tweak the Create Email Icebreaker prompt and keep a few example openers inside the prompt so the tone stays consistent. Many teams also customize the Map Lead Fields step to add extra columns like industry, ICP segment, or campaign name.
Usually it’s expired Google OAuth access or the wrong Google account connected. Reconnect the Google Sheets credential in n8n, then confirm the spreadsheet ID is correct in every Sheets node. If the workflow can read “Search URLs” but cannot write to “Leads,” it’s often a permissions issue on the file (especially when multiple people share the sheet).
It’s designed to handle hundreds of prospects per run using batching and page caps.
For deep scraping plus multi-step AI generation, n8n is usually the better fit because you can branch, loop through pages, merge summaries, and add safeguards without paying extra for every “advanced” step. You also get the self-hosting option, which matters once you start processing hundreds of leads regularly. Zapier or Make can work, but this kind of multi-page enrichment tends to get clunky fast, and costs can jump when you add iterations and filters. If you only need a simple one-page opener, they may be quicker to launch. Talk to an automation expert if you’re not sure which fits.
This is what scaling personalization should feel like: set the system up once, then spend your time on offers and follow-ups instead of browser research.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.