La guía Generative Engine Optimization de Google publicada a principios de 2026 cambió el manual de SEO. En AI Overviews se prefieren los sitios que siguen una estructura basada en OEA, evitan señales de autoridad no auténticas y brindan respuestas concisas y ricas en entidades. Este tutorial crea un script de auditoría automatizado que compara sus páginas con los criterios clave de GEO: encabezados estructurados, esquema de preguntas frecuentes, bloques de respuestas concisos, ausencia de estadísticas fabricadas y estado actual de las citas de AI Overview. La auditoría utiliza la API de Scavio para comprobar si sus páginas ya aparecen en las descripciones generales de IA e identifica las lagunas.
Requisitos previos
- Python 3.9+ instalado
- solicitudes y bibliotecas beautifulsoup4 instaladas
- Una clave API de Scavio de scavio.dev
- Una lista de URL de destino o consultas para auditar
Guia paso a paso
Paso 1: Definir la lista de verificación de auditoría GEO
Cree una lista de verificación de señales de cumplimiento GEO para probarlas en cada página. Estos se asignan directamente a las recomendaciones de la guía GEO publicadas por Google.
import os, requests
from bs4 import BeautifulSoup
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'
GEO_CHECKS = [
'has_faq_schema',
'has_concise_answer_block',
'uses_structured_headings',
'no_fabricated_stats',
'has_entity_mentions',
'appears_in_ai_overview',
]
def fetch_page(url: str) -> BeautifulSoup:
resp = requests.get(url, timeout=10)
return BeautifulSoup(resp.text, 'html.parser')Paso 2: Verifique las señales GEO en la página
Analice el HTML de la página y compruebe el esquema de preguntas frecuentes, títulos estructurados, párrafos de respuesta concisos y contenido rico en entidades.
def audit_page_structure(soup: BeautifulSoup) -> dict:
results = {}
# FAQ schema check
scripts = soup.find_all('script', type='application/ld+json')
faq_found = any('FAQPage' in s.text for s in scripts)
results['has_faq_schema'] = faq_found
# Structured headings
h2s = soup.find_all('h2')
h3s = soup.find_all('h3')
results['uses_structured_headings'] = len(h2s) >= 2 and len(h3s) >= 1
# Concise answer blocks (paragraphs under 300 chars after an h2)
concise_blocks = 0
for h2 in h2s:
next_p = h2.find_next_sibling('p')
if next_p and len(next_p.get_text()) < 300:
concise_blocks += 1
results['has_concise_answer_block'] = concise_blocks >= 1
# Fabricated stats check
import re
text = soup.get_text()
suspicious = re.findall(r'\d{1,3}% of (?:users|companies|developers|people)', text)
results['no_fabricated_stats'] = len(suspicious) == 0
# Entity mentions
entities = len(re.findall(r'[A-Z][a-z]+ (?:API|SDK|framework|platform|tool)', text))
results['has_entity_mentions'] = entities >= 2
return resultsPaso 3: Verifique la presencia de AI Overview a través de SERP
Busque su consulta de destino y verifique si su dominio aparece en la sección Descripción general de AI de los resultados de SERP.
def check_ai_overview(query: str, target_domain: str) -> dict:
resp = requests.post(URL, headers=H,
json={'query': query, 'country_code': 'us', 'include_ai_overview': True})
data = resp.json()
ai_overview = data.get('ai_overview', {})
ai_text = ai_overview.get('text', '')
ai_sources = ai_overview.get('sources', [])
cited = any(target_domain in s.get('link', '') for s in ai_sources)
return {
'appears_in_ai_overview': cited,
'ai_overview_present': bool(ai_text),
'ai_sources_count': len(ai_sources),
}Paso 4: Ejecute la auditoría completa y genere un informe
Combine todas las comprobaciones en una única función de auditoría que califique cada página y genere un informe de aprobación/reprobación.
def audit_url(page_url: str, query: str, domain: str) -> dict:
soup = fetch_page(page_url)
structure = audit_page_structure(soup)
ai_check = check_ai_overview(query, domain)
structure.update(ai_check)
passed = sum(1 for v in structure.values() if v is True)
total = len(GEO_CHECKS)
structure['score'] = f'{passed}/{total}'
structure['url'] = page_url
print(f'GEO Audit: {page_url}')
for check in GEO_CHECKS:
status = 'PASS' if structure.get(check) else 'FAIL'
print(f' [{status}] {check}')
print(f' Score: {passed}/{total}')
return structure
audit_url('https://scavio.dev/tutorials/how-to-fetch-google-search-results',
'fetch google search results api', 'scavio.dev')Ejemplo en Python
import os, requests
from bs4 import BeautifulSoup
import re
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
def geo_audit(page_url, query, domain):
# Fetch page
soup = BeautifulSoup(requests.get(page_url).text, 'html.parser')
# On-page checks
scripts = soup.find_all('script', type='application/ld+json')
faq = any('FAQPage' in s.text for s in scripts)
h2s = soup.find_all('h2')
structured = len(h2s) >= 2
text = soup.get_text()
no_fake = len(re.findall(r'\d+% of (?:users|companies)', text)) == 0
# AI Overview check
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'query': query, 'country_code': 'us', 'include_ai_overview': True})
ai = resp.json().get('ai_overview', {})
cited = any(domain in s.get('link', '') for s in ai.get('sources', []))
checks = {'faq_schema': faq, 'structured_headings': structured,
'no_fabricated_stats': no_fake, 'ai_overview_cited': cited}
passed = sum(1 for v in checks.values() if v)
print(f'GEO Audit: {page_url}')
for k, v in checks.items():
print(f' [{"PASS" if v else "FAIL"}] {k}')
print(f'Score: {passed}/{len(checks)}')
geo_audit('https://scavio.dev', 'scavio search api', 'scavio.dev')Ejemplo en JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function geoAudit(query, domain) {
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, country_code: 'us', include_ai_overview: true })
});
const data = await resp.json();
const ai = data.ai_overview || {};
const sources = ai.sources || [];
const cited = sources.some(s => (s.link || '').includes(domain));
const organic = data.organic_results || [];
const inTop10 = organic.some(r => (r.link || '').includes(domain));
console.log(`GEO Audit for: ${query}`);
console.log(` AI Overview present: ${!!ai.text}`);
console.log(` Cited in AI Overview: ${cited}`);
console.log(` In organic top 10: ${inTop10}`);
console.log(` AI sources: ${sources.length}`);
}
geoAudit('search api for developers', 'scavio.dev');Salida esperada
GEO Audit: https://scavio.dev/tutorials/how-to-fetch-google-search-results
[PASS] has_faq_schema
[PASS] has_concise_answer_block
[PASS] uses_structured_headings
[PASS] no_fabricated_stats
[PASS] has_entity_mentions
[FAIL] appears_in_ai_overview
Score: 5/6