Saltar al contenido

Buscadores de IA · 6 min de lectura

Por qué la IA no puede leer tu SPA de React.

Una SPA de React les manda a los rastreadores una página casi vacía, y puedes comprobarlo tú mismo en un minuto con curl.

Por Pedro CiordiaPublicado

Una persona saca una ficha de papel de un cajón de archivo para ponerla en un escáner encendido, mientras un portátil al lado muestra una larga lista de registros

En corto

Una single page application de React envía un cascarón de HTML casi vacío y pinta la página con JavaScript. Los rastreadores de IA como GPTBot, ClaudeBot o PerplexityBot solo leen ese HTML crudo, así que no ven nada. Polargate midió una tienda que servía 0 caracteres de texto legible a los rastreadores en 65 URL, y 105.212 caracteres tras la reconstrucción. Las tres soluciones son generación estática, renderizado en servidor y pre-renderizado.

Un rastreador de IA pide tu HTML y lee lo que le llega

Abres una single page application de React en el navegador y ves una página completa. Esa página no está en el fichero que envió el servidor. El servidor envió un cascarón: un <div id="root">, una etiqueta de script y cuatro metaetiquetas. El navegador descarga el bundle, lo ejecuta, llama a tu API y pinta todo lo que ves.

Lo que lee un visitante, y lo que recibe un rastreador de IA

Lo que lee un visitante, y lo que recibe un rastreador de IAUn sitio con JavaScript sirve la página entera al navegador que ejecuta su código, y un cascarón casi vacío a los rastreadores de IA que no lo ejecutan. Un sitio prerrenderizado sirve el mismo HTML completo a los dos.Un sitio con JavaScriptVisitante en unnavegadorejecuta el código, lo lee todo11.421El mismo sitioGPTBot, ClaudeBot,Perplexityno ejecuta el código14PrerrenderizadoVisitante en unnavegadorel mismo HTML completo11.421PrerrenderizadoLos mismos rastreadoresel mismo HTML completo11.421
Caracteres de texto de una noticia real, antes y después. Un asistente recomienda lo que ha podido leer, así que el segundo número es el que decide si sales en la respuesta.

GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, Claude-User y PerplexityBot no hacen nada de eso. Piden la URL, leen los bytes que llegan y siguen. Sin motor de JavaScript, sin esperar a la hidratación, sin llamar a tu API por ti. Lo que no esté en el HTML crudo, para ellos no existe.

Googlebot es la excepción que despista a todo el mundo: sí renderiza JavaScript, con retraso y con presupuesto limitado. Por eso una web renderizada en cliente puede posicionar de forma aceptable en Google y ser una página en blanco en todos los asistentes a los que pregunta tu comprador. En una web de hotel bilingüe que asumimos en junio de 2026, Google tenía indexadas solo 4 de unas 30 páginas antes de que la pre-renderizáramos.

Lo que falta en el HTML crudo suele ser más de lo que la gente espera:

  • El texto que se pinta tras la hidratación, incluidos tu H1 y tu primer párrafo.
  • Los textos que se piden en un useEffect a una API o a una base de datos en tiempo de ejecución.
  • Los paneles de pestañas y acordeones que solo se montan cuando están activos.
  • El JSON-LD que inyecta un helper en cliente en lugar de escribirse en el build.
  • Todo lo que quede detrás de un spinner, un aviso de cookies o un disparador de scroll.

Comprueba tu web en dos minutos

No te fíes de nadie en esto, tampoco de nosotros. Apunta curl a tu propia página con un user agent de rastreador y cuenta lo que vuelve.

Primero, descarga la página tal y como la ve GPTBot:

curl -s -A "GPTBot/1.2 (+https://openai.com/gptbot)" https://example.com/ -o crawler.html
wc -c crawler.html

El tamaño en bytes engaña, así que mide texto, no bytes. En una web que auditamos, el cascarón pesaba 3.559 bytes y no contenía ni un carácter legible. Esto cuenta los caracteres que un modelo podría leer:

python3 - <<'PY'
import re
h = open('crawler.html').read()
h = re.sub(r'(?is)<script.*?</script>', ' ', h)
h = re.sub(r'(?is)<style.*?</style>', ' ', h)
t = re.sub(r'(?s)<[^>]+>', ' ', h)
print(len(' '.join(t.split())), 'characters of readable text')
PY

Una página real de contenido da miles. Un cascarón vacío da unos cientos, y casi todos son tu meta description. Después, comprueba que la página dice lo que es:

grep -Eio '<title>[^<]*|<h1[^>]*>[^<]*' crawler.html
grep -c 'application/ld+json' crawler.html

