En un sitio HTML estático, añadir schema markup es trivial: pegas el bloque JSON-LD en el <head> y listo. En una aplicación Next.js o React la cosa se complica: tienes SSR, hidratación del cliente, el App Router con Server Components, el Pages Router con _document.tsx, y múltiples páginas con schemas distintos que no deben interferir entre sí. Hacerlo mal puede generar schema duplicado, errores de hidratación o markup que Google no detecta.
Next.js App Router (Next.js 13+): la forma recomendada
En el App Router de Next.js, el lugar correcto para el schema es dentro del componente de la página o del layout, usando una etiqueta <script> con dangerouslySetInnerHTML. Al ser un Server Component por defecto, el schema se renderiza en el servidor y Google lo ve en el HTML inicial sin necesidad de ejecutar JavaScript.
El pattern correcto es definir el objeto del schema como constante tipada en TypeScript y serializarlo con JSON.stringify directamente en el JSX:
- •Define el schema como objeto TypeScript — tipado, sin riesgo de errores de sintaxis JSON manual.
- •Usa JSON.stringify(schema) dentro de dangerouslySetInnerHTML={{ __html: ... }}.
- •Coloca la etiqueta <script> dentro del componente page.tsx de la ruta que corresponde.
- •Para schemas globales (Organization, WebSite), ponlos en el layout.tsx raíz.
- •No uses useEffect para inyectar el schema — perdería el SSR y Google podría no detectarlo.
Next.js Pages Router: _document.tsx vs componente de página
En el Pages Router, tienes dos opciones según el tipo de schema:
- •Schemas globales (Organization, WebSite): añádelos en _document.tsx dentro del <Head> — se renderizan en todas las páginas.
- •Schemas de página específica: añádelos en el componente de cada página usando el componente <Head> de next/head con el <script> dentro.
- •Si usas next-seo o similar: muchas librerías de SEO para Next.js incluyen soporte nativo para JSON-LD — revisa la documentación de la librería antes de implementar manualmente.
React puro (sin Next.js): react-helmet o inserción directa
En una SPA React sin SSR, el schema se puede añadir de dos formas:
- •Con react-helmet o react-helmet-async: permite gestionar el <head> de forma declarativa por componente, incluyendo etiquetas <script>.
- •Con useEffect + document.createElement: crea dinámicamente la etiqueta script y la añade al head. El problema es que el schema no existe en el HTML inicial — las SPA sin SSR tienen visibilidad de schema limitada para Google.
- •Recomendación: si el SEO es importante, usa SSR (Next.js, Remix) en lugar de una SPA pura.
Errores comunes de schema en apps JavaScript
| Error | Causa | Solución |
|---|---|---|
| Schema duplicado | Schema en layout + schema en página para el mismo tipo | Centralizar: global en layout, específico en página |
| Schema no detectado por Google | Inyectado con JS del lado del cliente sin SSR | Renderizar en servidor o usar SSR/SSG |
| Error de hidratación | Schema generado dinámicamente con datos que difieren entre servidor y cliente | Generar el schema con datos estáticos o asegurarse de que el estado inicial es el mismo |
| JSON inválido en producción | Datos con caracteres especiales no escapados en JSON.stringify | Usar JSON.stringify — nunca construir el JSON como string con interpolación |
Cómo generar el JSON-LD para tu app Next.js
El Generador de Schema con IA de iRankly produce el objeto JSON listo para usar. Cópialo, pégalo como constante en tu componente Next.js y usa JSON.stringify para serializarlo en la etiqueta script. El generador incluye todos los campos recomendados por Google para el tipo de schema seleccionado.
Prueba la herramienta gratis
Analiza tus URLs con Generador de Schema con IA de iRankly. Sin registro, sin tarjeta.
Verifica el schema con el Validador de iRankly
Una vez implementado, verifica que Google detecta correctamente el schema con el Validador de Schema de iRankly: introduce la URL de la página ya publicada y comprueba que el schema aparece correctamente parseado y sin errores de campos requeridos.