Voy a empezar por la opinión que le va a molestar a media industria: el GEO no es el SEO de siempre con un bloque de FAQ y cuatro líneas de schema. Y sí, es algo que me ha costado a mí también, eso sí, para ser un buen GEO será fundamental ser un gran SEO.. El cambio de fondo es que un buscador clásico rastreaba, indexaba y te ordenaba en una lista (clasificación); un motor de respuesta recupera fragmentos, los sintetiza y ahí entra un juego de probabilidades, además que lo que sucede fuera de tu dominio ahora adquiere otra dimensión más allá de la pura autoridad, share of voice, sentiment... son aspectos que cobran aún más relevancia.
Este post es la versión larga y técnica de lo que llevo montando en proyectos reales: cómo funciona lo que hay detrás de ChatGPT, AI Overviews, AI Mode o Gemini, y cómo instrumentar todo eso con scripts propios o con Screaming Frog para tomar decisiones que muevan negocio, no para rellenar un informe de vanity metrics.
El motor no rankea, recupera: la tubería por dentro
Cuando le preguntas algo a un motor de respuesta, por debajo pasa casi siempre una variante de este pipeline RAG (Retrieval-Augmented Generation): tu pregunta se convierte en un vector, se busca por similitud contra un corpus troceado, se reordenan los candidatos, y un modelo redacta la respuesta condicionado a esos fragmentos. Desmenuzo cada pieza porque cada una tiene una consecuencia SEO directa.
- Embeddings y distancia coseno. Un embedding es la representación de un texto como un vector en un espacio de muchas dimensiones donde lo semánticamente parecido queda cerca. Los modelos de OpenAI devuelven vectores de longitud fija —
text-embedding-3-smalltiene 1.536 dimensiones ytext-embedding-3-large, 3.072— y ya vienen normalizados a longitud 1, así que la similitud coseno se calcula como un simple producto escalar. La coseno va de -1 a 1: cuanto más cerca de 1, más parecido. No es un porcentaje de "acuerdo"; es una medida relativa que solo cobra sentido comparándola contra tu propio corpus. Esto no es teoría de laboratorio: es exactamente la lógica con la que el motor decide si tu pasaje se parece a la intención de la query. - Chunking. El corpus no se indexa por documentos, se indexa por fragmentos. Tu página se parte en chunks y cada chunk se embebe por separado; la recuperación opera sobre chunks. Un chunk que mezcla tres temas diluye su vector y pierde precisión. Traducción a on-page: encabezados limpios, y sobre todo pasajes autoconclusivos que respondan una pregunta entera sin depender de un párrafo que está 600 palabras más arriba. Contenido "chunk-friendly" es contenido que sigue teniendo sentido cuando lo arrancas del resto de la página, porque es justo así como el motor lo va a usar.
- Reranking. La recuperación es un embudo de dos fases. Primero un retriever denso trae rápido un montón de candidatos por similitud vectorial; después un reranker (a menudo un cross-encoder, a veces otro LLM) los reordena por relevancia fina a la intención. Un chunk con altísima similitud puede caerse en el reranking si no responde directo. Moraleja: no basta con "parecerte" a la query, hay que ser el fragmento que mejor la contesta.
- Grounding. Es anclar la respuesta en fuentes recuperadas en vivo en lugar de solo en la memoria del modelo. Reduce alucinaciones y es lo que permite las citas. Pero ojo con venderlo como infalible: un estudio de Nature Communications (Wu et al., 2025) encontró que entre el 50% y el 90% de las respuestas de LLM no están totalmente respaldadas por las fuentes que citan, y que incluso GPT-4o con búsqueda web deja ~30% de afirmaciones sin soporte. El grounding recorta el problema; no lo elimina. Eso, para un SEO, es una oportunidad: hay hueco para ser la fuente limpia y citable que el motor prefiere.
Query fan-out: por qué ya no optimizas "una keyword"
Esta es la parte que más gente ignora y la que más cambia el trabajo. Ante una consulta, el sistema no lanza una búsqueda: usa un LLM para descomponer tu pregunta en un abanico de sub-consultas sintéticas —relacionadas, implícitas, comparativas, recientes— que ejecuta en paralelo y luego sintetiza en una sola respuesta. Google lo confirmó al presentar AI Mode: su técnica de query fan-out parte la pregunta en subtemas y dispara muchas búsquedas simultáneas para "bajar más hondo" en la web que una búsqueda tradicional.
Ejemplo: "auriculares bluetooth cómodos con buena batería" no se resuelve con una SERP. Se abre en sub-consultas de comodidad (over-ear vs in-ear), de autonomía real, comparativas por marca (Sony vs Bose vs Sennheiser), reviews de usuario, precio, cancelación de ruido… y de ese pool ampliado se compone la respuesta. La unidad de optimización deja de ser la keyword y pasa a ser el clúster de intención. Si solo rankeas la cabecera, apareces en una rama del abanico y desapareces en las otras diez.
Lo potente es que el fan-out se puede simular. Le pides a un modelo que reproduzca la descomposición y luego mides, con embeddings, qué sub-consultas cubre tu contenido y cuáles son un agujero. Eso lo tienes en código más abajo.
Source attribution: quién se lleva la cita (y por qué casi nunca es quien crees)
Aquí es donde el sentido común del SEO clásico se rompe. Según Ahrefs (sobre 863.000 keywords), solo alrededor del 38% de las citaciones de AI Overviews venían del top 10 orgánico, cuando un año antes eran el 76%. Ranquear ya no te garantiza que te citen. Y entre motores el solape de dominios citados es bajísimo: se ha reportado que ChatGPT y Perplexity coinciden en apenas ~11% de fuentes. Cada motor es un canal distinto con sus manías.
¿Qué correlaciona de verdad con que te citen? Los datos apuntan, una y otra vez, a las señales de marca fuera de tu sitio. En el análisis de Ahrefs sobre 75.000 marcas, los mejores predictores de visibilidad en AI Overviews fueron las menciones en YouTube (correlación de Spearman ~0.737) y las menciones de marca en la web (~0.664), muy por encima de los backlinks (~0.218). Es decir, las menciones pesan del orden de 2-3 veces más que los enlaces. Con la advertencia honesta de siempre: correlación no es causalidad, esto no prueba que forzar menciones cause citas. Pero la señal es demasiado consistente para ignorarla.
Lo demás que sí tiene evidencia: densidad de evidencia (estadísticas, cifras concretas, definiciones directas) correlaciona con ser citado; la frescura importa mucho en Perplexity; y cada motor tira de fuentes distintas —ChatGPT se apoya fortísimo en Wikipedia, Perplexity históricamente en Reddit, AI Overviews reparte más—. Profound lo cuantificó analizando 680 millones de citaciones. Todo esto se mueve mes a mes, así que trátalo como una foto con fecha de caducidad, no como una ley.
Y ahora lo que no funciona, para que no pierdas el tiempo. El keyword stuffing rinde peor que no tocar nada. El schema ayuda a resolución de entidad donde se confirma su uso, pero no dispara citaciones por sí solo. Y el llms.txt es humo: ningún sistema de IA en producción lo usa —lo dijo John Mueller sin ambigüedad, y Ahrefs analizó 137.000 dominios y el 97% de esos ficheros no recibió ni una sola petición—. Si alguien te lo vende como palanca de visibilidad, sabes con quién no trabajar.
La única receta con respaldo académico serio es la del paper que acuñó el término, "GEO: Generative Engine Optimization" (Aggarwal et al., Princeton/Georgia Tech, KDD 2024): añadir citas de fuentes, estadísticas y quotes subió la visibilidad entre un 30% y un 40%. Con matices —era un entorno idealizado de un solo actor, hay trabajos posteriores que lo discuten en escenarios competitivos, y ese "40%" es un máximo, no una media—. Pero la dirección es sólida: sustancia citable, no formato. (Dato meta: este mismo artículo está escrito así a propósito. Frases con dato, fuente nombrada y pasajes que se sostienen solos. Predico con el ejemplo.)
Bajando al barro: scripts propios con embeddings
Todo lo anterior se puede instrumentar. No necesitas una suite de 500€/mes para empezar; con la API de embeddings de OpenAI (a ~0,02$/millón de tokens el 3-small, es casi gratis) y cuatro líneas de Python tienes un laboratorio. Cuatro utilidades que uso.
1. Detectar canibalización a escala, antes que Google. Embebe el contenido de tus URLs y calcula la matriz de similitud coseno. Los pares por encima de tu umbral son páginas peleándose por la misma intención semántica. Esto lo detectas de forma proactiva, sin esperar a que el buscador decida por ti cuál entierra.
import numpy as np
from openai import OpenAI
from sklearn.metrics.pairwise import cosine_similarity
client = OpenAI()
paginas = { # {url: texto_principal}
"/consultoria-seo/": "…",
"/seo-tecnico/": "…",
"/servicios/geo/": "…",
}
urls, docs = list(paginas), list(paginas.values())
resp = client.embeddings.create(model="text-embedding-3-small", input=docs)
vecs = np.array([d.embedding for d in resp.data]) # normalizados (L2 = 1)
sim = cosine_similarity(vecs)
UMBRAL = 0.86 # calíbralo con tu corpus: 3-small y 3-large NO comparten escala
for i in range(len(urls)):
for j in range(i + 1, len(urls)):
if sim[i, j] >= UMBRAL:
print(f"{sim[i,j]:.3f} canibalización {urls[i]} ↔ {urls[j]}")2. Simular el retriever: ¿qué pasaje tuyo recuperaría el motor? Embebe la query objetivo y los chunks de tu página, ordena por coseno y mira qué fragmento saldría elegido. Es una aproximación cruda al retriever real, pero te dice en 20 segundos si tu "respuesta directa" está donde el motor la buscaría o enterrada al final.
def trocear(texto):
# chunking naíf por párrafos; en producción, splitter con solape
return [p.strip() for p in texto.split("\n\n") if p.strip()]
query = "mejor consultor SEO para SaaS en España"
chunks = trocear(open("pagina.txt").read())
emb = client.embeddings.create(
model="text-embedding-3-small",
input=[query] + chunks
)
v = np.array([d.embedding for d in emb.data])
q, C = v[0], v[1:]
scores = C @ q # dot = coseno (vectores normalizados)
for s, ch in sorted(zip(scores, chunks), reverse=True)[:5]:
print(f"{s:.3f} {ch[:90]}…")3. Simular el query fan-out y medir cobertura. Le pides a un modelo que reproduzca la descomposición y luego cruzas cada sub-consulta contra tus chunks. Las sub-consultas con coseno bajo son huecos de contenido: intención que el abanico va a buscar y que tú no cubres. Ese listado de huecos es, literalmente, tu backlog de contenido priorizado por cómo funciona el motor.
import json
prompt = """Descompón esta consulta como un motor de respuesta con IA
(query fan-out): 12 sub-consultas — implícitas, comparativas, de producto
y recientes. Devuelve solo JSON: {"subqueries": ["…"]}.
Consulta: "auriculares bluetooth cómodos con buena batería"."""
r = client.chat.completions.create(
model="gpt-5.1",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"},
)
subs = json.loads(r.choices[0].message.content)["subqueries"]
sub_emb = np.array([d.embedding for d in
client.embeddings.create(model="text-embedding-3-small", input=subs).data])
cobertura = sub_emb @ C.T # cada subquery contra cada chunk tuyo
mejor = cobertura.max(axis=1) # mejor chunk por subquery
for sub, m in sorted(zip(subs, mejor), key=lambda x: x[1]):
flag = "HUECO" if m < 0.30 else "ok"
print(f"{m:.3f} {flag} {sub}")4. Puntuar citabilidad. Con lo que sabemos de source attribution, monta un scorer que marque, chunk a chunk, si arranca con una respuesta directa (BLUF), si tiene al menos un dato o cifra, si cita una fuente y si es autoconclusivo. No es ciencia exacta, es un semáforo para priorizar reescrituras. Un chunk que puntúa 0/4 es un candidato a no ser citado jamás por mucho que ranquee.
Screaming Frog como laboratorio GEO
Si no quieres montar todo el pipeline en Python, Screaming Frog es el atajo más infravalorado. Desde la v22 trae embeddings y similitud semántica nativos, y desde antes te deja meter la mano donde haga falta. Tres montajes que hago con él:
- Canibalización a escala de sitio sin escribir código. Con la similitud semántica de la v22 cruzas todas tus URLs por cercanía de embedding y sacas los pares sospechosos directamente en la interfaz. Si prefieres el control fino, exportas los embeddings y les pasas la matriz coseno del script 1.
- Embeddings en el propio crawl vía Custom JavaScript. En
Configuration > Custom > JavaScriptpuedes inyectar un snippet que llame a la API de OpenAI y guarde el vector de cada URL mientras rastrea. Terminas el crawl con un embedding por página listo para clusterizar, medir distancia a tus queries objetivo o alimentar el detector de canibalización. - Auditar la "extraibilidad" con Custom Extraction. Con XPath o CSSPath extraes la estructura de cada página —el primer párrafo (tu supuesta respuesta directa), los H2/H3, el JSON-LD, el número de palabras por sección— y detectas de un vistazo qué páginas están montadas en bloques recuperables y cuáles son un muro de texto sin puntos de anclaje. Cruza eso con el informe de Near Duplicates y con los datos de GSC/GA4 conectados, y tienes el mapa de qué reescribir primero por impacto.
La gracia es combinar las dos vías: Screaming Frog para el barrido masivo y la foto del sitio; Python para el análisis fino y la simulación del fan-out. Una cosa alimenta a la otra.
Monitorizar la visibilidad en IA: Peec AI, LLM Pulse y lo que puedes montar tú
Todo lo anterior te dice cómo estás construido. Para saber si apareces en las respuestas —y cómo evoluciona frente a tus competidores— necesitas monitorización continua sobre un set de prompts comerciales. Aquí es donde entran las herramientas de la categoría, y donde conviene tener criterio porque hay muchas y miden cosas parecidas de formas distintas.
Peec AI la uso como monitor de visibilidad y share of voice: defines tus prompts, y te devuelve con qué frecuencia apareces, tu SoV frente a competidores, el sentimiento y qué fuentes está citando cada motor. Tiene residencia de datos en la UE y seats ilimitados, lo que para agencias y equipos europeos es cómodo. Los planes base cubren ChatGPT, Perplexity y AI Overviews, y añades Gemini/Claude como extra. Es sólida en lo que hace —monitorizar— aunque no ejecuta acciones por ti.

