ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build a Google Maps Cold Email Pipeline
Tutorial

How to Build a Google Maps Cold Email Pipeline

Build a lead generation pipeline using Google Maps data from SERP results. Find local businesses, extract contacts, and personalize cold emails.

Get Free API KeyAPI Docs

Google Maps listings contain rich business data: name, address, phone, website, hours, ratings, and reviews. Instead of scraping Google Maps directly (which violates ToS and breaks constantly), this tutorial extracts Maps data from SERP results. Search for a business category and location, and the SERP returns local pack results with all the data you need for cold email outreach. Each search costs $0.005.

Prerequisites

  • Python 3.9+ installed
  • requests library installed
  • A Scavio API key from scavio.dev

Walkthrough

Step 1: Search for local businesses via SERP

Search for a business category and location. SERP results include both organic listings and local pack data with business details.

Python
import requests, os, re

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def find_local_businesses(category: str, city: str, count: int = 10) -> list:
    query = f'{category} near {city}'
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': 'us', 'num_results': count})
    resp.raise_for_status()
    data = resp.json()
    businesses = []
    # Extract from organic results
    for r in data.get('organic_results', []):
        domain = r['link'].split('/')[2] if '/' in r['link'] else ''
        # Skip aggregator sites
        if any(a in domain for a in ['yelp.com', 'yellowpages.com', 'angi.com', 'thumbtack.com']):
            continue
        phones = re.findall(r'\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}', r.get('snippet', ''))
        businesses.append({
            'name': r['title'].split(' - ')[0].split(' | ')[0].strip(),
            'website': r['link'],
            'domain': domain,
            'phone': phones[0] if phones else '',
            'snippet': r.get('snippet', ''),
            'category': category,
            'city': city
        })
    return businesses

leads = find_local_businesses('dentist', 'Austin TX')
print(f'Found {len(leads)} businesses')
for l in leads[:5]:
    print(f'  {l["name"]}: {l["domain"]} {l["phone"]}')

Step 2: Enrich leads with website analysis

Search for each business to find additional signals: whether they have a blog, social media presence, or outdated website design.

Python
import time

def enrich_lead(lead: dict) -> dict:
    domain = lead['domain']
    if not domain:
        return lead
    # Search for the business to find additional info
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': f'site:{domain}', 'country_code': 'us', 'num_results': 5})
    pages = resp.json().get('organic_results', [])
    lead['page_count'] = len(pages)
    lead['has_blog'] = any('blog' in p.get('link', '').lower() for p in pages)
    lead['has_booking'] = any(w in ' '.join(p.get('title', '') for p in pages).lower()
                              for w in ['book', 'schedule', 'appointment'])
    # Estimate website quality from page count
    if lead['page_count'] <= 2:
        lead['website_quality'] = 'minimal'
    elif lead['page_count'] <= 5:
        lead['website_quality'] = 'basic'
    else:
        lead['website_quality'] = 'established'
    return lead

# Enrich top leads
for i, lead in enumerate(leads[:3]):
    leads[i] = enrich_lead(lead)
    print(f'  {lead["name"]}: {lead["page_count"]} pages, '
          f'blog={lead.get("has_blog", False)}, '
          f'quality={lead.get("website_quality", "unknown")}')
    time.sleep(0.3)

Step 3: Generate personalized cold email templates

Use the enrichment data to create personalized email templates for each lead. Reference their specific website situation.

Python
def generate_email(lead: dict) -> str:
    name = lead['name']
    quality = lead.get('website_quality', 'unknown')
    has_blog = lead.get('has_blog', False)
    has_booking = lead.get('has_booking', False)
    # Personalized opening based on website analysis
    if quality == 'minimal':
        opening = (f'I noticed {name} has a fairly simple website. '
                   'Many of your competitors in the area have sites with '
                   'online booking and patient reviews that help them stand out.')
    elif not has_booking:
        opening = (f'I visited the {name} website and noticed you do not have '
                   'an online booking system. Adding one typically increases '
                   'new patient inquiries by 20-30%.')
    elif not has_blog:
        opening = (f'{name} has a solid website, but I noticed there is no blog. '
                   'Local dental practices with blogs rank for 3-5x more '
                   'keywords than those without.')
    else:
        opening = (f'I have been following {name} online and your web presence '
                   'is strong. I think there is an opportunity to improve '
                   'your local search visibility even further.')
    email = f"""Subject: Quick question about {name}'s website

Hi,

{opening}

I help {lead['category']}s in {lead['city']} get more patients through 
their website. Would a 10-minute call this week make sense?

Best regards"""
    return email

for lead in leads[:2]:
    if lead.get('website_quality'):
        email = generate_email(lead)
        print(email)
        print('---')

Python Example

Python
import requests, os, re, time

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def find_leads(category, city):
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': f'{category} near {city}', 'country_code': 'us', 'num_results': 10})
    leads = []
    for r in resp.json().get('organic_results', []):
        domain = r['link'].split('/')[2] if '/' in r['link'] else ''
        if not any(a in domain for a in ['yelp.com', 'yellowpages.com']):
            phones = re.findall(r'\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}', r.get('snippet', ''))
            leads.append({'name': r['title'].split(' - ')[0], 'domain': domain,
                          'phone': phones[0] if phones else ''})
    return leads

for l in find_leads('dentist', 'Austin TX')[:5]:
    print(f'{l["name"]}: {l["domain"]} {l["phone"]}')

JavaScript Example

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;

async function findLeads(category, city) {
  const resp = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST',
    headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query: `${category} near ${city}`, country_code: 'us', num_results: 10 })
  });
  return (await resp.json()).organic_results?.filter(r => {
    const domain = new URL(r.link).hostname;
    return !['yelp.com', 'yellowpages.com'].some(a => domain.includes(a));
  }).map(r => ({
    name: r.title.split(' - ')[0],
    domain: new URL(r.link).hostname,
    phone: (r.snippet || '').match(/\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/)?.[0] || ''
  })) || [];
}

findLeads('dentist', 'Austin TX').then(l => l.forEach(x => console.log(`${x.name}: ${x.phone}`)));

Expected Output

JSON
Found 7 businesses
  Austin Dental Care: austindentalcare.com (512) 555-0123
  Smile Solutions: smilesolutionsatx.com (512) 555-0456
  Capital City Dental: capitalcitydental.com

  Austin Dental Care: 3 pages, blog=False, quality=basic
  Smile Solutions: 8 pages, blog=True, quality=established

Subject: Quick question about Austin Dental Care's website

Hi,

I visited the Austin Dental Care website and noticed you do not have
an online booking system. Adding one typically increases
new patient inquiries by 20-30%.

I help dentists in Austin TX get more patients through their website.
Would a 10-minute call this week make sense?

Related Tutorials

  • How to Build a Local Lead Pipeline with SERP Enrichment
  • How to Run a SERP Audit for Cold Email Personalization
  • How to Find Businesses Without Websites at Scale

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.9+ installed. requests library installed. A Scavio API key from scavio.dev. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Workflow

Google Maps Cold Email Lead Pipeline

Read more
Use Case

Google Maps Local Lead Gen

Read more
Use Case

Google Maps Local Agency Lead Gen

Read more
Best Of

Best Google Maps API for Lead Extraction in 2026

Read more
Solution

Enrich Cold Email Campaigns with Google Maps Business Data

Read more
Best Of

Best Google Maps Business Data APIs (May 2026)

Read more

Start Building

Build a lead generation pipeline using Google Maps data from SERP results. Find local businesses, extract contacts, and personalize cold emails.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy