Google Maps + Supabase, enriched leads ready to call
Copying businesses out of Google Maps is tedious. Then you still have to clean the list, dedupe it, figure out who to call first, and write something that doesn’t sound like a robot.
This Google Maps leads automation hits sales teams hardest, but marketers building local lists and agency owners doing outbound for clients feel it too. The outcome is simple: leads land in Supabase already enriched, with a call script you can actually use.
Below you’ll see how the workflow turns a single form submission into a ready-to-call database, what it removes from your process, and what to watch for when you run it at scale.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Google Maps + Supabase, enriched leads ready to call
flowchart LR
subgraph sg0["Form Submission Flow"]
direction LR
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/form.svg' width='40' height='40' /></div><br/>Form Submission Trigger"]
n3@{ icon: "mdi:swap-vertical", form: "rounded", label: "Parse Coordinates from URL", pos: "b", h: 48 }
n4["<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/>Bright Data Request"]
n5@{ icon: "mdi:swap-vertical", form: "rounded", label: "Initialize Counter", pos: "b", h: 48 }
n6@{ icon: "mdi:cog", form: "rounded", label: "Pass Through Step", pos: "b", h: 48 }
n7@{ icon: "mdi:cog", form: "rounded", label: "Monitor Extraction Progress", pos: "b", h: 48 }
n8@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check Request Status", pos: "b", h: 48 }
n9@{ icon: "mdi:cog", form: "rounded", label: "Fetch Snapshot Data", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Snapshot Ready Check", pos: "b", h: 48 }
n11@{ icon: "mdi:cog", form: "rounded", label: "Pause Before Retry", pos: "b", h: 48 }
n12@{ icon: "mdi:swap-vertical", form: "rounded", label: "Structure Business Data", pos: "b", h: 48 }
n13@{ icon: "mdi:cog", form: "rounded", label: "Apply Item Limit", pos: "b", h: 48 }
n14@{ icon: "mdi:swap-vertical", form: "rounded", label: "Batch Item Loop", pos: "b", h: 48 }
n15@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Website Availability Check", pos: "b", h: 48 }
n16@{ icon: "mdi:robot", form: "rounded", label: "Scrape and Summarize", pos: "b", h: 48 }
n17@{ icon: "mdi:swap-vertical", form: "rounded", label: "Map Summary Fields", 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/merge.svg' width='40' height='40' /></div><br/>Combine Records"]
n19@{ icon: "mdi:robot", form: "rounded", label: "Generate Call Script", pos: "b", h: 48 }
n20@{ icon: "mdi:brain", form: "rounded", label: "Gemini Chat Model", pos: "b", h: 48 }
n21["<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/postgres.svg' width='40' height='40' /></div><br/>Upsert Database Row"]
n22@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Retry Limit Check", pos: "b", h: 48 }
n23@{ icon: "mdi:cog", form: "rounded", label: "Delay Cycle", pos: "b", h: 48 }
n24@{ icon: "mdi:swap-vertical", form: "rounded", label: "Increase Counter", pos: "b", h: 48 }
n25@{ icon: "mdi:wrench", form: "rounded", label: "Markdown Scraper Tool", pos: "b", h: 48 }
n26@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Mini Chat", pos: "b", h: 48 }
n11 --> n9
n18 --> n19
n23 --> n24
n5 --> n6
n13 --> n14
n17 --> n18
n26 -.-> n16
n12 --> n13
n14 --> n15
n24 --> n6
n8 --> n9
n8 --> n22
n19 --> n21
n2 --> n3
n16 --> n17
n25 -.-> n16
n22 --> n23
n21 --> n14
n15 --> n16
n15 --> n18
n20 -.-> n19
n6 --> n7
n4 --> n5
n10 --> n12
n10 --> n11
n9 --> n10
n7 --> n8
n3 --> n4
end
subgraph sg1["Manual Start Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "Manual Start Trigger", pos: "b", h: 48 }
n1["<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/postgres.svg' width='40' height='40' /></div><br/>Create Storage Table"]
n0 --> n1
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 n2,n0 trigger
class n16,n19 ai
class n20,n26 aiModel
class n25 ai
class n8,n10,n15,n22 decision
class n21,n1 database
class n4 api
class n0 disabled
classDef customIcon fill:none,stroke:none
class n2,n4,n18,n21,n1 customIcon
The Challenge: Turning Google Maps results into outreach-ready leads
Google Maps is great for finding businesses. It’s awful for turning those finds into a clean, usable lead list. You end up doing a messy mix of scraping, manual copy-paste, “is this the right phone number?”, and rebuilding context you already saw on the listing. And if you want personalization, you’re stuck opening websites one-by-one just to write a decent opener. After a few dozen leads, the whole thing gets slow, error-prone, and frankly annoying.
It adds up fast. Here’s where it breaks down once you try to do it consistently.
- Pulling businesses from Maps and formatting them for a CRM takes about 2 hours per batch if you care about quality.
- Duplicates creep in because the same business shows up across slightly different searches, which means reps waste time calling twice.
- You end up calling “cold” because there’s no quick summary of what the business does or what to mention on the first call.
- When the list lives in spreadsheets and inboxes, tracking outreach or assigning leads becomes a weekly cleanup project.
The Fix: Google Maps scraping, AI enrichment, and Supabase upserts
This workflow starts with a simple form submission where you provide a Google Maps starting location, a keyword, and a country. From there, Bright Data kicks off a Maps scraping job and the workflow automatically monitors the extraction until the snapshot is ready. Once results come back, the automation structures each business record, applies a sensible item limit, and processes leads in batches so it doesn’t fall over when you pull a big list. For leads that have a website, it scrapes and summarizes the site content, then uses an LLM (via Bright Data MCP and LangChain nodes) to generate a personalized cold call script and talking points. Finally, everything is upserted into Supabase, so re-running a search updates existing leads instead of creating duplicates.
The workflow begins when your form is submitted. It then runs a scrape-and-wait loop until Bright Data’s snapshot is ready, enriches each lead (website summary when available), and generates the call script. Supabase becomes the single place where “found it on Maps” turns into “ready to call”.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you need 100 local leads for “roofing” in a metro area. Manually, even a quick process is maybe 2 minutes per lead to copy details, check the website, and write a basic opener, which is about 3 hours. With this workflow, you submit the form in about 2 minutes, then let Bright Data run and the AI generate scripts while you do other work. You’re usually back to a Supabase table full of enriched leads without spending your afternoon in tabs.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Bright Data for Google Maps scraping jobs
- Supabase to store and upsert lead records
- LLM API key (get it from OpenAI or Google Gemini)
Skill level: Intermediate. You’ll connect credentials and create a Supabase/Postgres table once.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
Form submission kicks it off. You submit a starting location (often a Maps URL), a keyword, and a country, and the workflow parses coordinates so the search is consistent.
Bright Data runs the Maps extraction. n8n sends the request, then loops through a monitor-and-check cycle. If the snapshot isn’t ready yet, it waits and retries until it is (with a counter to avoid endless runs).
Lead records get cleaned and enriched. The workflow structures the business data, applies an item limit, and processes leads in batches. If a business has a website, it scrapes and summarizes it, then maps those insights into fields you can store.
AI generates the call script. Using an LLM (Gemini and/or OpenAI nodes appear in this workflow), it creates a personalized cold call script plus talking points, then merges everything into one record.
Supabase stays updated. Each lead is upserted to your database table, so reruns refresh details instead of multiplying rows. You can easily modify the keyword, the item limit, or the script prompt to match your niche and outreach style. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Manual Trigger
This workflow can be started manually for setup and also accepts user input through a form. Configure both entry points so you can create the database table and collect scraping parameters.
- Open Manual Start Trigger and confirm it’s enabled for testing (note: it’s disabled in the JSON).
- Open Form Submission Trigger and set Form Title to
Maps Extractor. - In Form Submission Trigger, verify the fields and placeholders for Location URL, Keyword Search, Country, and My company's segment.
- Set the Button Label to
Scrapeand the Form Submitted Text toScraping started 🔎.
⚠️ Common Pitfall: The form instructions require a full Google Maps URL from the browser address bar, not a “Share” link. Using a share link can break the coordinate parsing.
Step 2: Connect PostgreSQL Storage
Set up the database table and upsert logic that stores enriched business records.
- Open Create Storage Table and set Operation to
executeQuery. - Paste the full SQL into Query exactly as shown, starting with
CREATE TABLE business_scraping_result (...). - Credential Required: Connect your postgres credentials in Create Storage Table.
- Open Upsert Database Row and ensure the Table is
business_scraping_resultinpublicschema. - Credential Required: Connect your postgres credentials in Upsert Database Row.
- Confirm the mapped columns use expressions like
{{ $('Combine Records').item.json.company.name }}and{{ $json.text }}for sales_helper.
Step 3: Connect Bright Data Extraction and Retry Loop
Configure the Bright Data request, monitoring, and retry loop that fetches Google Maps business records.
- Open Parse Coordinates from URL and confirm latitude is set to
{{ $json['Location URL'].match(/@(-?\d+\.\d+),(-?\d+\.\d+)/)[1] }}and longitude to{{ $json['Location URL'].match(/@(-?\d+\.\d+),(-?\d+\.\d+)/)[2] }}. - Open Bright Data Request and set URL to
https://api.brightdata.com/datasets/v3/triggerwith MethodPOST. - Set JSON Body to the provided array expression, including
{{ $json.Country }},{{ $json['Keyword Search'] }}, and{{ $json.longitude.toNumber() }}. - In Bright Data Request, update query parameters like dataset_id to your Bright Data dataset ID.
- Credential Required: Connect your brightdataApi credentials in Bright Data Request.
- Open Monitor Extraction Progress and Fetch Snapshot Data, and confirm snapshot_id is set to
{{ $('Bright Data Request').item.json.snapshot_id }}. - Credential Required: Connect your brightdataApi credentials in Monitor Extraction Progress and Fetch Snapshot Data.
- Check the retry loop: Pause Before Retry uses Amount
10, Delay Cycle uses60, and Retry Limit Check compares{{ $('Pass Through Step').last().json.count }}to10.
⚠️ Common Pitfall: If the Bright Data dataset is still “building,” the workflow will loop between Snapshot Ready Check and Pause Before Retry. Verify your dataset configuration and quota to avoid endless retries.
Step 4: Set Up Data Structuring and Batching
Normalize fields, limit the number of records, and process items in batches for downstream enrichment.
- Open Structure Business Data and confirm mapped fields like company.name →
{{ $json.name }}and company.open_website →{{ $json.open_website }}. - Set Apply Item Limit to Max Items
15to cap the number of businesses processed. - Use Batch Item Loop to iterate through each item after limiting.
- Verify Website Availability Check uses the expression
{{ $json?.company?.open_website }}to route items with a website to enrichment.
Step 5: Set Up AI Enrichment and Call Script Generation
Configure the scraping agent and the call script generation chain with the connected AI models and tool.
- Open Scrape and Summarize and keep the Text prompt as
Use the tool 'scrape_as_markdown' with the url: {{ $json.company.open_website }}. - Open Markdown Scraper Tool and set Endpoint URL to
https://mcp.brightdata.com/mcp?token=[CONFIGURE_YOUR_TOKEN], then replace[CONFIGURE_YOUR_TOKEN]with your Bright Data MCP token. - Connect OpenAI Mini Chat as the language model for Scrape and Summarize and ensure credentials are added to OpenAI Mini Chat.
- Credential Required: Connect your openAiApi credentials in OpenAI Mini Chat.
- Open Generate Call Script and set Text to
{{ JSON.stringify($json) }}. - Connect Gemini Chat Model as the language model for Generate Call Script.
- Credential Required: Connect your googlePalmApi credentials in Gemini Chat Model.
⚠️ Common Pitfall: The Markdown Scraper Tool is a tool sub-node. Credentials and tokens should be configured at the tool and parent AI node level—ensure the token is valid and accessible when Scrape and Summarize runs.
Step 6: Configure Record Merging and Output Mapping
Combine the scraped summary with the original business data and route it into the database upsert.
- Open Map Summary Fields and confirm summary uses
{{ $json.output }}and company uses{{ $('Apply Item Limit').item.json.company }}. - Keep Combine Records as the merge point before Generate Call Script.
- Verify Website Availability Check routes the “false” path to Combine Records so items without websites still get processed.
Step 7: Test and Activate Your Workflow
Run a manual test, then enable the form trigger for production use.
- Click Manual Start Trigger to execute Create Storage Table and confirm the database table is created.
- Submit the Form Submission Trigger form with a valid Google Maps URL, keyword, country, and company segment.
- Watch the run: Bright Data Request should return a
snapshot_id, and the loop should proceed to Fetch Snapshot Data after readiness checks. - Confirm successful output: Upsert Database Row should insert/update records with page_summary and sales_helper populated.
- When validated, activate the workflow to allow Form Submission Trigger to run continuously in production.
Watch Out For
- Bright Data credentials can expire or need specific permissions. If things break, check your Bright Data token and workspace access in the Bright Data dashboard 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
Usually about an hour once your Bright Data and Supabase credentials are ready.
Yes, but someone has to set up the Supabase table the first time. After that, running it is just submitting the form and reviewing results.
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 Bright Data usage plus your LLM API costs.
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 customize it in three practical places. Change the “Apply Item Limit” node to control lead volume, tweak “Scrape and Summarize” to capture the signals you care about (services, pricing, locations), and rewrite the “Generate Call Script” prompt so it matches your offer and tone. If you prefer one model, you can also swap between the Gemini and OpenAI chat model nodes without changing the overall flow. That’s usually the fastest way to go from generic scripts to “this sounds like us.”
Most of the time it’s an expired token or missing permissions on the Bright Data side. Regenerate the API key (or MCP credentials), update it in n8n, then rerun the request and watch the monitor step to confirm the job is actually created. If it starts and then stalls, you may be hitting account limits or the snapshot is taking longer than your current wait cycle, so the “Pause Before Retry” duration needs to be increased.
If you self-host n8n, there’s no hard execution cap (it depends on your server). On n8n Cloud, your plan sets monthly executions, and this workflow can consume a lot if you enrich big batches because it loops and processes items in chunks. Practically, most small teams run this weekly or daily for tens to a few hundred leads per run, then scale up once prompts and database fields are stable.
Often, yes, because this workflow needs looping, waiting, branching logic, and database upserts, and n8n handles those without turning your bill into a surprise. Zapier or Make can work for simple “capture a lead and add a row” automations, but the moment you add scraping progress checks and AI enrichment, things get messy. n8n is also easier to self-host, which matters if you plan to run high volume. The honest answer: if you’re only doing lightweight list building, you might prefer the simpler tools. Talk to an automation expert if you’re not sure which fits.
Once this is running, lead building stops being a half-day task and becomes a repeatable input to your outreach machine. Set it up, tune the prompts, and let Supabase stay ready for the next call block.
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.