Realice un seguimiento de su clasificación de Google Maps en una cuadrícula geográfica ejecutando consultas de búsqueda basadas en la ubicación en múltiples puntos de la cuadrícula y registrando la posición de su empresa en los resultados de cada punto. El SEO local depende de la clasificación en el paquete de Google Maps, que varía significativamente según la ubicación del buscador. Una cuadrícula de clasificación revela puntos ciegos donde su empresa sale de los primeros resultados e identifica el radio geográfico de su visibilidad. Este tutorial construye un escáner de cuadrícula utilizando la API de Scavio.
Requisitos previos
- Python 3.8+ instalado
- solicita biblioteca instalada
- Una clave API de Scavio de scavio.dev
- El nombre de su empresa y las coordenadas del área de servicio objetivo
Guia paso a paso
Paso 1: Definir la grilla geográfica
Configure una cuadrícula de puntos de latitud/longitud centrada en la ubicación de su empresa.
import os, requests, json
API_KEY = os.environ['SCAVIO_API_KEY']
BUSINESS_NAME = 'Your Business Name'
CENTER_LAT = 30.2672 # Austin, TX example
CENTER_LNG = -97.7431
GRID_SIZE = 5 # 5x5 grid
GRID_STEP = 0.02 # ~1.4 miles per step
def generate_grid(center_lat: float, center_lng: float, size: int, step: float) -> list:
points = []
half = size // 2
for i in range(-half, half + 1):
for j in range(-half, half + 1):
lat = round(center_lat + i * step, 4)
lng = round(center_lng + j * step, 4)
points.append({'lat': lat, 'lng': lng})
return points
grid = generate_grid(CENTER_LAT, CENTER_LNG, GRID_SIZE, GRID_STEP)
print(f'Grid: {len(grid)} points ({GRID_SIZE}x{GRID_SIZE})')Paso 2: Consultar cada punto de la cuadrícula
Ejecute una consulta de búsqueda local en cada punto de la cuadrícula y encuentre la posición de su empresa en los resultados.
def search_at_location(query: str, lat: float, lng: float) -> list:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': f'{query} near {lat},{lng}'}, timeout=15)
return resp.json().get('organic_results', [])
def find_rank(results: list, business_name: str) -> int:
name_lower = business_name.lower()
for i, r in enumerate(results):
title = r.get('title', '').lower()
if name_lower in title:
return i + 1
return 0 # Not found
results = search_at_location('plumber', CENTER_LAT, CENTER_LNG)
rank = find_rank(results, BUSINESS_NAME)
print(f'Rank at center: {rank if rank else "not found"}')Paso 3: Posiciones récord en toda la parrilla
Escanee todos los puntos de la cuadrícula y registre la clasificación en cada ubicación.
def scan_grid(query: str, business: str, grid: list) -> list:
scan_results = []
for i, point in enumerate(grid):
results = search_at_location(query, point['lat'], point['lng'])
rank = find_rank(results, business)
scan_results.append({
'lat': point['lat'],
'lng': point['lng'],
'rank': rank,
'total_results': len(results),
})
if (i + 1) % 5 == 0:
print(f'Scanned {i + 1}/{len(grid)} points')
return scan_results
# For demo, scan a small subset
small_grid = grid[:4]
results = scan_grid('plumber', BUSINESS_NAME, small_grid)
for r in results:
status = f'Rank {r["rank"]}' if r['rank'] else 'Not found'
print(f'({r["lat"]}, {r["lng"]}): {status}')Paso 4: Calcular los cambios de clasificación a lo largo del tiempo
Compare el escaneo de hoy con un escaneo anterior para identificar ubicaciones donde la clasificación mejoró o bajó.
def compare_scans(current: list, previous: list) -> list:
prev_map = {(p['lat'], p['lng']): p['rank'] for p in previous}
changes = []
for c in current:
key = (c['lat'], c['lng'])
prev_rank = prev_map.get(key, 0)
curr_rank = c['rank']
if prev_rank and curr_rank:
change = prev_rank - curr_rank # positive = improved
elif curr_rank and not prev_rank:
change = 'NEW'
elif prev_rank and not curr_rank:
change = 'LOST'
else:
change = 0
changes.append({**c, 'prev_rank': prev_rank, 'change': change})
return changes
# Example:
prev = [{'lat': 30.27, 'lng': -97.74, 'rank': 5}]
curr = [{'lat': 30.27, 'lng': -97.74, 'rank': 3, 'total_results': 10}]
for c in compare_scans(curr, prev):
print(f'({c["lat"]}, {c["lng"]}): {c["prev_rank"]} -> {c["rank"]} (change: {c["change"]})')Paso 5: Visualice la cuadrícula de clasificación
Genere un mapa de calor basado en texto de su clasificación en la cuadrícula para un análisis rápido.
def print_heatmap(scan_results: list, grid_size: int):
print(f'\nRank Heatmap ({grid_size}x{grid_size}):')
print('1-3=top, 4-7=mid, 8+=low, .=not found\n')
for i in range(grid_size):
row = []
for j in range(grid_size):
idx = i * grid_size + j
if idx < len(scan_results):
rank = scan_results[idx]['rank']
if rank == 0:
row.append('.')
elif rank <= 3:
row.append(str(rank))
elif rank <= 7:
row.append('m')
else:
row.append('L')
else:
row.append(' ')
print(' '.join(row))
# Demo with mock data
mock_scan = [{'rank': r} for r in [1,2,3,0,5, 2,1,4,3,6, 0,3,1,2,0, 5,4,3,2,7, 0,6,5,4,0]]
print_heatmap(mock_scan, 5)Ejemplo en Python
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def rank_at(query, lat, lng, business):
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': f'{query} near {lat},{lng}'}).json()
for i, r in enumerate(data.get('organic_results', [])):
if business.lower() in r.get('title', '').lower():
return i + 1
return 0
print(f'Rank: {rank_at("plumber", 30.2672, -97.7431, "Your Business")}')Ejemplo en JavaScript
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function rankAt(query, lat, lng, business) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({platform: 'google', query: `${query} near ${lat},${lng}`})
});
const results = (await r.json()).organic_results || [];
const idx = results.findIndex(r => r.title?.toLowerCase().includes(business.toLowerCase()));
return idx >= 0 ? idx + 1 : 0;
}
rankAt('plumber', 30.2672, -97.7431, 'Your Business').then(console.log);Salida esperada
A geographic grid scan that shows your Google Maps ranking at each location point, with change tracking over time and a text-based heatmap visualization.