Tutorial

How to Build a Local Lead Gen Pipeline

Build an automated local lead generation pipeline using search API data. Find businesses, enrich with web presence data, and score leads automatically.

Local lead generation at scale requires finding businesses in a target category, enriching them with web presence data, and scoring them by likelihood to convert. Manual research does not scale beyond a few dozen leads. This tutorial builds an automated pipeline that searches for local businesses using the Scavio API, enriches each lead with website quality signals, and produces a scored lead list ready for outreach. The complete pipeline costs about $0.015 per lead (3 API calls).

Prerequisites

  • Python 3.9+ installed
  • requests library installed
  • A Scavio API key from scavio.dev
  • A target business category and list of locations

Walkthrough

Step 1: Find local businesses via SERP data

Search for businesses in your target category across multiple locations. Extract names, ratings, and basic contact info from local results.

Python
import os, requests, json, time, csv

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
URL = 'https://api.scavio.dev/api/v1/search'

def find_businesses(category: str, location: str) -> list:
    resp = requests.post(URL, headers=H,
        json={'query': f'{category} {location}', 'country_code': 'us', 'num_results': 10})
    data = resp.json()
    leads = []
    for b in data.get('local_results', data.get('local_pack', [])):
        leads.append({
            'name': b.get('title', b.get('name', '')),
            'address': b.get('address', ''),
            'phone': b.get('phone', ''),
            'rating': b.get('rating', ''),
            'reviews': b.get('reviews', 0),
            'website': b.get('website', b.get('link', '')),
            'category': category,
            'location': location,
        })
    return leads

leads = find_businesses('dental offices', 'Denver CO')
print(f'Found {len(leads)} dental offices in Denver')

Step 2: Enrich leads with web presence signals

For each business with a website, search for their web presence to assess digital maturity. Businesses with weak web presence are better prospects for marketing services.

Python
def enrich_lead(lead: dict) -> dict:
    name = lead['name']
    website = lead.get('website', '')
    domain = website.split('/')[2] if '/' in website and len(website.split('/')) > 2 else ''
    if not domain:
        lead['web_score'] = 0
        lead['web_signals'] = 'no website'
        return lead
    # Check web presence
    resp = requests.post(URL, headers=H,
        json={'query': f'site:{domain}', 'country_code': 'us', 'num_results': 5})
    indexed_pages = len(resp.json().get('organic_results', []))
    time.sleep(0.3)
    # Check social presence
    resp2 = requests.post(URL, headers=H,
        json={'query': f'"{name}" ({lead["location"]})', 'country_code': 'us', 'num_results': 5})
    mentions = len(resp2.json().get('organic_results', []))
    # Score: higher = more established web presence
    lead['indexed_pages'] = indexed_pages
    lead['web_mentions'] = mentions
    lead['web_score'] = min(indexed_pages * 2 + mentions, 20)
    lead['web_signals'] = 'strong' if lead['web_score'] > 10 else 'moderate' if lead['web_score'] > 5 else 'weak'
    return lead

enriched = enrich_lead(leads[0])
print(f'{enriched["name"]}: web_score={enriched["web_score"]}, signals={enriched["web_signals"]}')

Step 3: Score and export the lead list

Calculate a composite lead score based on rating, review count, and web presence. Export scored leads to CSV sorted by score.

Python
def score_lead(lead: dict) -> float:
    score = 0
    # Rating score (high rating = established business)
    rating = float(lead.get('rating', 0) or 0)
    score += rating * 4  # Max 20
    # Reviews (more reviews = larger business)
    reviews = int(lead.get('reviews', 0) or 0)
    score += min(reviews / 10, 15)  # Max 15
    # Web presence (weak = better prospect for services)
    web = lead.get('web_score', 0)
    if web <= 5:
        score += 15  # Weak web = needs help
    elif web <= 10:
        score += 8
    return round(score, 1)

def build_lead_list(category: str, locations: list, output: str = 'leads.csv') -> list:
    all_leads = []
    for loc in locations:
        leads = find_businesses(category, loc)
        for lead in leads:
            enrich_lead(lead)
            lead['lead_score'] = score_lead(lead)
            all_leads.append(lead)
            time.sleep(0.2)
        print(f'{loc}: {len(leads)} leads found')
    # Sort by score
    all_leads.sort(key=lambda x: x.get('lead_score', 0), reverse=True)
    # Export
    keys = ['name', 'lead_score', 'phone', 'website', 'rating', 'reviews', 'web_signals', 'location', 'address']
    with open(output, 'w', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=keys, extrasaction='ignore')
        writer.writeheader()
        writer.writerows(all_leads)
    cost = len(all_leads) * 0.015
    print(f'\nPipeline complete: {len(all_leads)} scored leads')
    print(f'Top leads:')
    for lead in all_leads[:5]:
        print(f'  [{lead["lead_score"]:5.1f}] {lead["name"][:30]} | {lead["web_signals"]} web | {lead.get("phone", "N/A")}')
    print(f'Cost: ${cost:.3f}')
    print(f'Saved to {output}')
    return all_leads

build_lead_list('dental offices', ['Denver CO', 'Boulder CO'])

Python Example

Python
import os, requests, time

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}

def lead_gen(category, location):
    resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
        json={'query': f'{category} {location}', 'country_code': 'us', 'num_results': 10})
    leads = resp.json().get('local_results', resp.json().get('local_pack', []))
    print(f'{category} in {location}: {len(leads)} leads')
    for b in leads[:5]:
        name = b.get('title', b.get('name', ''))
        rating = b.get('rating', 'N/A')
        phone = b.get('phone', 'N/A')
        print(f'  {name[:30]} | {rating} stars | {phone}')
    print(f'Cost: $0.005')

for loc in ['Denver CO', 'Boulder CO']:
    lead_gen('dental offices', loc)
    time.sleep(0.3)

JavaScript Example

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;

async function leadGen(category, location) {
  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} ${location}`, country_code: 'us', num_results: 10 })
  });
  const data = await resp.json();
  const leads = data.local_results || data.local_pack || [];
  console.log(`${category} in ${location}: ${leads.length} leads`);
  leads.slice(0, 5).forEach(b => {
    console.log(`  ${(b.title || b.name || '').slice(0, 30)} | ${b.rating || 'N/A'} stars`);
  });
}

(async () => {
  await leadGen('dental offices', 'Denver CO');
  await leadGen('dental offices', 'Boulder CO');
})();

Expected Output

JSON
Found 8 dental offices in Denver
ACE Dental: web_score=4, signals=weak

Denver CO: 8 leads found
Boulder CO: 6 leads found

Pipeline complete: 14 scored leads
Top leads:
  [ 44.2] Mountain View Family Dental    | weak web   | (303) 555-0123
  [ 42.8] Cherry Creek Dental Center     | weak web   | (303) 555-0456
  [ 38.5] Denver Smile Design            | moderate web | (303) 555-0789
  [ 36.1] Boulder Dental Arts            | weak web   | (720) 555-0321
  [ 33.9] Pearl Street Dentistry         | moderate web | (720) 555-0654
Cost: $0.210
Saved to leads.csv

Related Tutorials

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 target business category and list of locations. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, 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.

Start Building

Build an automated local lead generation pipeline using search API data. Find businesses, enrich with web presence data, and score leads automatically.