Suivez quotidiennement les métriques SEO géo-ciblées en interrogeant l'API de recherche avec des paramètres de localisation, en stockant les données de position au fil du temps et en comparant les classements entre régions. Les performances SEO locales varient considérablement selon la géographie, et le suivi des classements au niveau national ignore totalement ces différences. Un pipeline de suivi géographique quotidien capture les positions dans le pack cartographique, les classements organiques et la présence des fonctionnalités SERP pour chaque emplacement cible, constituant ainsi les données historiques nécessaires pour détecter rapidement les changements de classement régionaux.
Prérequis
- Python 3.8+ installé
- Bibliothèque requests installée
- Une clé API Scavio depuis scavio.dev
- Mots-clés cibles et emplacements définis
Parcours
Étape 1: Définir les cibles de suivi
Configurez les mots-clés et les emplacements géographiques à surveiller quotidiennement.
import os, requests, json, datetime
API_KEY = os.environ['SCAVIO_API_KEY']
TARGETS = [
{'keyword': 'plumber near me', 'locations': ['New York', 'Los Angeles', 'Chicago']},
{'keyword': 'best coffee shop', 'locations': ['San Francisco', 'Seattle', 'Portland']},
{'keyword': 'emergency dentist', 'locations': ['Houston', 'Phoenix', 'Dallas']},
]
HISTORY_FILE = 'geo_metrics_history.json'
print(f'Tracking {len(TARGETS)} keywords across {sum(len(t["locations"]) for t in TARGETS)} locations')Étape 2: Interroger avec des paramètres géographiques
Recherchez chaque mot-clé avec des requêtes spécifiques à la localisation pour capturer les classements régionaux.
def search_geo(keyword: str, location: str) -> dict:
query = f'{keyword} in {location}'
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': query}, timeout=15)
data = resp.json()
return {
'keyword': keyword,
'location': location,
'date': datetime.date.today().isoformat(),
'organic_count': len(data.get('organic_results', [])),
'top_3': [{'title': r.get('title', ''), 'url': r.get('link', ''), 'position': i+1}
for i, r in enumerate(data.get('organic_results', [])[:3])],
'has_map_pack': 'local_results' in data or 'map_pack' in str(data.keys()),
'has_featured_snippet': 'featured_snippet' in data or 'answer_box' in data,
}
result = search_geo('plumber near me', 'New York')
print(f"{result['location']}: {result['organic_count']} results, map_pack={result['has_map_pack']}")Étape 3: Lancer l'analyse quotidienne
Exécutez l'analyse sur toutes les combinaisons mot-clé-localisation et collectez les résultats.
import time
def daily_scan(targets: list) -> list:
results = []
for target in targets:
for location in target['locations']:
result = search_geo(target['keyword'], location)
results.append(result)
print(f" {result['keyword']} / {result['location']}: {result['organic_count']} results")
time.sleep(0.3)
return results
today_results = daily_scan(TARGETS)
print(f'\nScanned {len(today_results)} keyword-location pairs')Étape 4: Stocker et comparer l'historique
Enregistrez les résultats quotidiens et comparez-les aux jours précédents pour détecter les changements de classement.
def store_results(results: list):
history = []
try:
with open(HISTORY_FILE) as f:
history = json.load(f)
except FileNotFoundError:
pass
history.extend(results)
with open(HISTORY_FILE, 'w') as f:
json.dump(history, f, indent=2)
print(f'Stored {len(results)} results (total history: {len(history)})')
def compare_days(keyword: str, location: str) -> dict:
try:
with open(HISTORY_FILE) as f:
history = json.load(f)
except FileNotFoundError:
return {}
entries = [h for h in history if h['keyword'] == keyword and h['location'] == location]
entries.sort(key=lambda x: x['date'])
if len(entries) < 2:
return {'change': 'insufficient data'}
prev = entries[-2]
curr = entries[-1]
return {
'keyword': keyword,
'location': location,
'prev_date': prev['date'],
'curr_date': curr['date'],
'organic_change': curr['organic_count'] - prev['organic_count'],
'map_pack_change': curr['has_map_pack'] != prev['has_map_pack'],
}
store_results(today_results)Étape 5: Générer un rapport géographique
Produisez un rapport récapitulatif des performances de classement pour tous les emplacements suivis.
def geo_report(targets: list) -> str:
lines = [f'Geo SEO Report - {datetime.date.today().isoformat()}', '']
for target in targets:
lines.append(f'Keyword: {target["keyword"]}')
for location in target['locations']:
diff = compare_days(target['keyword'], location)
status = 'NEW' if diff.get('change') == 'insufficient data' else ''
if not status:
change = diff.get('organic_change', 0)
status = f'+{change}' if change > 0 else str(change) if change < 0 else 'stable'
lines.append(f' {location}: {status}')
lines.append('')
report = '\n'.join(lines)
print(report)
return report
geo_report(TARGETS)Exemple Python
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def geo_rank(keyword, location):
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': f'{keyword} in {location}'}).json()
top = data.get('organic_results', [])[:3]
return {'location': location, 'top': [r.get('title', '')[:50] for r in top]}
print(geo_rank('plumber near me', 'New York'))Exemple JavaScript
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function geoRank(keyword, location) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({platform: 'google', query: `${keyword} in ${location}`})
});
const top = ((await r.json()).organic_results || []).slice(0, 3);
return {location, top: top.map(r => (r.title || '').slice(0, 50))};
}
geoRank('plumber near me', 'New York').then(console.log);Sortie attendue
A daily geo-targeted SERP tracking pipeline that monitors rankings across multiple locations, detects regional changes, and produces summary reports for local SEO optimization.