Monitoriza los AI Overviews de Google con Python: fuentes y cambios

Revisamos 100 consultas de Google en busca de AI Overviews el 19 de octubre de 2026: quién tiene uno, qué cita, qué tan estable es, y un tracker en Python que guarda snapshots.

Llama a /v1/serp y busca un objeto ai_overview en la respuesta. Si está, text_blocks contiene el texto del overview y references las páginas que cita; si falta, Google no mostró ninguno para esa consulta. Ejecutamos 100 consultas así el 19 de octubre de 2026: 57 tenían overview, citaban 7,5 fuentes de media, y cerca de dos tercios de los sitios citados también aparecían en la misma página de resultados. Al repetir 20 de ellas con minutos de diferencia, las fuentes citadas cambiaron mucho más a menudo que la presencia del overview.

Este post trata de los AI Overviews de la página de resultados normal. Para el AI Mode de Google, que es aparte, mira el post sobre AI Mode; para el seguimiento clásico de posiciones, mira cómo monitorizar rankings de palabras clave.

¿Cómo es un AI Overview en la respuesta de la API?

Es una clave ai_overview de primer nivel junto a organic_results. Lo que vimos el 19 de octubre de 2026:

  • ai_overview.text_blocks: una lista de objetos {type, snippet}. En los 57 overviews que recogimos, todos los bloques tenían el tipo paragraph, incluso los encabezados visuales, y el texto promediaba 232 palabras (de 88 a 415).
  • ai_overview.references: las páginas citadas, cada una con index, title, source (el nombre visible del sitio) y link. Los 425 enlaces eran URL absolutas, y 32 títulos contenían una etiqueta <b> literal, así que limpia el marcado antes de mostrarlos.
  • answer_box y peopleAlsoAskedFor no estaban vacíos exactamente en las 57 respuestas con overview, y llevan fragmentos de él (la primera frase, la primera referencia). Comprueba ai_overview en sí, no esos.

La documentación de Google dice que no hace falta ningún marcado especial para que te citen: la página debe estar indexada y ser elegible para snippets, y los clics se registran en el tipo normal de búsqueda web de Search Console (Search Central, funciones de IA, actualizado por última vez en diciembre de 2025). Por tanto, la presencia es algo que mides desde fuera, como hace el tracker de abajo.

¿Con qué frecuencia muestran las consultas un AI Overview?

Construimos 100 consultas, 20 por cada una de cinco intenciones, y ejecutamos cada una una vez con country=us, idioma por defecto, escritorio (hacia las 18:00 UTC del 19 de octubre de 2026). Cinco workers en paralelo tardaron unos 85 segundos.

Intención Consulta de ejemplo Con overview Porcentaje
Informacional how do vaccines work 19 de 20 95 %
Comercial best crm for small business 20 de 20 100 %
Navegacional netflix 14 de 20 70 %
Local plumber in austin tx 2 de 20 10 %
Desarrollador fix cors error 2 de 20 10 %
Todas 57 de 100 57 %

Las consultas con “how” y “best” casi siempre tuvieron uno. Los dos aciertos locales fueron “things to do in new orleans” y “pharmacy open 24 hours in atlanta”. Los seis fallos navegacionales fueron búsquedas de marca (chatgpt, youtube, netflix, linkedin, paypal login, walmart). Las consultas de desarrollador nos sorprendieron: solo “what is a webhook” y “http 429 too many requests” tuvieron uno. Con 20 consultas por intención, trata las diferencias de menos de unos 15 puntos como ruido.

¿Cuántas fuentes cita un AI Overview y coinciden con el top 10?

Un overview citó 7,5 fuentes de media (mediana 7, rango de 2 a 13). Comparamos cada sitio citado con los sitios de los organic_results de esa respuesta, que promediaron 8,9 resultados en lugar de diez completos.

Intención Fuentes (media) Sitios citados que también están en los resultados orgánicos URL citadas exactas que también están en los resultados orgánicos
Informacional 9,4 70 % 54 %
Comercial 7,2 66 % 44 %
Navegacional 5,8 70 % 49 %
Local (2 overviews) 5,5 90 % 73 %
Desarrollador (2 overviews) 5,5 45 % 36 %
Los 57 overviews 7,5 69 % 50 %

