La optimización generativa del motor (GEO) mide qué tan visible es su marca en los resultados de búsqueda generados por IA. Este tutorial crea un canal de informes automatizado que rastrea su visibilidad GEO en todas las palabras clave, se compara con la competencia y genera informes semanales. Cada escaneo de palabras clave cuesta $0,005.
Requisitos previos
- Python 3.8+
- solicita biblioteca
- Una clave API de Scavio de scavio.dev
- Orientar palabras clave y dominios de la competencia
Guia paso a paso
Paso 1: Definir métricas de visibilidad GEO
Mida múltiples señales que indiquen qué tan bien se clasifica su contenido en los resultados generativos.
import os, requests, json
from datetime import datetime
from collections import defaultdict
API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
BRAND = 'scavio.dev'
COMPETITORS = ['tavily.com', 'serpapi.com']
KEYWORDS = [
'best search api for ai agents',
'web search api comparison',
'mcp search tool setup',
'serp api free tier',
'search api for rag pipeline',
]
def geo_score_keyword(keyword, domain):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}, timeout=10).json()
ai = data.get('ai_overview', data.get('answer_box', {}))
organic = data.get('organic_results', [])
featured = data.get('featured_snippet', {})
paa = data.get('people_also_ask', [])
domain_l = domain.lower()
# Score components (0-100 each)
ai_score = 30 if (ai and domain_l in json.dumps(ai).lower()) else 0
org_pos = next((i+1 for i, r in enumerate(organic) if domain_l in r.get('link', '').lower()), None)
org_score = max(0, 30 - (org_pos - 1) * 3) if org_pos else 0
feat_score = 20 if (featured and domain_l in json.dumps(featured).lower()) else 0
paa_score = 20 if any(domain_l in json.dumps(q).lower() for q in paa) else 0
total = ai_score + org_score + feat_score + paa_score
return {'keyword': keyword, 'total': total, 'ai': ai_score, 'organic': org_score,
'featured': feat_score, 'paa': paa_score, 'organic_pos': org_pos}
print(f'GEO Visibility Scan for {BRAND}\n')
scores = [geo_score_keyword(kw, BRAND) for kw in KEYWORDS]
for s in scores:
pos = f'#{s["organic_pos"]}' if s['organic_pos'] else '-'
print(f' {s["keyword"][:40]:40} | GEO: {s["total"]:3} | Pos: {pos}')
avg = sum(s['total'] for s in scores) / len(scores)
print(f'\nAverage GEO Score: {avg:.0f}/100 | Cost: ${len(KEYWORDS) * 0.005:.3f}')Paso 2: Comparar con la competencia
Ejecute el mismo escaneo GEO para los dominios de la competencia y clasifíquelos.
def competitive_geo(keywords, brand, competitors):
all_domains = [brand] + competitors
domain_scores = defaultdict(list)
for kw in keywords:
for domain in all_domains:
score = geo_score_keyword(kw, domain)
domain_scores[domain].append(score)
print(f'\n=== GEO Competitive Analysis ===')
rankings = []
for domain, keyword_scores in domain_scores.items():
avg = sum(s['total'] for s in keyword_scores) / len(keyword_scores)
ai_pct = sum(1 for s in keyword_scores if s['ai'] > 0) / len(keyword_scores) * 100
rankings.append({'domain': domain, 'avg_geo': avg, 'ai_citation_pct': ai_pct})
rankings.sort(key=lambda x: x['avg_geo'], reverse=True)
for i, r in enumerate(rankings, 1):
marker = ' <-- you' if r['domain'] == brand else ''
print(f' {i}. {r["domain"]:25} | GEO: {r["avg_geo"]:5.1f} | AI cited: {r["ai_citation_pct"]:.0f}%{marker}')
return rankings
rankings = competitive_geo(KEYWORDS, BRAND, COMPETITORS)
print(f'\nTotal cost: ${len(KEYWORDS) * (1 + len(COMPETITORS)) * 0.005:.3f}')Paso 3: Generar el informe GEO semanal
Recopile todos los datos en un informe semanal formateado con tendencias y recomendaciones.
def weekly_geo_report(brand, scores, rankings):
print(f'\n{"=" * 60}')
print(f' WEEKLY GEO VISIBILITY REPORT')
print(f' Brand: {brand} | Date: {datetime.now().strftime("%Y-%m-%d")}')
print(f'{"=" * 60}')
avg_geo = sum(s['total'] for s in scores) / len(scores)
ai_cited = sum(1 for s in scores if s['ai'] > 0)
print(f'\n Overall GEO Score: {avg_geo:.0f}/100')
print(f' AI Citations: {ai_cited}/{len(scores)} keywords')
print(f' Competitive Rank: {next((i+1 for i, r in enumerate(rankings) if r["domain"] == brand), "?")} of {len(rankings)}')
# Breakdown
print(f'\n Score Breakdown:')
print(f' AI Overview: {sum(s["ai"] for s in scores)/len(scores):.0f}/30')
print(f' Organic: {sum(s["organic"] for s in scores)/len(scores):.0f}/30')
print(f' Featured: {sum(s["featured"] for s in scores)/len(scores):.0f}/20')
print(f' People Ask: {sum(s["paa"] for s in scores)/len(scores):.0f}/20')
# Opportunities
weak = [s for s in scores if s['total'] < 30]
if weak:
print(f'\n Improvement Opportunities:')
for s in weak:
print(f' - {s["keyword"][:40]} (GEO: {s["total"]})')
print(f'\n Weekly cost: ${len(KEYWORDS) * (1 + len(COMPETITORS)) * 0.005 * 7:.2f}')
weekly_geo_report(BRAND, scores, rankings)Ejemplo en Python
import os, requests, json
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def geo_check(keyword, domain):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}, timeout=10).json()
ai = data.get('ai_overview', data.get('answer_box', {}))
cited = domain.lower() in json.dumps(ai).lower() if ai else False
org = next((i+1 for i, r in enumerate(data.get('organic_results', [])) if domain in r.get('link', '')), None)
print(f'{keyword[:35]:35} | AI: {cited} | Organic: {org or "-"}')
geo_check('best search api 2026', 'scavio.dev')Ejemplo en JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query: 'best search api 2026', country_code: 'us' })
}).then(r => r.json());
const ai = data.ai_overview || data.answer_box || {};
const cited = JSON.stringify(ai).toLowerCase().includes('scavio');
console.log(`GEO visibility: AI cited=${cited}`);Salida esperada
GEO Visibility Scan for scavio.dev
best search api for ai agents | GEO: 60 | Pos: #3
web search api comparison | GEO: 30 | Pos: #5
mcp search tool setup | GEO: 50 | Pos: #2
serp api free tier | GEO: 27 | Pos: #7
search api for rag pipeline | GEO: 47 | Pos: #4
Average GEO Score: 43/100 | Cost: $0.025
=== GEO Competitive Analysis ===
1. scavio.dev | GEO: 43.0 | AI cited: 40%
2. serpapi.com | GEO: 38.0 | AI cited: 20%
3. tavily.com | GEO: 32.0 | AI cited: 20%
============================================================
WEEKLY GEO VISIBILITY REPORT
Brand: scavio.dev | Date: 2026-05-21
============================================================
Overall GEO Score: 43/100
AI Citations: 2/5 keywords
Competitive Rank: 1 of 3
Weekly cost: $0.53