Luego asegúrate de que nada en el borde está rechazando a los bots en silencio. Las reglas de firewall y la protección antibots devuelven un 403 o un reto de JavaScript que ningún rastreador de IA sabe resolver, y tu analítica no te lo va a contar:

for ua in "Mozilla/5.0" "GPTBot/1.2" "OAI-SearchBot/1.0" "ClaudeBot/1.0" "PerplexityBot/1.0"; do
  printf '%-22s ' "$ua"
  curl -s -o /dev/null -w '%{http_code}\n' -A "$ua" https://example.com/
done

Todas las líneas deberían dar 200. Por último, barre la web entera en vez de una URL afortunada, y ordena las peores páginas arriba:

curl -s https://example.com/sitemap.xml | grep -oE '<loc>[^<]+' | cut -c6- |
while read -r url; do
  n=$(curl -s -A "OAI-SearchBot/1.0" "$url" | sed -E 's/<[^>]+>/ /g' | tr -s ' ' | wc -c)
  echo "$n  $url"
done | sort -n | head -20

Cómo se ve un cero

En el verano de 2026 reconstruimos el comercio electrónico de una marca española de mesa y hogar. Cuando medimos la web antigua igual que acabas de hacer tú, el resultado no fue "contenido pobre": en las 65 URL públicas, las páginas servían 0 caracteres de texto legible a los rastreadores de IA. Nombres de producto, precios, descripciones de serie, condiciones de envío, todo llegaba solo después de ejecutar JavaScript.

Tras la reconstrucción, el mismo barrido del 4 de agosto de 2026 devolvió 105.212 caracteres en esas mismas 65 URL. No se escribió nada para robots: es el mismo texto que lee una persona, movido de tiempo de ejecución al fichero HTML. Ese es todo el truco, y es la única medición de este artículo que hicimos nosotros mismos.

Las tres formas de arreglarlo

Generación estática, la opción por defecto

En el build renderizas cada ruta a un fichero HTML real. Con Vite y React, vite-react-ssg lo hace sin salirte de tu stack: exportas las rutas, defines getStaticPaths para los segmentos dinámicos y el build escribe dist/precios/index.html con el texto ya dentro. La web sigue siendo una SPA una vez hidratada, así que la navegación se mantiene instantánea.

Úsala cuando la lista de rutas se conoce en el build: webs de marca, páginas de servicio, blogs, documentación, catálogos. Que el contenido cambie a diario no lo impide: un deploy hook programado lo reconstruye. El catálogo de mesa y hogar funciona así, con un refresco diario.

Renderizado en servidor, cuando la página depende de la petición

Next.js, Remix o un montaje SSR con Vite generan el HTML en cada petición. Lo necesitas cuando la página no se puede conocer de antemano: stock en vivo de miles de referencias, resultados de búsqueda, cualquier cosa detrás de un login. El precio es un servidor en marcha, diseño de caché y más formas de romperse a las tres de la mañana. No adoptes SSR porque suene más moderno que la generación estática. Adóptalo cuando el contenido dependa de quién pregunta.

Pre-renderizado para rastreadores en el borde, el parche

Cuando una SPA grande no se puede reestructurar ahora, un middleware en el borde puede servir a los rastreadores un cuerpo HTML real mientras las personas siguen con la aplicación intacta. Lo usamos en una web corporativa con unas 700 noticias: el middleware detecta al bot, devuelve el H1, el cuerpo del artículo y el JSON-LD, y el resto recibe la SPA.

Dos condiciones lo hacen seguro. El texto que sirves a los bots tiene que ser el mismo que ve una persona, verificado con una prueba de paridad automática en CI; si no, es cloaking. Y trátalo como un puente, no como un destino, porque a partir de ahí mantienes dos caminos de renderizado.

Cuál eliges

  • Ruta conocida en el build y contenido que cambia como mucho a diario: generación estática.
  • Contenido que depende de la petición o del usuario: renderizado en servidor.
  • SPA grande que no puedes reconstruir este trimestre: pre-renderizado en el borde, con prueba de paridad.

Lo que no lo arregla

  • Un fichero llms.txt. Los asistentes de consumo no lo piden y Google lo ignora. Sirve para agentes de código, no para visibilidad.
  • El JSON-LD por sí solo. En un estudio de Ahrefs de 2026 sobre 1.885 páginas frente a 4.000 de control, añadir schema no produjo mejora apreciable en AI Overviews, AI Mode ni ChatGPT. El texto visible es la capa principal y los datos estructurados lo reflejan.
  • Escribir "para la IA": trocear páginas en fragmentos, copias en markdown solo para modelos, tipos de schema inventados. La guía de Google de 2026 dice que no ayudan, y las páginas solo para IA son un riesgo de cloaking.
  • Poner nosnippet o max-snippet:0 en páginas que quieres que te citen. Eliminan justo la elegibilidad que intentas ganar.