Todos los overviews compartían al menos un sitio con los resultados orgánicos, pero solo la mitad de las URL citadas exactas eran URL orgánicas. Posicionarte en la primera página hace probable una cita, no segura, y cerca de un tercio de los sitios citados no estaban en la página en absoluto. Sin contar YouTube, el solapamiento es del 68 %.

¿Qué dominios cita más Google?

Se citaron 243 sitios distintos en los 57 overviews. YouTube lideró por un amplio margen.

Sitio Overviews que lo citan Porcentaje de los 57
youtube.com 38 67 %
reddit.com 12 21 %
wikipedia.org 8 14 %
facebook.com 7 12 %
nytimes.com 6 11 %
cnet.com 5 9 %
mayoclinic.org, pcmag.com, rtings.com, apple.com 4 cada uno 7 %

YouTube apareció en 16 de los 19 overviews informacionales y en 18 de los 20 comerciales, pero solo en 3 de los 14 navegacionales. Un vídeo puede ser la cita, y los sitios de reseñas (nytimes, cnet, pcmag, rtings) se agrupan en las consultas “best X”.

¿Qué tan estable es un AI Overview entre ejecuciones?

Elegimos 20 de las 100 consultas de todas las intenciones (16 con overview en la primera pasada, 4 sin) y las ejecutamos dos veces más: aproximadamente un minuto después de la primera pasada, y cinco minutos después de eso.

Medida Resultado
Overview presente en las 3 ejecuciones 15 consultas
Overview ausente en las 3 ejecuciones 3 consultas
La presencia cambió 2 consultas (“facebook login” en 2 de 3, “netflix” en 1 de 3)
Mismo texto y mismas fuentes en las 3 ejecuciones 5 de 16
Solapamiento medio de URL citadas entre ejecuciones 72 %
Solapamiento medio de sitios citados entre ejecuciones 78 %
Similitud media del texto (a nivel de palabra) 64 %

Las últimas cuatro filas cubren las 16 consultas con overview en al menos dos ejecuciones. Cinco (entre ellas “best vpn” y “how do vaccines work”) volvieron idénticas palabra por palabra. Otras se movieron mucho: para “what causes inflation” el número de fuentes fue 10, 10, 8, y entre las dos últimas ejecuciones seis sitios salieron mientras congress.gov y youtube.com entraron. La presencia es bastante estable en cuestión de minutos; las fuentes y la redacción, no. Configura alertas para cuando aparece, desaparece o tu propio dominio entra o sale, no para los cambios de texto.

¿Cómo monitorizo los AI Overviews a diario en Python?

Este es el script que ejecutamos para el conjunto de datos. Guarda un snapshot por consulta y ejecución en SQLite e imprime qué cambió desde el anterior. Define WATCH_DOMAIN para que te avise cuando ganas o pierdes una cita.

import difflib, json, os, sqlite3, sys
from datetime import date
from urllib.parse import urlparse
import requests

API = "https://api.fastaf.co/v1"
KEY = os.environ["FASTAF_API_KEY"]
DB = os.environ.get("AIO_DB", "aio.db")
WATCH = os.environ.get("WATCH_DOMAIN", "")  # e.g. example.com


def host(url):
    return (urlparse(url).hostname or "").removeprefix("www.")


def parse(data):
    ao = data.get("ai_overview")
    return {
        "has_overview": ao is not None,
        "text": " ".join(b.get("snippet", "") for b in (ao or {}).get("text_blocks", [])).strip(),
        "sources": [{"title": s.get("title"), "source": s.get("source"), "link": s["link"]}
                    for s in (ao or {}).get("references", [])],
        "organic": [o["link"] for o in data.get("organic_results", [])],
    }


def cites(domain, sources):
    return any(host(x["link"]) == domain or host(x["link"]).endswith("." + domain) for x in sources)


def fetch(query, country="us"):
    r = requests.get(f"{API}/serp", params={"query": query, "country": country},
                     headers={"Authorization": f"Bearer {KEY}"}, timeout=90)
    r.raise_for_status()
    return parse(r.json())


def init(db=DB):
    conn = sqlite3.connect(db)
    conn.execute("""CREATE TABLE IF NOT EXISTS snapshots (
        snap TEXT, query TEXT, has_overview INTEGER, text TEXT, sources TEXT, organic TEXT,
        taken_at TEXT DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (snap, query))""")
    return conn


