Tenten AIGEO
Volver al blog
AEO técnicoImplementación

Cómo insertar JSON-LD en Next.js App Router con Server Components

En Next.js App Router, un Server Component puede generar directamente `<script type="application/ld+json">` para incluir los datos estructurados en el HTML inicial. Así, los rastreadores de IA pueden leerlos sin ejecutar JavaScript. Incluye un ejemplo mínimo de page.tsx, la agrupación de varias entidades con @graph y los pasos de verificación con curl antes de publicar.

Equipo de Tenten GEOPublicado 2026-06-115 min de lectura
Diagrama del flujo de datos estructurados generados en el servidor hacia el HTML inicial que lee el rastreador de IA.

La forma más fiable de insertar JSON-LD en App Router es generar directamente un bloque `<script type="application/ld+json">` desde un Server Component. De este modo, los datos estructurados aparecen en el HTML inicial que devuelve el servidor y el rastreador de IA puede leerlos sin ejecutar JavaScript. Para los motores de respuesta, el JSON-LD añadido después mediante useEffect o Google Tag Manager es prácticamente invisible: la mayoría termina de rastrear la página y se marcha sin esperar a que se complete la hidratación.

¿Por qué debe generarse en el servidor?

La diferencia está en el momento de ejecución. El Server Component escribe el JSON-LD en la cadena HTML cuando recibe la solicitud. Por tanto, el primer archivo que obtienen rastreadores como GPTBot, ClaudeBot, PerplexityBot y Google-Extended ya contiene el esquema completo. La inserción en el cliente, en cambio, exige esperar a que el navegador descargue y ejecute el bundle, un paso que la mayoría de los rastreadores de IA ni siquiera realiza. Aquí hay una trampa fácil de pasar por alto: Google Rich Results Test sí renderiza JavaScript. Los datos insertados en el cliente parecen correctos dentro de la herramienta y pueden dar la impresión de haber superado la prueba; sin embargo, cuando el motor de respuesta consulta la página, recibe el HTML original sin renderizar, donde el esquema no existe. En las auditorías técnicas que realizamos para nuestros clientes, esta es una de las carencias más frecuentes y menos evidentes.

Ejemplo mínimo viable: una página page.tsx

La implementación es muy breve. No requiere paquetes adicionales ni rutas de API: todo se resuelve dentro del Server Component que renderiza el artículo. Solo hay tres tareas esenciales: obtener los datos, agrupar los objetos y generar el script.

  1. En `app/blog/[slug]/page.tsx`, que de forma predeterminada es un Server Component, utiliza primero `await` para obtener los datos del artículo.
  2. Crea un objeto JavaScript puro llamado `jsonLd`. Empieza con `"@context": "https://schema.org"` y `"@type": "Article"`, y completa dinámicamente los demás campos —headline, datePublished, author e image— con los datos del artículo.
  3. Añade al principio del JSX devuelto: `<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }} />`.
  4. No importes bibliotecas de cliente ni añadas "use client" al principio del archivo. Si lo haces, pasará a ser un Client Component y se perderá todo el trabajo anterior.

Cómo conectar varias entidades con @graph

Una página suele necesitar más de un esquema: la marca se representa como Organization; el artículo, como Article; la ruta de navegación, como BreadcrumbList; y la sección de preguntas y respuestas, como FAQPage. En lugar de generar cuatro etiquetas script independientes, resulta más limpio reunirlas en el array `@graph` de un único objeto JSON-LD y relacionarlas mediante `@id`. Por ejemplo, el `publisher` de Article puede apuntar al `@id` de Organization, mientras que el último elemento de BreadcrumbList puede apuntar al `@id` de la página actual. Así, el motor de respuesta obtiene en un solo análisis el mapa completo de relaciones entre entidades y disminuye el riesgo de encontrar nodos contradictorios o duplicados.

  • Organization y WebSite: inclúyelos una sola vez en `app/layout.tsx` para compartirlos en todo el sitio. No los declares de nuevo en cada página.
  • Article o BlogPosting: inclúyelo en el `page.tsx` del artículo y completa sus campos dinámicamente con los datos de la página actual.
  • BreadcrumbList: organízalo según la jerarquía de rutas. Resulta especialmente útil para que la IA comprenda la estructura del sitio.
  • FAQPage: añádelo únicamente cuando la página muestre una sección real de preguntas y respuestas. El texto de `acceptedAnswer` debe coincidir con el contenido visible; no inventes preguntas solo para incluir el esquema.