Verifica, y sigue verificando

Repite el barrido después de desplegar y deja una versión en CI, para que ninguna refactorización vuelva a sacar el texto del HTML en silencio. Mira los registros del servidor, no tu analítica: los rastreadores no ejecutan JavaScript, así que GA4 y Plausible no los ven nunca, y los logs de Vercel o Cloudflare filtrados por user agent son el único registro fiable de si los bots han vuelto.

Si prefieres que alguien lo mida y lo arregle contigo, Polargate lo hace dentro de un Discovery Sprint de pago y precio cerrado. En cualquier caso, ejecuta antes los comandos de curl. El número que salga no es una opinión.

Tu caso

Cuéntanos tu proyecto.

En una llamada corta te decimos cómo se aplica esto a tu proyecto, y después te llega un presupuesto por escrito.

Por ejemplo: ~2.500 peticiones de huésped atendidas en cuatro meses en Santo Domingo Bay. Estevano

FAQ

Preguntas sobre el artículo.

¿Cómo compruebo si ChatGPT puede ver mi web?
Descarga la página con un user agent de rastreador y cuenta texto, no bytes. Ejecuta curl con -A "GPTBot/1.2" contra tu URL, guarda la respuesta, quita las etiquetas y cuenta los caracteres que quedan. Una página real de contenido devuelve miles de caracteres legibles. Un cascarón de React devuelve unos cientos, casi todos de tu meta description. Repítelo en todas las URL del sitemap, porque una sola página no demuestra nada.
¿Google indexa las single page applications de React?
Sí, pero despacio y a menudo de forma parcial. Googlebot renderiza JavaScript con retraso y con un presupuesto de rastreo, así que las páginas renderizadas en cliente se indexan tarde o no se indexan. En una web de hotel bilingüe que Polargate asumió en junio de 2026, Google tenía indexadas solo 4 de unas 30 páginas antes de pre-renderizarla. Los asistentes de IA son aún más estrictos: no renderizan JavaScript nunca.
¿SSG o SSR: cuál necesito para que la IA me lea?
Generación estática para casi todo. Si la lista de rutas se conoce en el build y el contenido cambia como mucho a diario, la generación estática escribe un HTML real por página y no cuesta nada mantener. Elige SSR solo cuando la página dependa de la petición o del usuario: stock en vivo de miles de referencias, resultados de búsqueda, vistas con login. Ambas hacen visible tu texto, pero el SSR cuesta más de operar.
¿Un fichero llms.txt hace visible mi web para la IA?
No. Los asistentes de consumo no piden llms.txt, Google lo ignora y ningún estudio muestra que aumente las citas. Sirve para agentes y herramientas de código, no para la búsqueda con IA. Lo que decide si un asistente puede citarte es si tu texto visible está en la respuesta HTML cruda. Arregla primero el renderizado y luego dedica tiempo a extras como los datos estructurados.
¿Servir un HTML distinto a los rastreadores de IA es cloaking?
Solo si el contenido es distinto. Servir un cuerpo pre-renderizado a los bots mientras las personas reciben la aplicación es aceptable si ambos ven el mismo texto. Polargate lo despliega con una prueba de paridad automática en CI que compara la respuesta al rastreador con la página renderizada y rompe el build si divergen. Servir a los bots contenido que las personas no ven sí es cloaking y puede acarrear una acción manual.

Por ejemplo: 99 tests automáticos escritos para el módulo, partiendo de cero. NationwideLegal

Sigue leyendo

Más del estudio.

Si un texto te deja una duda sobre tu proyecto, te la resolvemos en una llamada corta.

Por ejemplo: 6 cabeceras de seguridad habituales que faltaban antes del trabajo. Empresa de servicios B2B, Europa

Empezar

Cuéntanos qué quieres construir.

Webs, apps, sistemas a medida e IA para empresas que los necesitan en producción en semanas. Rellena el formulario o reserva una llamada de 30 minutos: un ingeniero senior responde en 48 horas laborables con una primera lectura de alcance, plazo y precio.

¿Qué necesitas?
Presupuesto
Plazo

Al menos diez caracteres.

Respuesta por escrito en 48 horas laborables. Sin boletines ni correos automáticos.

¿Prefieres el encargo completo?

Primer paso

Discovery Sprint

Dos semanas para cerrar alcance, arquitectura y precio antes de construir nada.

Sin lista de precios. Recibes un presupuesto privado, por escrito, tras una llamada corta.

Después, para construir, siempre a precio cerrado

¿Aún no es el momento?

Estudio digital nativo en IA para empresas medianas

POLARGATE, S.L. · CIF B24895005
Calle Electrónica 6, 28027 Madrid, España