Qué es Schema.org y por qué importa en SEO técnico
Schema.org es un vocabulario estandarizado de tipos y propiedades (por ejemplo, Organization, Product, Article) que se añade al HTML para describir el significado del contenido de una página de forma estructurada. Su objetivo principal es mejorar el entendimiento semántico por parte de los motores de búsqueda: qué entidad es cada cosa, cómo se relaciona con otras y qué atributos tiene.
Cuando el marcado coincide con políticas y requisitos, los buscadores pueden usarlo para habilitar rich results (resultados enriquecidos) como migas de pan, FAQs, productos con precio/stock, etc. Importante: el marcado estructurado no garantiza rich results; es una señal adicional que debe ser válida, consistente y elegible.
Principios clave (lo que suele romper implementaciones)
- Reflejar contenido visible: si marcas un precio, una valoración o una FAQ, esa información debe existir en la página para el usuario (y ser coherente).
- Consistencia de entidades: define una identidad estable para tu organización/sitio y reutilízala en todo el sitio (mismo
@id, mismo nombre, misma URL canónica). - Evitar marcado engañoso: no inventes datos (ratings, reviews, FAQs, disponibilidad). Además de perder rich results, puedes provocar acciones manuales o pérdida de elegibilidad.
Formatos de marcado: JSON-LD vs Microdata (y por qué suele recomendarse JSON-LD)
JSON-LD (recomendado en la mayoría de casos)
- Se inserta como un bloque
<script type="application/ld+json">sin mezclarlo con el HTML. - Más fácil de generar desde backend/CMS y de mantener cuando cambian plantillas.
- Menos propenso a errores por refactors de markup visual.
Microdata
- Se incrusta con atributos HTML (
itemscope,itemtype,itemprop) en los elementos visibles. - Puede ser útil cuando quieres asegurar alineación directa con el contenido visible, pero es más frágil ante cambios de DOM y más costoso de mantener.
Pauta práctica de elección
- Si tienes SSR o puedes renderizar HTML en servidor: JSON-LD suele ser la opción más limpia.
- Si tu CMS/plantillas ya están fuertemente acoplados a Microdata y funciona: mantén, pero documenta y testea.
- Evita duplicar el mismo marcado en ambos formatos para la misma entidad si no tienes un motivo claro; puede introducir inconsistencias.
Entidades base recomendadas y consistencia entre páginas
En sitios reales, la calidad del marcado depende más de la consistencia que de la cantidad. Un patrón común es definir entidades “globales” y enlazarlas desde el resto.
Organization (o LocalBusiness si aplica)
Úsala para representar a la entidad propietaria del sitio. Define un @id estable (URL con fragmento) y reutilízalo.
<script type="application/ld+json">{ "@context":"https://schema.org", "@type":"Organization", "@id":"https://example.com/#org", "name":"Example, Inc.", "url":"https://example.com/", "logo":"https://example.com/static/logo.png" }</script>WebSite (y SearchAction si tienes buscador interno)
Describe el sitio y opcionalmente el patrón de búsqueda interna.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
<script type="application/ld+json">{ "@context":"https://schema.org", "@type":"WebSite", "@id":"https://example.com/#website", "url":"https://example.com/", "name":"Example", "publisher":{ "@id":"https://example.com/#org" }, "potentialAction":{ "@type":"SearchAction", "target":"https://example.com/search?q={search_term_string}", "query-input":"required name=search_term_string" } }</script>BreadcrumbList
Útil para reflejar la jerarquía de navegación (y a veces habilitar breadcrumbs enriquecidos). Debe coincidir con el breadcrumb visible.
<script type="application/ld+json">{ "@context":"https://schema.org", "@type":"BreadcrumbList", "itemListElement":[ {"@type":"ListItem","position":1,"name":"Inicio","item":"https://example.com/"}, {"@type":"ListItem","position":2,"name":"Categoría","item":"https://example.com/categoria/"}, {"@type":"ListItem","position":3,"name":"Producto X","item":"https://example.com/categoria/producto-x"} ] }</script>Tipos por plantilla: Article / Product / FAQPage (según corresponda)
- Article: para contenido editorial (blog, noticias). Alinea
headline,datePublished,author,imagecon lo visible. - Product: para fichas de producto. Alinea
name,image,offers.price,offers.availability,skucon lo visible. - FAQPage: solo si hay preguntas y respuestas visibles en la página (no para “meter keywords”).
Guía práctica paso a paso: flujo de implementación en un proyecto real
Paso 1: Seleccionar el tipo Schema por plantilla (no por URL suelta)
Empieza por identificar tus plantillas (home, categoría, producto, artículo, FAQ, contacto…). Para cada una, decide el tipo principal y los complementarios:
- Global (todas):
Organization,WebSite - Navegación:
BreadcrumbList(donde exista breadcrumb visible) - Editorial:
ArticleoNewsArticle - Ecommerce:
Product+Offer - FAQ:
FAQPage(si hay bloque FAQ visible)
Paso 2: Mapear campos desde CMS/backend (contrato de datos)
Define un “contrato” entre contenido y marcado: qué campo del CMS alimenta qué propiedad Schema. Esto evita que el marcado se rompa cuando cambian nombres o fuentes.
| Entidad | Propiedad Schema | Fuente típica | Regla |
|---|---|---|---|
| Organization | name | Configuración global | Estable, no por página |
| Organization | logo | Asset/CDN | URL absoluta accesible |
| Article | headline | Título | Coincidir con H1 |
| Article | datePublished | Fecha publicación | ISO 8601 |
| Product | offers.price | Precio | Coincidir con UI y moneda |
| Product | offers.availability | Stock | Usar URLs schema.org (p.ej. InStock) |
Recomendación técnica: genera el JSON-LD desde un modelo tipado (TypeScript/Java/Kotlin/etc.) para reducir propiedades mal escritas y valores nulos.
Paso 3: Construir JSON-LD con IDs estables y enlaces entre entidades
Usa @id para identificar entidades de forma estable y enlazarlas. Patrón común:
https://example.com/#orgpara Organizationhttps://example.com/#websitepara WebSitehttps://example.com/ruta/pagina#articleo#productpara la entidad principal de la página
Ejemplo de Article enlazando con el publisher:
<script type="application/ld+json">{ "@context":"https://schema.org", "@type":"Article", "@id":"https://example.com/blog/mi-post#article", "mainEntityOfPage":"https://example.com/blog/mi-post", "headline":"Mi post", "image":["https://example.com/media/mi-post.jpg"], "datePublished":"2026-01-15T10:00:00Z", "dateModified":"2026-01-20T09:30:00Z", "author":{ "@type":"Person", "name":"Autor/a" }, "publisher":{ "@id":"https://example.com/#org" } }</script>Paso 4: Insertar el JSON-LD en SSR/HTML de forma segura
Ubicación: normalmente en el <head> o al final del <body>. Lo importante es que esté en el HTML entregado o que sea renderizado de forma confiable.
- SSR (Server-Side Rendering): ideal; el bot recibe el JSON-LD en la primera respuesta.
- Plantillas CMS: inserta el script desde el layout, con variables escapadas correctamente.
- Evita concatenar strings sin serialización JSON: usa
JSON.stringifyo equivalente del lenguaje para prevenir JSON inválido.
Ejemplo (Node/SSR) de inserción segura:
const schema = { "@context": "https://schema.org", "@type": "BreadcrumbList", itemListElement: items }; const html = `<script type="application/ld+json">${JSON.stringify(schema)}</script>`;Paso 5: Validar (sintaxis, elegibilidad y consistencia)
- Validador de Schema.org: comprueba que el JSON-LD es válido y que las propiedades pertenecen al tipo.
- Herramientas de prueba de resultados enriquecidos: comprueban elegibilidad para rich results específicos (por tipo).
- Inspección de URL en Search Console: verifica lo que Google detecta en una URL real (incluyendo renderizado).
Checklist de validación:
- ¿El JSON es válido (sin comas finales, comillas mal cerradas, etc.)?
- ¿Las URLs son absolutas y accesibles?
- ¿El contenido marcado existe y coincide con lo visible?
- ¿
@idyurlson consistentes con la URL canónica de la página? - ¿No hay propiedades requeridas faltantes para el rich result objetivo?
Errores comunes y cómo evitarlos
Marcado que no coincide con la UI
- FAQPage con preguntas no visibles.
- Product con
pricedistinto al mostrado por geolocalización o promociones. - Availability marcada como
InStockcuando el botón dice “Sin stock”.
Solución: deriva el marcado de la misma fuente de datos que renderiza la UI (mismo backend/DTO) y aplica reglas por locale/moneda.
Inconsistencias de entidad (Organization/WebSite)
Si cada página genera un Organization distinto (sin @id estable), pierdes coherencia semántica.
Solución: centraliza Organization/WebSite en un componente/layout global y referencia por @id desde el resto.
Duplicidad o mezcla confusa de tipos
Una página de producto marcada como Article y Product sin intención clara, o múltiples Product en una PDP.
Solución: define un “tipo principal por plantilla” y añade complementarios solo cuando aporten valor y sean correctos.
Mantenimiento: cómo evitar que el marcado se degrade con el tiempo
Cambios de plantillas y refactors
- Si el equipo cambia el componente de precio o breadcrumbs, el JSON-LD puede quedar desalineado.
- Mitigación: tests automatizados que comparen datos UI vs datos Schema (por ejemplo, snapshot del JSON-LD y asserts de campos críticos).
Locales, monedas y variantes
- El marcado debe reflejar el contenido de la variante servida (idioma, moneda, disponibilidad por país).
- Mitigación: generar Schema con el mismo contexto de locale que la página (no usar “defaults” globales).
IDs estables y estrategia de versionado
- No uses IDs efímeros (por ejemplo, IDs internos que cambian al migrar CMS) como
@idpúblico si no son estables. - Preferible:
@idbasado en URL canónica + fragmento (#product,#article), y para entidades globales un#orgfijo. - Si cambias estructura de URLs o dominios, revisa y migra los
@idpara mantener consistencia.
Observabilidad
- Registra en logs/monitoring cuándo falla la generación del JSON-LD (por ejemplo, campos obligatorios nulos).
- Incluye alertas cuando el validador interno detecte JSON inválido en producción.