# Tutorial: ¿Tu sitio web es visible para las Inteligencias Artificiales?
23 de febrero de 2026 — Alessandro Caprai
---
## Guía práctica para verificar y optimizar la accesibilidad de tu sitio por parte de los Large Language Models
***Método***: Basado en pruebas reales realizadas en sitios en producción con Claude, ChatGPT, Gemini y Perplexity*
Los Large Language Models (LLM) como Claude, ChatGPT, Gemini y Perplexity se están convirtiendo en un canal de descubrimiento y tráfico cada vez más relevante para los sitios web. Sin embargo, la forma en que estos sistemas acceden a los contenidos es profundamente diferente tanto de los navegadores tradicionales como de los motores de búsqueda clásicos.
Un sitio perfectamente indexado en Google puede resultar **completamente invisible** a los LLM. Los motivos son múltiples: firewall del hosting, configuración errónea del robots.txt, contenido renderizado solo vía JavaScript, sitemap ilegibles, caché envenenadas de los crawlers.
Esta guía proporciona un recorrido estructurado en 9 niveles para diagnosticar y resolver cada posible punto de bloqueo. Cada prueba ha sido verificada en el campo.
### SEO vs GEO: por qué se necesita una nueva perspectiva
El SEO tradicional (Search Engine Optimization) se centra en la visibilidad en los resultados de los motores de búsqueda. La **GEO** (Generative Engine Optimization) extiende este concepto al ecosistema de la inteligencia artificial generativa: cómo hacer que los LLM encuentren, lean y citen correctamente tus contenidos.
La GEO no sustituye al SEO, lo integra. Un sitio optimizado para la GEO es también un sitio con un SEO más sólido, porque muchos de los requisitos son compartidos: contenido accesible, estructura clara, metadatos coherentes. Pero la GEO añade requisitos específicos — como la legibilidad por parte de crawlers que no ejecutan JavaScript, la compatibilidad de los Content-Type con las herramientas de los LLM, la exposición explícita de las relaciones entre contenidos multilingües, y la adopción de protocolos emergentes como **llms.txt** para comunicarse directamente con los modelos de lenguaje.
---
## Nivel 1 — Firewall y Bot Protection del hosting
### Qué verificar
El primer y más insidioso nivel de bloqueo. Muchos hostings modernos ofrecen sistemas de protección bot que bloquean el tráfico no-navegador **antes incluso de que llegue a tu servidor**. El bloqueo ocurre de forma silenciosa: no verás nada en tus logs aplicativos.
Esto es particularmente crítico porque el bloqueo puede generar una **caché envenenada** en el crawler del LLM: si el crawler es bloqueado una vez, podría memorizar el bloqueo y no volver a intentarlo durante días o semanas, incluso después de que hayas corregido la configuración.
### Plataformas involucradas
| Plataforma | Dónde controlar |
|------------|----------------|
| Vercel | Dashboard → Proyecto → Firewall → Rules → Bot Management |
| Cloudflare | Dashboard → Security → Bots |
| Netlify | Site settings → Security (si está presente) |
| AWS CloudFront | WAF → Web ACLs → Bot Control |
| Hosting tradicional | Panel del firewall aplicativo (ModSecurity, etc.) |
### Pruebas a ejecutar
**1.1 — Verifica Bot Protection genérica**
Accede al panel de tu hosting y comprueba si existen protecciones bot activas. Busca dos tipos de protección, a menudo configurables por separado:
- **Bot Protection genérica** — bloquea todo el tráfico no-navegador (headless requests, curl, scripts automatizados)
- **AI Bots Managed Ruleset** — bloquea específicamente los crawlers de los LLM (ClaudeBot, GPTBot, etc.)
Si quieres que los LLM accedan a tu sitio, configura ambos en **"Log"** (monitoreo sin bloqueo) en lugar de "Block" o "Challenge".
**1.2 — Verifica en los logs en vivo**
Esta es la prueba diagnóstica clave. Pide a un LLM (ej. Claude, ChatGPT) que acceda a una página específica de tu sitio, luego comprueba inmediatamente los logs en vivo del firewall:
- Si **ves la solicitud en los logs** → el bloqueo es a nivel aplicativo (robots.txt, middleware, respuesta del servidor)
- Si **no ves ninguna solicitud** → el bloqueo ocurre a nivel de firewall/infraestructura, o bien el LLM está usando una respuesta cacheada y la solicitud ni siquiera parte
**1.3 — Verifica WAF y reglas personalizadas**
Comprueba si tienes reglas WAF personalizadas que bloquean user-agents específicos. Los principales user-agents de los LLM son:
| LLM / Servicio | User-Agent |
|----------------|------------|
| Claude (Anthropic) | `ClaudeBot` |
| ChatGPT (OpenAI) | `GPTBot`, `ChatGPT-User` |
| Gemini (Google) | `Google-Extended` |
| Perplexity | `PerplexityBot` |
| Apple AI | `Applebot-Extended` |
| Microsoft Copilot | `Bingbot` (compartido con Bing Search) |
| Meta AI | `FacebookBot` |
| Common Crawl (usado por muchos LLM) | `CCBot` |
**1.4 — Test con User-Agents específicos**
Verifica desde tu terminal que el servidor responda correctamente a los diferentes user-agents:
```bash
# Test con User-Agent de Claude
curl -I -H "User-Agent: ClaudeBot" https://tusitio.com/
# Test con User-Agent de ChatGPT
curl -I -H "User-Agent: GPTBot" https://tusitio.com/
# Comparación con User-Agent navegador estándar
curl -I -H "User-Agent: Mozilla/5.0" https://tusitio.com/
```
Si los user-agents LLM reciben respuestas diferentes (403, 503, redirect a challenge), el firewall los está bloqueando.
### Señales de problema
- El LLM devuelve "no puedo acceder" pero el sitio funciona en el navegador
- Ningún rastro en los logs del servidor cuando el LLM intenta el acceso
- Errores genéricos tipo "robots.txt disallowed" aunque el robots.txt esté configurado correctamente
- Respuestas HTTP diferentes según el User-Agent
---
## Nivel 2 — robots.txt
### Qué verificar
El archivo robots.txt es el primer archivo que los crawlers (incluidos los de los LLM) leen antes de acceder a cualquier página. Una configuración errónea puede bloquear todo el sitio. Además, si el robots.txt mismo no es alcanzable, muchos crawlers interpretan esto como "acceso denegado a todo".
### Pruebas a ejecutar
**2.1 — Verifica la accesibilidad del robots.txt**
```bash
curl -I https://tusitio.com/robots.txt
```
Comprueba que el código de respuesta sea `200 OK` y no `403`, `404` o `500`. Un robots.txt inaccesible es a menudo el síntoma de un bloqueo a nivel de firewall (ver Nivel 1).
**2.2 — Verifica el contenido efectivamente servido**
```bash
curl -s https://tusitio.com/robots.txt
```
Compara el contenido devuelto con el que esperas. Atención a los conflictos entre generación estática y dinámica:
| Framework | Archivo estático | Archivo dinámico | Prevalencia |
|-----------|-----------------|------------------|-------------|
| Next.js | `public/robots.txt` | `app/robots.ts` | Dinámico sobrescribe estático |
| Nuxt.js | `public/robots.txt` | Módulo `@nuxtjs/robots` | Depende de la configuración |
| Gatsby | `static/robots.txt` | Plugin `gatsby-plugin-robots-txt` | Plugin sobrescribe |
| WordPress | Archivo físico | Plugin SEO (Yoast, Rank Math) | Plugin sobrescribe |
| Sitios estáticos | Archivo en la raíz | — | — |
Si ambas fuentes existen, la dinámica podría sobrescribir la estática con reglas diferentes a las previstas.
**2.3 — Añade Allow explícito para los bots LLM**
Para maximizar la compatibilidad, añade reglas explícitas para cada bot LLM. Muchos crawlers verifican primero si existe una regla específica para su propio user-agent; un Allow explícito elimina toda ambigüedad:
```
User-Agent: ClaudeBot
User-Agent: GPTBot
User-Agent: ChatGPT-User
User-Agent: Google-Extended
User-Agent: PerplexityBot
User-Agent: Applebot-Extended
Allow: /
Disallow: /admin/
Disallow: /api/
User-Agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Sitemap: https://tusitio.com/sitemap.xml
```
**2.4 — Verifica el Content-Type del robots.txt**
```bash
curl -I https://tusitio.com/robots.txt | grep -i content-type
```
Debe ser `text/plain`. Si el servidor devuelve `text/html` u otro tipo MIME, algunos crawlers podrían no interpretarlo correctamente como archivo robots.
**2.5 — Verifica la coherencia entre robots.txt y firewall**
Un error común es tener un robots.txt que dice "Allow" pero un firewall que bloquea. El robots.txt es solo una directiva: si el firewall niega el acceso aguas arriba, el robots.txt ni siquiera se lee. Los dos niveles deben ser coherentes.
### Señales de problema
- El robots.txt devuelve un error HTTP (403, 404, 500)
- Existen tanto el archivo estático como el dinámico con reglas diferentes
- Las reglas `Disallow` son demasiado amplias (ej. `Disallow: /` sin `Allow`)
- El Content-Type no es `text/plain`
- El firewall bloquea aguas arriba haciendo el robots.txt inalcanzable
---
## Nivel 3 — Meta tags y headers HTTP
### Qué verificar
Incluso con un robots.txt perfecto, meta tags HTML o headers HTTP pueden bloquear la indexación a nivel de página individual. Estos controles son granulares y pueden aplicarse selectivamente a páginas o secciones específicas del sitio.
### Pruebas a ejecutar
**3.1 — Comprueba los meta tags robots en el** `<head>`
```bash
curl -s https://tusitio.com/pagina | grep -i "robots"
```
Busca tags como:
```html
<!-- BLOQUEANTES — impiden indexación -->
<meta name="robots" content="noindex">
<meta name="robots" content="nofollow">
<meta name="robots" content="none">
<meta name="robots" content="noindex, nofollow">
<!-- PERMISIVOS — permiten indexación -->
<meta name="robots" content="index, follow">
<!-- O simplemente la ausencia del tag (default = index, follow) -->
```
Atención: algunos frameworks inyectan automáticamente meta tags `noindex` en determinadas condiciones (ej. páginas de error, páginas de preview, entornos de staging).
**3.2 — Comprueba el header X-Robots-Tag**
```bash
curl -I https://tusitio.com/pagina | grep -i "x-robots"
```
El header `X-Robots-Tag: noindex` en la respuesta HTTP bloquea la indexación incluso sin meta tag en el HTML. Es a menudo usado por CDN, middleware o configuraciones server-side.
**3.3 — Comprueba headers específicos para bots AI**
Algunos frameworks, CDN o middleware añaden headers o comportamientos diferentes para los bots AI:
```bash
# Compara las respuestas con diferentes User-Agents
curl -I -H "User-Agent: ClaudeBot" https://tusitio.com/pagina
curl -I -H "User-Agent: Mozilla/5.0" https://tusitio.com/pagina
```
Compara: código de estado, header `X-Robots-Tag`, eventuales redirects, Content-Type. Deben ser idénticos.
### Señales de problema
- `noindex` presente en el `<head>` de páginas que deberían ser visibles
- `X-Robots-Tag` restrictivo en los headers HTTP
- Respuestas diferentes según el User-Agent (redirect, 403, challenge page)
- Meta tags `noindex` inyectados automáticamente por el framework en producción
---
## Nivel 4 — Middleware y rewrites
### Qué verificar
Los frameworks modernos (Next.js, Nuxt, SvelteKit, Remix, etc.) usan middleware que intercepta las solicitudes y puede modificar el comportamiento antes de que lleguen a la página. Esto es particularmente crítico para sitios multilingües (redirect según idioma) y sitios con autenticación.
### Pruebas a ejecutar
**4.1 — Comprueba que el middleware no intercepte recursos SEO**
El middleware no debería interceptar robots.txt, sitemap.xml, favicon.ico y otros archivos estáticos. Recursos a excluir del middleware:
- robots.txt
- sitemap.xml (y sitemap index)
- favicon.ico
- Archivos estáticos (assets, imágenes, CSS, JS)
- API routes (si no requieren auth)
**4.2 — Verifica los redirects del middleware para los bots**
Si el middleware gestiona la localización (ej. redirect de `/` a `/es/`), verifica que no cree loops de redirect o páginas de error para los bots. Los bots típicamente no envían cookies de preferencia de idioma:
```bash
# Prueba como un bot sin cookies
curl -v -H "User-Agent: ClaudeBot" https://tusitio.com/ 2>&1 | grep -i "location\|301\|302\|307"
```
Si ves redirects múltiples o loops, el middleware está creando problemas para los crawlers.
**4.3 — Verifica la ausencia de bloqueo basado en User-Agent en el middleware**
Comprueba que el código del middleware no contenga lógica de bloqueo para los bots. Patrones problemáticos a buscar en el código middleware:
- Bloqueo de User-Agents que contienen "Bot" o "Crawler"
- Redirect a páginas de challenge/captcha para User-Agents no-navegador
- Respuesta 403/401 para solicitudes sin cookie de sesión
**4.4 — Verifica los rewrites de URL**
Si el sitio usa URL rewriting (ej. de slugs simplificados a rutas internas), verifica que los rewrites funcionen también para los bots:
```bash
curl -s -o /dev/null -w "%{http_code}" -H "User-Agent: ClaudeBot" https://tusitio.com/articulo-ejemplo
```
Debe devolver `200`, no `404` o `500`.
### Señales de problema
- El middleware intercepta solicitudes a `robots.txt` o `sitemap.xml`
- Redirects infinitos para bots que no gestionan cookies de idioma
- Respuestas 403 o 401 para User-Agents no-navegador
- Páginas que funcionan en el navegador pero devuelven 404 vía curl
---
## Nivel 5 — Renderizado y contenido accesible
### Qué verificar
Los LLM y sus crawlers generalmente **no ejecutan JavaScript**. Si el contenido de tu sitio se carga solo vía client-side rendering (CSR), los bots verán una página vacía o parcial. Este es uno de los problemas más comunes y subestimados.
### Impacto por estrategia de renderizado
| Estrategia de renderizado | Visibilidad a los bots LLM |
|---------------------------|---------------------------|
| Static Site Generation (SSG) | ✅ Óptima — HTML completo en la primera solicitud |
| Server-Side Rendering (SSR) | ✅ Buena — HTML generado en cada solicitud |
| Incremental Static Regeneration (ISR) | ✅ Buena — similar a SSG con actualización |
| Client-Side Rendering (CSR) | ❌ Problemática — contenido ausente para los bots |
| Hydration parcial | ⚠️ Variable — depende de qué es server-rendered |
### Pruebas a ejecutar
**5.1 — Verifica el renderizado sin JavaScript**
```bash
curl -s https://tusitio.com/pagina | grep -c "<article\|<p\|<h1\|<h2"
```
Si el contenido HTML principal (títulos, párrafos, artículos) no está presente en la respuesta inicial, significa que se carga vía JavaScript y los bots no lo verán.
**5.2 — Compara el contenido SSR vs navegador**
Cuenta los elementos visibles en los dos contextos:
1. Abre la página en el navegador → cuenta los artículos/secciones/elementos visibles
2. Haz un `curl` de la misma página → cuenta los mismos elementos en el HTML en bruto
3. Si el navegador muestra más contenido, la diferencia se carga vía JavaScript y es **invisible para los bots**
Ejemplo práctico: si la homepage muestra 8 artículos en el navegador pero el `curl` devuelve solo 6, los 2 faltantes se cargan dinámicamente.
**5.3 — Verifica el lazy loading y el infinite scroll**
Si usas infinite scroll, botones "cargar más" o lazy loading para los artículos, los contenidos cargados dinámicamente no serán visibles para los crawlers. Asegúrate de que al menos todos los contenidos principales estén en el HTML inicial (SSR/SSG).
Para las listas de artículos, considera incluir todos los artículos recientes en el HTML inicial, o usa paginación con URLs distintas (`/blog/page/2`) en lugar de carga dinámica.
**5.4 — Prueba la versión LLM-friendly (si está presente)**
Algunos sitios ofrecen una versión en Markdown o texto simple para los LLM. Si está presente, verifica que sea accesible:
```bash
curl -s https://tusitio.com/pagina/markdown
```
Ofrecer un endpoint dedicado para LLM es una best practice emergente en la GEO. El protocolo llms.txt (ver Nivel 9) estandariza este enfoque proponiendo que cada página tenga una versión Markdown accesible añadiendo `.md` a la URL.
**5.5 — Verifica el contenido estructurado (Schema.org)**
Los datos estructurados en formato JSON-LD ayudan a los LLM a comprender el tipo y la estructura del contenido:
```bash
curl -s https://tusitio.com/pagina | grep -i "application/ld+json"
```
El marcado Schema.org para `Article`, `BlogPosting`, `FAQPage`, `HowTo` es particularmente útil para la GEO.
### Señales de problema
- El `curl` devuelve HTML con poco o ningún contenido textual
- Artículos faltantes respecto a los visibles en el navegador
- Contenidos importantes cargados solo después de interacción del usuario (scroll, click)
- Ausencia de datos estructurados JSON-LD
---
## Nivel 6 — Sitemap
### Qué verificar
El sitemap es fundamental para comunicar a los crawlers la estructura completa del sitio. Si no es legible o está mal configurado, los bots podrían no descubrir todas tus páginas o no comprender las relaciones entre las versiones lingüísticas de los contenidos.
### Pruebas a ejecutar
**6.1 — Verifica la accesibilidad del sitemap**
```bash
curl -s -o /dev/null -w "%{http_code}" https://tusitio.com/sitemap.xml
```
Debe devolver `200`.
**6.2 — Verifica el Content-Type**
```bash
curl -I https://tusitio.com/sitemap.xml | grep -i content-type
```
Este es un problema crítico verificado en el campo: algunas herramientas LLM tratan `application/xml` como **datos binarios** y no logran leer su contenido. Para maximizar la compatibilidad, sirve el sitemap con:
```
Content-Type: text/xml; charset=utf-8
```
Nota: muchos frameworks fuerzan `application/xml` y no permiten sobrescribir el Content-Type mediante configuración. En estos casos, la solución es generar el sitemap manualmente mediante un route handler o un endpoint API personalizado, donde puedes controlar el Content-Type directamente en la respuesta HTTP.
**6.3 — Verifica la estructura sitemap index (sitios multilingües)**
Si el sitio es multilingüe y usas un sitemap index que apunta a sitemaps hijos por idioma, verifica la cadena completa:
```bash
# Sitemap index principal
curl -s https://tusitio.com/sitemap.xml
# Sitemaps hijos por idioma
curl -s https://tusitio.com/es/sitemap.xml
curl -s https://tusitio.com/en/sitemap.xml
```
El sitemap index debería tener esta estructura:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://tusitio.com/es/sitemap.xml</loc>
<lastmod>2026-02-23T10:00:00.000Z</lastmod>
</sitemap>
<sitemap>
<loc>https://tusitio.com/en/sitemap.xml</loc>
<lastmod>2026-02-23T10:00:00.000Z</lastmod>
</sitemap>
</sitemapindex>
```
**6.4 — Verifica que el robots.txt apunte al sitemap index**
En el robots.txt, referencia un solo punto de entrada — el sitemap index principal — en lugar de enumerar todos los sitemaps hijos:
```
# ✅ CORRECTO — un solo punto de entrada
Sitemap: https://tusitio.com/sitemap.xml
# ❌ REDUNDANTE — los hijos ya están referenciados en el index
Sitemap: https://tusitio.com/es/sitemap.xml
Sitemap: https://tusitio.com/en/sitemap.xml
Sitemap: https://tusitio.com/fr/sitemap.xml
```
Para sitios monolingües sin sitemap index, apunta directamente al sitemap:
```
Sitemap: https://tusitio.com/sitemap.xml
```
**6.5 — Verifica la presencia de los tags** `hreflang` **(sitios multilingües)**
Esta es la prueba más importante para sitios multilingües. Sin `hreflang`, los crawlers no pueden conectar las versiones lingüísticas del mismo contenido. Cada URL debe declarar todas sus variantes lingüísticas, **incluyéndose a sí misma**.
Añade el namespace `xhtml` en el elemento `<urlset>` y los links alternados en cada `<url>`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://tusitio.com/es/blog/articulo-ejemplo</loc>
<lastmod>2026-02-12</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="es" href="https://tusitio.com/es/blog/articulo-ejemplo" />
<xhtml:link rel="alternate" hreflang="en" href="https://tusitio.com/en/blog/example-article" />
<xhtml:link rel="alternate" hreflang="it" href="https://tusitio.com/it/blog/articolo-esempio" />
</url>
</urlset>
```
Para verificar si los tags están presentes:
```bash
curl -s https://tusitio.com/es/sitemap.xml | grep -c "hreflang"
```
Si el resultado es `0`, los tags faltan y las relaciones multilingües no están declaradas.
**6.6 — Verifica la coherencia de las** `priority`
Las priorities deben reflejar la importancia real de las páginas. Una distribución uniforme de las priorities equivale a no tener priorities:
| Tipo de página | Priority recomendada |
|----------------|---------------------|
| Homepage | 1.0 |
| Páginas categoría / Secciones principales | 0.8 |
| Artículos / Posts / Páginas de contenido | 0.7 |
| Quiénes somos / Contactos / About | 0.5 |
| Legal / Privacidad / Cookies / Registro | 0.3 (o excluidas del sitemap) |
**6.7 — Verifica que páginas funcionales no estén en el sitemap**
Páginas como registro, login, legal, política de privacidad, política de cookies, términos de servicio son páginas funcionales y generalmente no deberían estar en el sitemap. Incluirlas diluye el crawl budget y señala a los motores que tienen la misma importancia que los contenidos originales.
```bash
curl -s https://tusitio.com/sitemap.xml | grep -iE "registr|legal|login|admin|privacidad|cookie|terminos|signup|signin"
```
**6.8 — Verifica la coherencia de** `lastmod` **y** `changefreq`
Incoherencias en estos campos reducen la confianza del crawler en todo el sitemap:
- `lastmod` debe reflejar la fecha real de la última modificación del contenido, no la fecha de generación del sitemap
- `lastmod` **de las páginas categoría** debe corresponder a la fecha del último artículo publicado en ellas
- `changefreq` debe ser realista: declarar `weekly` para páginas estáticas que nunca cambian es una señal de poca fiabilidad
- **Todas las URLs deberían tener** `lastmod`: páginas sin `lastmod` se tratan como de baja prioridad de actualización
```bash
# Comprueba las fechas en el sitemap
curl -s https://tusitio.com/sitemap.xml | grep -B1 "lastmod"
# Cuenta las URLs sin lastmod
curl -s https://tusitio.com/sitemap.xml | grep "<loc>" | wc -l # total URLs
curl -s https://tusitio.com/sitemap.xml | grep "lastmod" | wc -l # URLs con lastmod
```
**6.9 — Verifica la completitud del sitemap**
Compara el número de URLs en el sitemap con el número de páginas efectivas del sitio:
```bash
curl -s https://tusitio.com/sitemap.xml | grep -c "<loc>"
```
Cada página pública con contenido original debería estar presente. Páginas huérfanas (presentes en el sitio pero ausentes del sitemap) podrían no ser nunca descubiertas por los crawlers.
### Señales de problema
- Sitemap devuelve errores (404, 500)
- Content-Type `application/xml` interpretado como binario por algunos crawlers LLM
- Faltan los tags `xhtml:link` con `hreflang` en sitios multilingües
- robots.txt enumera los sitemaps hijos en lugar de apuntar al index
- Páginas funcionales (legal, registro, login) en el sitemap con priority alta
- `lastmod` incoherente, ausente o igual para todas las páginas
- `changefreq: weekly` en páginas que nunca cambian
- Priorities uniformes que no diferencian entre contenidos y páginas de servicio
- `lastmod` de las categorías no actualizado al último artículo publicado
- Páginas del sitio ausentes del sitemap
---
## Nivel 7 — Caché de los crawlers LLM
### Qué verificar
Los crawlers de los LLM memorizan las respuestas. Si tu sitio ha bloqueado un crawler en el pasado (incluso involuntariamente, por ejemplo mediante un firewall configurado por defecto), ese bloqueo puede persistir en la caché del crawler durante un período indefinido, incluso después de haber corregido la configuración.
Este es un problema particularmente insidioso porque todo parece correcto desde tu lado, pero el LLM sigue sin acceder al sitio.
### Cómo funciona la caché envenenada
1. El crawler del LLM intenta acceder a tu `robots.txt`
2. El firewall del hosting bloquea la solicitud (403 o página de challenge)
3. El crawler interpreta el bloqueo como "robots.txt dice disallow all"
4. Esta interpretación se cachea
5. Desde ese momento, el crawler ni siquiera intenta acceder al sitio — bloquea todo internamente basándose en la caché
6. Corriges el firewall y el robots.txt, pero el crawler sigue usando la caché envenenada
### Pruebas a ejecutar
**7.1 — Diagnóstico de caché envenenada**
Si un LLM dice no poder acceder a tu sitio pero los logs del servidor no muestran ninguna solicitud:
1. Corrige la configuración (firewall, robots.txt, etc.)
2. Pide al LLM que acceda a una página específica
3. Comprueba los logs del servidor en tiempo real:
- **Solicitud presente en los logs** → el problema está en la respuesta del servidor, no en la caché
- **Solicitud ausente en los logs** → caché envenenada: la solicitud ni siquiera parte
**7.2 — Fuerza la invalidación de la caché**
Después de haber corregido la configuración:
- **Espera**: la caché se invalida típicamente en horas o días, no minutos
- **Vuelve a probar periódicamente**: intenta cada pocas horas para verificar si la caché se ha actualizado
- **Verifica el robots.txt primero**: a menudo el robots.txt es el archivo cuya caché se actualiza antes que todo lo demás. Si el LLM logra leer el robots.txt actualizado, el resto seguirá
**7.3 — Fuerza el re-crawling (si es posible)**
Algunos proveedores LLM ofrecen mecanismos para solicitar un re-crawling:
- **Google (Gemini)**: Google Search Console → Solicitar indexación
- **Microsoft (Copilot)**: Bing Webmaster Tools → Submit URL
- **Anthropic (Claude)**: Por el momento no existe una herramienta pública equivalente; la invalidación ocurre automáticamente
- **OpenAI (ChatGPT)**: Por el momento no existe una herramienta pública de re-crawling
### Señales de problema
- El LLM reporta errores de acceso pero en los logs del servidor no hay rastro de la solicitud
- El problema persiste incluso después de haber corregido todas las configuraciones
- El sitio funciona con `curl` manual pero no con la herramienta del LLM
- El robots.txt se lee correctamente pero las páginas permanecen bloqueadas (caché parcial)
---
## Nivel 8 — Indexación en los motores de búsqueda de los LLM
### Qué verificar
Algunos LLM usan motores de búsqueda propios (no Google) para encontrar contenidos. Tu sitio podría estar bien indexado en Google pero completamente ausente del motor de búsqueda usado por el LLM. Además, el motor de búsqueda usado por cada LLM puede cambiar y no siempre está documentado.
### Pruebas a ejecutar
**8.1 — Prueba la búsqueda desde el LLM**
Pide directamente al LLM que busque un artículo tuyo con una query muy específica (ej. título exacto + nombre del sitio). Repite la prueba con diferentes LLM:
- Pide a **Claude** que busque tu artículo
- Pide a **ChatGPT** que busque el mismo artículo
- Pide a **Perplexity** que busque el mismo artículo
- Pide a **Gemini** que busque el mismo artículo
Si el sitio aparece en los resultados de algunos LLM pero no de otros, el problema está en la indexación del motor de búsqueda específico, no en tu sitio.
**8.2 — Verifica en Google Search Console**
Comprueba que el sitio esté indexado en Google:
- Número de páginas indexadas vs páginas totales del sitio
- Errores de crawling señalados
- Cobertura del índice
- Solicitudes de indexación pendientes
**8.3 — Verifica en Bing Webmaster Tools**
Muchos LLM (incluido ChatGPT/Copilot) usan Bing como fuente de búsqueda. Registra el sitio en Bing Webmaster Tools y verifica:
- Estado de la indexación
- Errores de crawling
- Sitemaps enviados y procesados
**8.4 — Verifica en otras webmaster tools**
- **Yandex Webmaster** — usado por algunos LLM para mercados específicos
- **IndexNow** — protocolo soportado por Bing, Yandex y otros para notificar nuevos contenidos en tiempo real
### Señales de problema
- El sitio aparece en Google pero no en los resultados de búsqueda del LLM
- Bajo número de páginas indexadas respecto al total
- Errores de crawling en las webmaster tools
- Sitemap no procesado o con errores en las webmaster tools
---
## Nivel 9 — El protocolo llms.txt y los contenidos LLM-friendly
### Qué verificar
Además de la accesibilidad técnica (Niveles 1-8), existen protocolos y formatos específicos diseñados para hacer los contenidos directamente comprensibles por los LLM. El más importante es **llms.txt**, una propuesta de estándar abierto creada por Jeremy Howard (cofundador de fast.ai y Answer.AI) en septiembre de 2024.
El concepto es simple: así como `robots.txt` dice a los crawlers "qué puedes ver" y `sitemap.xml` dice "dónde se encuentran las páginas", `llms.txt` **dice a los LLM "así es como entender mi sitio"**.
### El protocolo llms.txt
El archivo `/llms.txt` es un archivo Markdown posicionado en la raíz del sitio que proporciona un mapa curado y legible de todo el sitio en un formato optimizado para las context windows de los LLM. A diferencia del sitemap (que enumera todas las URLs), el llms.txt ofrece una selección razonada de los contenidos más importantes con descripciones y contexto.
Especificaciones del formato (de llmstxt.org):
- Un **H1** con el nombre del proyecto o sitio (obligatorio)
- Un **blockquote** con una descripción breve y clave del proyecto
- Cero o más **párrafos** con información de contexto
- Cero o más **secciones H2** conteniendo listas de links con descripciones
- Una sección opcional **"Optional"** con recursos secundarios que el LLM puede saltar si tiene una context window limitada
### Pruebas a ejecutar
**9.1 — Verifica la presencia del archivo llms.txt**
```bash
curl -s -o /dev/null -w "%{http_code}" https://tusitio.com/llms.txt
```
Si devuelve `404`, el archivo no existe y el sitio no está comunicando su estructura a los LLM.
**9.2 — Verifica el contenido y el formato del llms.txt**
```bash
curl -s https://tusitio.com/llms.txt
```
El archivo debe seguir el formato estándar. Aquí un ejemplo para un sitio empresarial:
```markdown
# Nombre Empresa
> Breve descripción de la empresa y de sus servicios principales.
> Información clave que cada LLM debería conocer.
La empresa opera en el sector X desde YYYY. Los servicios principales son A, B y C.
El sitio está disponible en español, inglés e italiano.
## Servicios
- [Servicio principal](https://tusitio.com/servicios/principal.html.md): Descripción concisa del servicio
- [Consultoría](https://tusitio.com/servicios/consultoria.html.md): Descripción de la consultoría ofrecida
## Blog y profundizaciones
- [Artículo importante](https://tusitio.com/blog/articulo.html.md): Por qué este artículo es relevante
- [Guía técnica](https://tusitio.com/blog/guia.html.md): Qué cubre esta guía
## Quiénes somos
- [About](https://tusitio.com/quienes-somos.html.md): Historia y misión de la empresa
- [Equipo](https://tusitio.com/equipo.html.md): El equipo y las competencias
## Optional
- [Case study detallado](https://tusitio.com/case-study.html.md): Profundización opcional
- [Documentación técnica](https://tusitio.com/docs.html.md): Referencia técnica completa
```
Nota: los links en el llms.txt deberían apuntar a las versiones Markdown de las páginas (ver prueba 9.3), no a las páginas HTML completas.
**9.3 — Implementa las versiones Markdown de las páginas**
La propuesta llms.txt incluye una convención fundamental: cada página del sitio debería tener una versión Markdown accesible añadiendo `.md` a la URL original. Esta versión contiene solo el contenido textual estructurado, sin navegación, sidebar, footer, popups o elementos UI.
```bash
# Página HTML original
curl -s https://tusitio.com/blog/articulo.html
# Versión Markdown para LLM
curl -s https://tusitio.com/blog/articulo.html.md
```
Si el sitio usa URLs sin extensión (ej. `/blog/articulo`), la convención es añadir `index.html.md`:
```bash
curl -s https://tusitio.com/blog/articulo/index.html.md
```
Alternativamente, puedes adoptar una ruta personalizada siempre que sea coherente:
```bash
curl -s https://tusitio.com/blog/articulo/markdown
```
La versión Markdown debe contener:
- El título del artículo (H1)
- El autor y la fecha de publicación
- El contenido completo estructurado con headings, párrafos, listas
- Los links a las fuentes citadas
- Ningún elemento de navegación, UI o marketing
**9.4 — Implementa el archivo llms.html para chatbots y sistemas RAG**
Además del llms.txt (pensado para los crawlers) y de las versiones Markdown (pensadas para las páginas individuales), un tercer archivo completa el ecosistema: **llms.html**.
El llms.html es una página HTML estructurada que funciona como **fuente de conocimiento para chatbots empresariales y sistemas RAG** (Retrieval Augmented Generation). Contiene todos los contenidos del sitio en formato estructurado, actualizado dinámicamente, y puede usarse como knowledge base para:
- Chatbots personalizados en el propio sitio
- GPTs personalizados (Custom GPTs de OpenAI)
- Agentes AI empresariales
- Cualquier sistema que necesite una fuente de conocimiento actualizada
```bash
curl -s -o /dev/null -w "%{http_code}" https://tusitio.com/llms.html
```
A diferencia del llms.txt (que es un mapa con links), el llms.html contiene el texto completo de los contenidos, organizado en secciones, listo para ser ingerido por un sistema RAG sin pasos adicionales.
**9.5 — Referencia el llms.txt en el robots.txt**
Así como el robots.txt referencia el sitemap, es buena práctica añadir una referencia al llms.txt. Aunque todavía no existe un estándar formal para esto, algunos crawlers comienzan a buscarlo:
```
Sitemap: https://tusitio.com/sitemap.xml
# LLM-friendly content map
# llms.txt: https://tusitio.com/llms.txt
```
**9.6 — Usa datos estructurados (Schema.org)**
Los datos estructurados JSON-LD ayudan a los LLM a comprender el tipo, el autor, la fecha y la estructura del contenido:
```html
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Título del artículo",
"author": {
"@type": "Person",
"name": "Nombre Autor"
},
"datePublished": "2026-02-12",
"dateModified": "2026-02-15",
"description": "Descripción del artículo",
"inLanguage": "es"
}
</script>
```
El marcado Schema.org para `Article`, `BlogPosting`, `Product`, `FAQPage`, `HowTo`, `Organization` y `LocalBusiness` es particularmente útil para la GEO.
**9.7 — Estructura el contenido de forma clara**
Los LLM interpretan mejor los contenidos cuando:
- Cada página tiene un solo `<h1>` claro y descriptivo
- Los subtítulos (`<h2>`, `<h3>`) siguen una jerarquía lógica
- Los párrafos tratan un concepto a la vez
- Las informaciones clave están al inicio del texto (estructura de pirámide invertida)
- Las listas y las tablas se usan para datos estructurados
**9.8 — Declara la autoría y la fecha**
Los LLM dan más peso a los contenidos con autor identificable y fecha clara:
- Incluye nombre del autor visible en la página
- Incluye la fecha de publicación y de última actualización
- Usa los meta tags `article:author`, `article:published_time`, `article:modified_time`
**9.9 — Monitorea las citas de los LLM**
Prueba periódicamente si los LLM citan tu sitio cuando responden a preguntas pertinentes a tus contenidos. Pregunta a los LLM cuestiones sobre temas que tu sitio trata en profundidad y verifica si tu sitio aparece como fuente.
### Relación entre sitemap.xml, llms.txt y llms.html
| Archivo | Propósito | Destinatarios | Contenido |
|---------|-----------|---------------|-----------|
| `sitemap.xml` | Listado completo de las URLs del sitio | Motores de búsqueda (Google, Bing) y crawlers LLM | URLs, lastmod, priority, hreflang |
| `robots.txt` | Directivas de acceso para los crawlers | Todos los crawlers | Allow/Disallow por User-Agent |
| `llms.txt` | Mapa curado y contexto del sitio | LLM durante la inference | Markdown estructurado con links a las versiones .md |
| `llms.html` | Knowledge base completa | Chatbots, GPTs custom, sistemas RAG | HTML estructurado con contenido completo |
| `*.html.md` | Versión limpia de cada página | LLM que acceden a páginas específicas | Markdown del solo contenido, sin UI |
Todos estos archivos coexisten y tienen propósitos complementarios. Ninguno sustituye a los otros.
### Señales de problema
- Archivo `/llms.txt` ausente (404)
- llms.txt presente pero con formato no estándar o contenido genérico
- Ninguna versión Markdown disponible para las páginas del sitio
- Los links en el llms.txt apuntan a páginas HTML completas en lugar de versiones .md
- Ausencia de datos estructurados JSON-LD
- Contenido sin autor o fecha identificable
- El LLM no cita el sitio cuando se le hacen preguntas pertinentes a los contenidos publicados
---
## Checklist rápida
### Accesibilidad e infraestructura
| # | Test | Comando/Acción | Resultado esperado |
|---|------|----------------|-------------------|
| 1 | Bot Protection hosting | Panel Firewall hosting | Log o desactivado |
| 2 | AI Bots ruleset | Panel Firewall hosting | Log o desactivado |
| 3 | Respuesta a User-Agent LLM | `curl -I -H "User-Agent: ClaudeBot" tusitio.com` | 200 OK, idéntico a navegador |
| 4 | robots.txt accesible | `curl -I tusitio.com/robots.txt` | 200 OK, `text/plain` |
| 5 | robots.txt Allow para LLM | `curl -s tusitio.com/robots.txt` | Allow explícito para bots LLM |
| 6 | robots.txt apunta a sitemap index | `curl -s tusitio.com/robots.txt | grep Sitemap` | Un solo link al sitemap index |
### Meta tags y middleware
| # | Test | Comando/Acción | Resultado esperado |
|---|------|----------------|-------------------|
| 7 | Meta robots | `curl -s tusitio.com/pagina | grep robots` | Ningún noindex |
| 8 | X-Robots-Tag | `curl -I tusitio.com/pagina` | Ningún noindex |
| 9 | Middleware no bloquea bots | `curl -I -H "User-Agent: ClaudeBot" tusitio.com/pagina` | 200 OK, no redirect loop |
### Renderizado y contenido
| # | Test | Comando/Acción | Resultado esperado |
|---|------|----------------|-------------------|
| 10 | Contenido en el HTML inicial | `curl -s tusitio.com | grep "<h1|<article|<p"` | Contenido principal presente |
| 11 | Conteo elementos SSR vs navegador | Cuenta artículos en curl vs navegador | Números idénticos |
| 12 | Datos estructurados JSON-LD | `curl -s tusitio.com/pagina | grep "ld+json"` | Schema.org presente |
### Sitemap
| # | Test | Comando/Acción | Resultado esperado |
|---|------|----------------|-------------------|
| 13 | Sitemap accesible | `curl -I tusitio.com/sitemap.xml` | 200 OK |
| 14 | Sitemap Content-Type | `curl -I tusitio.com/sitemap.xml | grep content-type` | `text/xml; charset=utf-8` |
| 15 | hreflang presentes (multilingüe) | `curl -s tusitio.com/sitemap.xml | grep hreflang` | Tags para cada idioma |
| 16 | No páginas funcionales | `curl -s tusitio.com/sitemap.xml | grep -iE "legal|login|registr"` | Ningún resultado |
| 17 | Priority diferenciadas | Revisión manual del sitemap | Coherentes con importancia páginas |
| 18 | lastmod coherente | `curl -s tusitio.com/sitemap.xml | grep lastmod` | Fechas reales, no uniformes |
### Verificación end-to-end
| # | Test | Comando/Acción | Resultado esperado |
|---|------|----------------|-------------------|
| 19 | llms.txt presente | `curl -s -o /dev/null -w "%{http_code}" tusitio.com/llms.txt` | 200 OK |
| 20 | llms.txt formato correcto | `curl -s tusitio.com/llms.txt` | Markdown estructurado con H1, blockquote, secciones H2 |
| 21 | Versiones Markdown de las páginas | `curl -s tusitio.com/blog/articulo.html.md` | Contenido Markdown limpio |
| 22 | llms.html para RAG | `curl -s -o /dev/null -w "%{http_code}" tusitio.com/llms.html` | 200 OK (si implementado) |
| 23 | Test acceso desde LLM | Pide a Claude/GPT que lea una página | Contenido devuelto |
| 24 | Logs servidor durante test LLM | Comprueba logs en vivo durante el test | Solicitud visible |
| 25 | Búsqueda del sitio mediante LLM | Pide al LLM que busque un artículo tuyo | Sitio en los resultados |
| 26 | Citación por parte del LLM | Pregunta al LLM sobre un tema que trates | Sitio citado como fuente |
---
## Cuándo repetir las pruebas
El ecosistema de los crawlers LLM está en rápida evolución. Repite las pruebas periódicamente, en particular después de:
- Actualizaciones del framework (Next.js, Nuxt, WordPress, etc.)
- Modificaciones al hosting, al plan o a la CDN
- Actualizaciones del firewall, del WAF o de las reglas bot
- Deploy de nuevas funcionalidades que involucren middleware o renderizado
- Señalizaciones de usuarios que no logran encontrar el sitio mediante LLM
- Lanzamiento de nuevos LLM o actualizaciones significativas de los existentes
---
## Glosario
| Término | Definición |
|---------|-----------|
| **GEO** | Generative Engine Optimization: optimización para la visibilidad en los LLM |
| **SEO** | Search Engine Optimization: optimización para los motores de búsqueda |
| **SSR** | Server-Side Rendering: el contenido HTML es generado por el servidor |
| **CSR** | Client-Side Rendering: el contenido es generado por JavaScript en el navegador |
| **SSG** | Static Site Generation: las páginas HTML son pre-generadas en el build |
| **WAF** | Web Application Firewall: firewall a nivel aplicativo |
| **robots.txt** | Archivo que indica a los crawlers qué páginas pueden o no acceder |
| **Sitemap** | Archivo XML que enumera todas las páginas del sitio para los crawlers |
| **hreflang** | Atributo que indica el idioma y la región de una página |
| **Caché envenenada** | Cuando un crawler memoriza un bloqueo y continúa usándolo incluso después de la corrección |
| **Content-Type** | Header HTTP que indica el formato del contenido de la respuesta |
| **User-Agent** | Header HTTP que identifica el cliente que efectúa la solicitud |
| **Crawl budget** | Número de páginas que un crawler está dispuesto a escanear en un sitio |
| **JSON-LD** | Formato para datos estructurados embebidos en el HTML |
| **Schema.org** | Vocabulario estándar para datos estructurados en la web |
| **llms.txt** | Archivo Markdown en la raíz del sitio que proporciona un mapa curado de los contenidos para los LLM (estándar propuesto por Jeremy Howard, llmstxt.org) |
| **llms.html** | Página HTML estructurada que funciona como knowledge base para chatbots y sistemas RAG |
| **RAG** | Retrieval Augmented Generation: técnica que permite a un LLM acceder a fuentes de conocimiento externas para generar respuestas más precisas |
| **Inference** | El momento en que un LLM genera una respuesta a una solicitud del usuario, potencialmente consultando fuentes externas |