La génération de leads locaux à grande échelle nécessite de trouver des entreprises dans une catégorie cible, de les enrichir avec des données de présence en ligne, et de les noter selon leur probabilité de conversion. La recherche manuelle ne passe pas à l'échelle au-delà de quelques dizaines de leads. Ce tutoriel construit un pipeline automatisé qui recherche des entreprises locales via l'API Scavio, enrichit chaque lead avec des signaux de qualité de site web, et produit une liste de leads notés prêts pour la prospection. Le pipeline complet coûte environ 0,015 $ par lead (3 appels API).
Prérequis
- Python 3.9+ installé
- bibliothèque requests installée
- Une clé API Scavio depuis scavio.dev
- Une catégorie d'entreprise cible et une liste d'emplacements
Parcours
Étape 1: Trouver des entreprises locales via les données SERP
Recherchez des entreprises dans votre catégorie cible sur plusieurs emplacements. Extrayez les noms, les notes et les informations de contact de base des résultats locaux.
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')Étape 2: Enrichir les leads avec des signaux de présence en ligne
Pour chaque entreprise disposant d'un site web, recherchez leur présence en ligne pour évaluer leur maturité numérique. Les entreprises avec une faible présence en ligne sont de meilleurs prospects pour les services marketing.
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"]}')Étape 3: Noter et exporter la liste de leads
Calculez un score composite de lead basé sur la note, le nombre d'avis et la présence en ligne. Exportez les leads notés en CSV triés par score.
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'])Exemple 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)Exemple 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');
})();Sortie attendue
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