Infografía: el Server Component incluye JSON-LD en el HTML inicial, mientras que el rastreador de IA omite la inserción en el cliente.
El JSON-LD generado en el servidor llega con el HTML inicial; el que se inserta en el cliente puede aparecer demasiado tarde para el rastreador.

Cómo mantener el JSON-LD a largo plazo

Si los objetos del esquema quedan dispersos entre distintas páginas, en tres meses nadie querrá modificarlos. Nuestro enfoque consiste en extraer un archivo `lib/schema.ts` y usar los tipos de `schema-dts` (`import type { Article, WithContext } from "schema-dts"`) para restringir el valor devuelto por cada función generadora. Si el nombre o el tipo de un campo es incorrecto, TypeScript lo señalará durante la compilación. La página solo tiene que llamar a `buildArticleSchema(post)`, recibir un objeto con tipos seguros y generarlo. Cada cambio se aplicará entonces a todo el sitio. Las URL deben ser siempre absolutas y estar centralizadas en una constante `SITE_URL`, lo que evita discrepancias en los `@id` entre el sitio oficial y el dominio de vista previa.

Errores habituales y comprobaciones antes de publicar

  • Los valores de `url`, `image` o `datePublished` del JSON-LD no coinciden con el contenido visible. El motor de respuesta detecta la discrepancia y reduce su confianza en toda la página.
  • Utilizar rutas relativas en `@id` o `url` puede hacer que apunten al lugar equivocado al cambiar al dominio de vista previa.
  • Olvidar escapar `<` o añadir por error `"use client"` al principio de la página, lo que convierte el script en contenido generado en el cliente.
  • Antes de publicar, comprueba la sintaxis con Google Rich Results Test. Después, utiliza `curl` para obtener directamente el HTML original de la página y confirmar que el script forma parte de la respuesta inicial, en vez de aparecer únicamente en las DevTools del navegador. Esta es la comprobación más importante, porque reproduce exactamente lo que ve el rastreador de IA.
En la mayoría de los sitios que hemos auditado, el problema del JSON-LD no está en cómo se ha escrito el esquema, sino en que solo existe en el cliente. Si el servidor no lo devuelve dentro del HTML, para la IA es como si no existiera.Tenten GEO Technical Audit

De la implementación a la citación

Trasladar el JSON-LD a un Server Component es el requisito mínimo para que el contenido sea «legible por máquinas». El siguiente paso consiste en alinear los nombres de las entidades, los enlaces internos y la coherencia entre páginas para que la IA pueda citar el sitio de forma estable como fuente de confianza. Si no sabes con certeza si los datos estructurados de tu sitio forman parte del HTML que ve el rastreador, puedes solicitar un diagnóstico GEO de 30 minutos. Revisaremos el código fuente obtenido directamente para ayudarte a detectar las carencias, en lugar de limitarnos a examinar la página renderizada.

Preguntas frecuentes

¿Cómo se añade JSON-LD a Next.js App Router?
Crea un objeto de esquema en el Server Component —page.tsx o layout.tsx—, genéralo mediante `<script type="application/ld+json">` y `dangerouslySetInnerHTML`, y escapa el carácter `<` de la cadena como `<`. De esta forma, los datos estructurados quedarán incluidos en el HTML inicial y el rastreador de IA podrá leerlos sin ejecutar JavaScript.
¿Puedo añadir JSON-LD mediante next/head o la Metadata API?
App Router ya no utiliza next/head y la Metadata API no permite generar etiquetas script arbitrarias. La recomendación oficial de Next.js es renderizar `<script type="application/ld+json">` directamente en el JSX del Server Component. Actualmente, es la opción más estable para incluir JSON-LD y facilitar que los rastreadores lo lean.
¿Por qué no se recomienda insertar datos estructurados con GTM o useEffect?
Ambos se ejecutan en el cliente, por lo que el JSON-LD aparece después de que el navegador hidrate la página. La mayoría de los rastreadores de IA solo obtiene el HTML inicial y no ejecuta JavaScript; por tanto, no puede ver el esquema. Generarlo en el servidor es la única manera de garantizar que el motor de respuesta pueda leer y consultar realmente los datos estructurados.

DA EL SIGUIENTE PASO

¿Qué visibilidad tiene tu marca en las respuestas de la IA?

En un diagnóstico GEO de 30 minutos identificamos tus brechas de visibilidad y las acciones que conviene priorizar.

Reservar el diagnóstico