LLM Pulse —hecha en España, por cierto— la meto cuando quiero rastrear menciones, fuentes de citación y sentimiento a través de un abanico más amplio de modelos, y sobre todo por su capa de automatización: trae servidor MCP, API REST y analítica de tráfico de bots de IA a nivel de servidor. Ese último punto es oro para reporting, porque te deja ver los crawlers de IA que pasan por tu web antes incluso de que la visibilidad se traduzca en tráfico. Correr las dos en paralelo un tiempo, además, te enseña algo importante: para la misma query te dan lecturas distintas, porque los LLM son no deterministas y cada herramienta parsea diferente. No hay una "verdad"; hay tendencias.

¿Y qué puedes montarte tú? Un monitor de SoV mínimo: pasas tu set de prompts por la API de un modelo con búsqueda web activada y parseas menciones de marca. No sustituye a las herramientas —para trackear los motores de consumo reales (la app de ChatGPT, AI Overviews) hay que scrapear la interfaz o tirar de Peec/LLM Pulse, que es justo lo que productizan—, pero para un baseline rápido y barato cumple.
MARCAS = ["MiMarca", "Competidor A", "Competidor B"]
PROMPTS = [
"¿Mejor consultor SEO para ecommerce en España?",
"Recomiéndame una agencia de GEO en Madrid",
# … tu set comercial completo, por fase del funnel
]
conteo = {m: 0 for m in MARCAS}
for p in PROMPTS:
r = client.chat.completions.create(
model="gpt-5.1",
messages=[{"role": "user", "content": p}],
# activa la herramienta de búsqueda web del proveedor para
# replicar el grounding real del motor
)
texto = r.choices[0].message.content.lower()
for m in MARCAS:
if m.lower() in texto:
conteo[m] += 1
total = sum(conteo.values()) or 1
for m, c in conteo.items():
print(f"{m}: {c}/{len(PROMPTS)} · SoV {100*c/total:.0f}%")De vanity a revenue: cómo se reporta esto
Nada de lo anterior vale si acaba en un informe de "menciones totales". El número de menciones es una vanity metric. Lo que un comité de dirección compra es la cadena completa: visibilidad/SoV en IA → tráfico de IA por motor → conversión y revenue de ese canal. Y para eso lo primero es dejar de perder el tráfico de IA en el cajón de "Directo".
En GA4, por defecto, las visitas desde ChatGPT o Perplexity caen en "Referral" o directamente en "Direct" (parte llega sin referrer, el famoso dark traffic). Monta un channel group propio con una regex sobre el referrer para aislarlo:
chatgpt\.com|openai\.com|perplexity\.ai|gemini\.google|
copilot\.microsoft|claude\.ai|.*\.ai$Con el canal aislado, el argumento de negocio se cae por su peso, porque el tráfico de IA es poco pero de altísima intención: Adobe midió que convertía un 42% mejor que el tráfico no-IA, y Ahrefs reportó un caso donde el 0,5% de sesiones desde IA generaba el 12% de los registros —un techo del orden de 23x—. Cifras de fuentes y metodologías distintas, no comparables entre sí, y hoy la IA sigue siendo ~1% de las sesiones. Pero la dirección es inequívoca: no vendes volumen, vendes calidad de tráfico. Ese es el titular para dirección.
Así que el cuadro de mando que yo llevaría a un cliente no tiene "menciones". Tiene: SoV en IA por motor, tasa de citación por tipo de prompt, tráfico de IA aislado en su canal, y conversión y pipeline atribuidos a ese canal. Lo demás es ruido bonito.
Si te has fijado, todo esto encaja en un bucle: entiendes la tubería, te construyes las herramientas para verla, actúas sobre el contenido y las señales de entidad, monitorizas el SoV y lo atas a revenue. No hay un truco. Hay entender el sistema por dentro y trabajar en consecuencia — que es, al final, lo único que ha funcionado siempre en SEO, solo que ahora el sistema recupera en vez de rankear