def save(conn, snap, query, s):
    conn.execute("INSERT OR REPLACE INTO snapshots (snap, query, has_overview, text, sources, organic) "
                 "VALUES (?,?,?,?,?,?)",
                 (snap, query, int(s["has_overview"]), s["text"],
                  json.dumps(s["sources"]), json.dumps(s["organic"])))
    conn.commit()

El informe compara los dos últimos snapshots:

def report(conn):
    snaps = [r[0] for r in conn.execute(
        "SELECT snap FROM snapshots GROUP BY snap ORDER BY MIN(taken_at) DESC LIMIT 2")]
    if len(snaps) < 2:
        return print("Need two snapshots to compare.")
    new, old = snaps
    q = "SELECT query, has_overview, text, sources FROM snapshots WHERE snap = ?"
    a = {r[0]: r[1:] for r in conn.execute(q, (old,))}
    b = {r[0]: r[1:] for r in conn.execute(q, (new,))}
    print(f"{old} -> {new}")
    for query in sorted(a.keys() & b.keys()):
        (had, t0, s0), (has, t1, s1) = a[query], b[query]
        if not had and has:
            print(f"APPEARED   {query}")
        elif had and not has:
            print(f"DISAPPEARED {query}")
        elif has:
            if WATCH and cites(WATCH, json.loads(s0)) != cites(WATCH, json.loads(s1)):
                print(f"{'GAINED' if cites(WATCH, json.loads(s1)) else 'LOST'} CITATION {query}")
            d0 = {host(x["link"]) for x in json.loads(s0)}
            d1 = {host(x["link"]) for x in json.loads(s1)}
            same = difflib.SequenceMatcher(None, t0.split(), t1.split(), autojunk=False).ratio()
            if d0 != d1 or same < 0.9:
                print(f"CHANGED    {query}: text {same:.0%} alike, +{sorted(d1 - d0)} -{sorted(d0 - d1)}")


if __name__ == "__main__":
    snap = sys.argv[1] if len(sys.argv) > 1 else date.today().isoformat()
    conn = init()
    for query in [q.strip() for q in open("queries.txt") if q.strip()]:
        s = fetch(query)
        save(conn, snap, query, s)
        print(f"{query}: {'overview, %d sources' % len(s['sources']) if s['has_overview'] else 'no overview'}")
    report(conn)

Extracto de la salida real al comparar nuestra segunda y tercera ejecución con WATCH_DOMAIN=youtube.com:

LOST CITATION best noise cancelling headphones
CHANGED    best noise cancelling headphones: text 21% alike, +['audiophileon.com'] -['youtube.com']
DISAPPEARED netflix
GAINED CITATION what causes inflation

autojunk=False importa: con el valor por defecto, los textos largos parecen mucho menos parecidos de lo que son.

¿Cuánto cuesta monitorizar los AI Overviews?

Una llamada a /serp son 5 créditos y el overview viene en la misma respuesta, así que el seguimiento no cuesta nada extra. Una pasada sobre 100 consultas son 500 créditos, exactamente la cuota gratuita, y unos 0,25 $ con el pack Starter (10 $ por 20.000 créditos). Las mismas 100 consultas a diario durante 30 días son 15.000 créditos, 7,50 $ a precios de Starter; mira los precios y la página de la SERP API. Dos llamadas extra el 19 de octubre de 2026 devolvieron HTTP 200 con X-FastAF-Credits-Used: 5, en 3,9 y 14,4 segundos, así que usa un timeout generoso, como hace el script.

¿Qué no muestran estos datos?

Un país (us), un idioma, escritorio, sin location, una tarde, y 100 consultas que escribimos nosotros, no una muestra de tráfico real. El solapamiento en local y desarrollador se apoya en 2 overviews cada uno. Google decide por usuario y por momento, así que lo que devuelve la API puede diferir de tu navegador, y la prueba de volatilidad abarca seis minutos. Repítelo con tus propias consultas antes de construir una estrategia sobre estas cifras.

En resumen

Comprueba ai_overview en la respuesta de /serp, guarda las references a diario en SQLite y configura alertas para cuando aparece, desaparece o tu dominio entra o sale de las citas. En nuestras 100 consultas, las de “how” y “best” casi siempre tuvieron un overview, las locales y las de desarrollador pocas veces, las fuentes se reordenaron mucho más que la presencia, y YouTube se citó en dos tercios de los overviews. Consigue 500 créditos gratis y pasa tu propia lista de consultas por el script; la documentación lista todos los parámetros de /serp.