Realice un seguimiento diario de las métricas de SEO orientadas geográficamente consultando la API de búsqueda con parámetros de ubicación, almacenando datos de posición a lo largo del tiempo y comparando clasificaciones entre regiones. El rendimiento del SEO local varía drásticamente según la geografía, y el seguimiento de la clasificación a nivel nacional pasa por alto estas diferencias por completo. Un proceso de seguimiento geográfico diario captura las posiciones de los paquetes de mapas, las clasificaciones orgánicas y la presencia de funciones SERP para cada ubicación de destino, generando los datos históricos necesarios para detectar cambios en las clasificaciones regionales de manera temprana.
Requisitos previos
- Python 3.8+ instalado
- solicita biblioteca instalada
- Una clave API de Scavio de scavio.dev
- Palabras clave de destino y ubicaciones definidas
Guia paso a paso
Paso 1: Definir objetivos de seguimiento
Configure las palabras clave y las ubicaciones geográficas para monitorear diariamente.
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')Paso 2: Consulta con parámetros geográficos
Busque cada palabra clave con consultas específicas de la ubicación para capturar clasificaciones regionales.
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']}")Paso 3: Ejecutar análisis diario
Ejecute el análisis en todas las combinaciones de ubicación y palabra clave y recopile los resultados.
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')Paso 4: Almacenar y comparar el historial
Guarde los resultados diarios y compárelos con los de días anteriores para detectar cambios en la clasificación.
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)Paso 5: Generar informe geográfico
Produzca un informe resumido del desempeño de la clasificación en todas las ubicaciones rastreadas.
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)Ejemplo en 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'))Ejemplo en 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);Salida esperada
A daily geo-targeted SERP tracking pipeline that monitors rankings across multiple locations, detects regional changes, and produces summary reports for local SEO optimization.