Schema, fechas y el último chequeo antes de publicar

Datos estructurados válidos y datos estructurados elegibles son dos estados distintos, y una propiedad faltante decide en cuál estás. Nuestro propio post salió con una fecha de publicación siete días en el futuro, escrita ahí por nuestro propio producto. Tres corridas distintas de claude-seo la encontraron, y esta clase recorre el arreglo.

Módulo 5 · 11 de 13 · 18 min

Este curso es independiente. No tiene relación con Anthropic ni con AgriciDaniel, que escribe claude-seo, y nadie de ese lado lo revisó. Corrido con claude-seo v2.4.1 el 2026-10-03.

Qué vas a poder hacer

  • Distinguir un bloque de schema válido de uno elegible para un resultado enriquecido.
  • Chequear que todas las superficies con fecha coincidan antes de que la página sea pública.
  • Entregar un borrador aprobado a tu repositorio y publicarlo vos.

Publicar es el paso donde los errores chicos se vuelven públicos, y los más baratos de cometer son una propiedad faltante y una fecha equivocada. El 2026-10-03 el agente de schema de nuestra auditoría puntuó los datos estructurados de este sitio en 78 sobre 100, con un grafo maduro y dos propiedades requeridas ausentes. Ese mismo día, otras dos corridas de claude-seo marcaron un post nuestro por llevar una fecha de publicación siete días en el futuro. Esa fecha salió de nuestro propio producto: el artículo estaba planificado para el 2026-10-10 en el calendario, la entrega escribió ese día planificado en el archivo, y el post salió en vivo el 2026-09-28. Esta clase recorre los dos hallazgos y después la parte de publicar que ninguna herramienta hace por vos.

Un validador y un resultado enriquecido preguntan cosas distintas

Un marcado válido es un marcado que un parser acepta, y un marcado elegible es un marcado que Google puede convertir en una función. Un bloque puede pasar la primera vara y quedar bastante abajo de la segunda, porque un resultado enriquecido tiene una lista de propiedades requeridas y tu marcado las lleva o no las lleva. Nuestro BlogPosting parseó limpio, con headline, datePublished, dateModified, author como referencia a una Person y publisher como referencia a una Organization, todos bien tipados.

Y seguía sin ser elegible para el resultado enriquecido de artículo, porque faltaba image en todos los posts del sitio. Una propiedad ausente, y el blog entero quedó afuera de una función para la que calificaba en todo lo demás. Leé la lista de requeridas del resultado que querés antes de puntuar tu propio marcado, y tomá todo lo demás que te diga el validador como contexto.

Nuestro propio grafo sacó 78 sobre 100

La auditoría encontró datos estructurados en siete plantillas de página, y la forma era la buena noticia. Organization, WebSite y SoftwareApplication con un Offer en la home; WebPage y BreadcrumbList en precios; WebPage, FAQPage y BreadcrumbList en una página de feature; BlogPosting, Organization, Person y FAQPage en el post; una WebApplication con un Offer en una herramienta gratis. Todos los @context apuntaban a la URL canónica de schema.org, todas las URL eran absolutas, todas las fechas eran ISO 8601, y las entidades estaban cruzadas por @id, así que un grafo describía un sitio.

Tres cosas le pusieron techo al puntaje. BlogPosting no tenía image y los posts no tenían BreadcrumbList, mientras que las otras cuatro plantillas sí. SoftwareApplication y WebApplication no tenían aggregateRating ni review, que el resultado enriquecido de Software App requiere. Y FAQPage, presente en cuatro plantillas, ya no gana nada en la SERP.

Algunos huecos son una línea de código y otros necesitan datos que no tenés

Partir la lista de huecos en dos es el primer movimiento útil, porque las dos mitades cuestan distinto. image en BlogPosting nos salió gratis: cada post ya renderiza una tarjeta OG en una URL estable, así que completar la propiedad era apuntar a un recurso que existe. BreadcrumbList en los posts era el mismo tipo de trabajo, porque otras cuatro plantillas ya emitían uno.

aggregateRating es del otro tipo. La propiedad quiere datos de reseñas reales, y un sitio sin reseñas no tiene nada honesto para poner ahí. Nuestra auditoría escribió la instrucción adentro del hallazgo: sumalo solo cuando existan datos de reseñas genuinos, y nunca fabriques calificaciones. Un agente al que le pedís "completá el schema" te inventa feliz un 4,8 sobre 237 reseñas, y ese número pasa a ser una afirmación fabricada en una página cuyo argumento entero es que informa cosas medidas. Dejá la propiedad vacía hasta que existan los datos.

FAQPage es marcado válido sin función en la SERP desde mayo de 2026

Google retiró los resultados enriquecidos de FAQ para todos los sitios el 2026-05-07, así que hoy el marcado FAQPage no gana ninguna función de búsqueda. Nuestra auditoría lo registra como información en las cuatro plantillas que lo llevan, recomienda dejarlas así y desaconseja sumarlo a páginas nuevas por motivos de SERP. El agente geo de la misma corrida propuso sumar FAQPage a más páginas, y el orquestador descartó esa propuesta con la fecha del retiro adjunta.

Escribí igual el FAQ visible. Lo lee un lector con una pregunta, y lo lee un motor de respuestas buscando un pasaje corto y citable, que es de lo que se trata la clase 12. Si querés el marcado por lo que sea que parsee tu JSON-LD, el generador de schema FAQ gratis lo arma con las preguntas que ya escribiste, y lo de la SERP lo decidís aparte.

Una fecha de calendario se convirtió en fecha de publicación

El artículo estaba planificado para el 2026-10-10, y ese día planificado es el que la entrega escribió en el campo publishedAt del archivo. El post salió en vivo el 2026-09-28 y cuenta un fin de semana del 26 y el 27 de septiembre. Así que la página se publicó llevando una fecha futura en la línea que ve un lector, en datePublished y dateModified, en article:published_time y en cuatro valores de lastmod del sitemap.

Tres corridas lo encontraron el mismo día, desde tres ángulos. El orquestador de la auditoría lo confirmó contra el sitio en vivo y lo ató a los lastmod futuros del sitemap como una misma causa raíz. El comando de contenido lo puntuó como problema de confianza de severidad alta, porque la fecha visible contradice un cuerpo que dice que la cosa salió en vivo el 27 de septiembre. El comando de geo lo calificó de crítico y adivinó bien el mecanismo: el producto está escribiendo la fecha programada en lugar de la real. Corregimos la fecha en el repositorio al 2026-09-28.

El arreglo sugerido se trajo el bug adentro

El agente de schema cerró su informe con un bloque de JSON-LD listo para pegar que resolvía el image faltante, y ese bloque reusaba 2026-10-10 en las dos fechas. El orquestador lo agarró y dejó una nota en la sección de verificación diciéndole al lector que use la fecha real de publicación.

La salida copiable es donde un valor equivocado viaja más rápido. Una fecha que habrías cuestionado en una oración se cuela adentro de un bloque de código, porque un bloque de código se lee como algo que produjo una máquina y chequeó una máquina. Leé el ejemplo antes de pegarlo, y chequeá los valores que el ejemplo se trajo de la página que estaba describiendo.

La entrega deja un archivo borrador en tu repositorio y para ahí

Un destino de entrega son cinco respuestas: repositorio, rama, plantilla de ruta, formato del cuerpo y el mapeo del frontmatter. El nuestro dice GitHub ch0rch/seodraft-app, rama main, content/blog/{locale}/{slug}.mdoc, cuerpo Markdoc, preset de Keystatic, y ese preset mapea date a publishedAt, updatedDate a updatedAt y descarta image. delivery_status te devuelve esas cinco respuestas, más si hay un token guardado, y nunca devuelve el token.

Cada entrega escribe draft: true en el archivo diga lo que diga la marca del artículo, no hay opción para apagarlo, y nunca se borra nada de tu repositorio. Volver a entregar sobrescribe la misma ruta, así que repetirlo es seguro; cuando un slug se mueve, se escribe la ruta nueva y se te nombra la vieja para que la borres a mano. La página de entrega al CMS describe los destinos con más detalle.

Aprobar es una sola llamada que chequea primero las reglas

approve_post se niega si el último chequeo de run_gate no pasó, lo que convierte la aprobación en un gate más que en un botón. Cuando pasa, la misma llamada mueve el artículo a ready y lo entrega al destino configurado. Nuestro propio post llegó a ese estado con lastGateOk: true y cayó en content/blog/en/how-to-distribute-an-mcp-server.mdoc el 2026-09-28 a las 03:11 UTC, con su traducción al español enlazada como el mismo artículo en otro idioma.

Después de eso la herramienta terminó y vos no. El archivo de tu repositorio espera a que una persona lo abra, chequee las fechas, chequee los enlaces, suba las imágenes que pidieron los slots del artículo y publique desde el CMS. Nuestro bug de fecha vivió en ese hueco unos días, que es la versión honesta de la clase: el hueco existe para que un humano agarre lo que escribió un pipeline, y funciona solo cuando el humano mira.

El árbol en español se declaraba inglés en el HTML crudo

El único ítem crítico de la auditoría no tenía nada que ver con el post. Nuestras rutas /es servían <html lang="en"> en el HTML que sale del servidor, con el idioma correcto aplicado después por un script de cliente. Un crawler que lee HTML crudo, y cualquier cliente que no corre JavaScript, veía contenido en español etiquetado como inglés en todo el árbol español.

Lo arreglamos renderizando lang en el servidor a partir de la propia ruta, así el atributo sale correcto en el primer byte. El chequeo es una línea de curl contra tu propio sitio, y vale la pena correrlo después de cualquier cambio en un layout raíz. Una declaración de idioma es de esas cosas que están bien en todas partes o mal en todas partes, y en un navegador no se nota.

Qué leer la mañana que publicás

Cuatro lecturas forman un chequeo de publicación, y en un post normal llevan unos diez minutos. Leé las fechas en cada superficie que lleve una, incluido tu sitemap, que el chequeador de sitemap gratis te lista sin instalar nada. Leé las propiedades requeridas del resultado enriquecido que querés, y dejá vacío todo lo que no puedas respaldar con datos reales. Abrí el archivo entregado y confirmá que la marca de borrador sigue ahí, y después publicá vos desde tu CMS.

La cuarta lectura es la que todos se saltean: abrí la URL en vivo después y mirá qué dice la página de verdad. Nuestro post estaba bien en el borrador, bien en la entrega y mal en la página, y la diferencia fue un campo que un pipeline completó con el día que alguien había planificado. La clase 12 agarra esa misma página publicada y le hace otra pregunta: si un motor de respuestas puede citarla.

Pasos

  1. Paso 1

    claude-seo

    Leé la mitad de schema de la auditoría

    La auditoría que corriste en la clase 3 ya trae un informe de schema por plantilla de página. Abrí ese archivo solo ahora, porque esta es la clase donde sus hallazgos se ejecutan. La columna que sirve es la que nombra propiedades requeridas, que es lo que separa un marcado que un validador acepta de un marcado que Google puede mostrar.

    /seo audit https://your-site.com

    Qué deberías ver

    Una lista de tipos por plantilla y un puntaje. El nuestro devolvió 78/100 sobre un grafo con Organization, WebSite, SoftwareApplication, WebPage, BreadcrumbList, BlogPosting, Person y FAQPage, cruzados por `@id`, con todos los `@context` en https://schema.org.

  2. Paso 2

    claude-seo

    Separá los huecos que podés llenar de los que no

    Pegá esto como prompt contra el informe de schema. Algunos huecos son una línea de código y otros necesitan datos que todavía no existen, y el segundo tipo es donde un agente descuidado inventa un número. Una calificación sin reseñas atrás es un dato fabricado en una página que dice ser una fuente.

    For every schema type on this page, list the properties the rich result requires and which of them are missing. Separate the ones I can fill today from the ones that need data I do not have.

    Qué deberías ver

    Dos listas cortas. La nuestra puso `image` de BlogPosting en la primera, porque la tarjeta OG ya existe, y `aggregateRating` de SoftwareApplication en la segunda, donde la auditoría escribió la instrucción completa: sumalo solo cuando existan reseñas reales, nunca lo fabriques.

  3. Paso 3

    claude-seo

    Hacé que todas las superficies digan la misma fecha

    Una fecha de publicación vive en cuatro o cinco lugares, y se despegan de a un deploy por vez. Corré esto contra cualquier post que estés por publicar, y contra los tres que publicaste el mes pasado. El sitemap es la superficie que todos olvidan, y le enseña a un crawler cuánto vale tu `lastmod`.

    Compare the visible date, datePublished, dateModified, article:published_time and the sitemap lastmod for this URL. Tell me which of them disagree with each other or sit in the future.

    Qué deberías ver

    Una fecha por superficie, una al lado de la otra. La nuestra volvió con 2026-10-10 en todas, para un post que salió en vivo el 2026-09-28, más cuatro valores de `lastmod` del sitemap con ese mismo día futuro.

  4. Paso 4

    seodraft

    Sabé dónde caen tus borradores antes de aprobar uno

    `delivery_status` devuelve las cinco respuestas que forman un destino de entrega: repositorio, rama, plantilla de ruta, formato del cuerpo y el mapeo del frontmatter, más si hay un token guardado. Nunca devuelve el token. Leelo una vez antes de tu primera aprobación, así el primer archivo cae donde esperás en lugar de en un lugar que vas a tener que buscar.

    Show me delivery_status for this workspace.

    Qué deberías ver

    Las cinco respuestas de tu workspace. El nuestro dice GitHub `ch0rch/seodraft-app`, rama `main`, ruta `content/blog/{locale}/{slug}.mdoc`, cuerpo Markdoc y el preset de Keystatic, que mapea `date` a `publishedAt`.

  5. Paso 5

    seodraft

    Aprobá una vez, y que la aprobación entregue

    `approve_post` es un solo acto: se niega si el último chequeo de `run_gate` no pasó, mueve el artículo a `ready` y, con un destino configurado, lo entrega en la misma llamada. Cada entrega escribe `draft: true` diga lo que diga el artículo, no hay interruptor para apagarlo, y nunca se borra nada de tu repositorio.

    Run run_gate on this post and show me every finding. If it passes, wait for me to say yes before calling approve_post.

    Qué deberías ver

    Una lista de hallazgos y después un archivo en tu repositorio. El nuestro pasó con `lastGateOk: true` y cayó en `content/blog/en/how-to-distribute-an-mcp-server.mdoc` el 2026-09-28 a las 03:11 UTC, con la traducción al español enlazada.

Checklist

Tildá todas las líneas y la clase se marca como completada.

Checkpoint

Un validador acepta tu bloque BlogPosting sin errores. ¿La página es elegible para un resultado enriquecido de artículo?Ver la respuesta

Solo si están todas las propiedades requeridas, y un validador que no informa errores contesta una pregunta más angosta que esa. El nuestro parseó limpio con `headline`, `datePublished`, `dateModified`, `author` y `publisher` bien tipados, y seguía bloqueado para el resultado enriquecido de artículo porque faltaba `image` en todos los posts del sitio. La auditoría también marcó ahí la falta de BreadcrumbList, que las otras plantillas ya tenían. Leé la lista de requeridas del resultado enriquecido que querés y chequeá tu marcado contra esa lista.

Tu agente aprobó un artículo y el archivo está en tu repositorio. ¿El post es público?Ver la respuesta

El archivo lleva `draft: true` y tu CMS sigue siendo lo que lo publica. seodraft fuerza esa marca en cada entrega diga lo que diga el campo del artículo, y no hay opción para apagarla, así que un artículo entregado espera a que lo abra un humano. En ese hueco pasa el trabajo de esta clase: chequeás fechas, schema, enlaces y las imágenes que el artículo pidió, y recién ahí publicás. Nuestro propio bug de fecha muestra para qué está el hueco, y el hueco solo le sirve a quien lo usa.

Qué dijo esta clase

  • Un bloque de schema puede ser válido y seguir sin ser elegible: nuestro grafo sacó 78/100 porque BlogPosting no tenía `image` y los posts no tenían BreadcrumbList.
  • Google retiró los resultados enriquecidos de FAQ para todos los sitios el 2026-05-07, así que el marcado FAQPage es información para lo que lea el JSON-LD y no compra ninguna función en la SERP.
  • Sumá `aggregateRating` solo cuando existan reseñas reales. Una auditoría que te dice que no fabriques nada está dando la instrucción más importante de la página.
  • Nuestro producto escribió la fecha de calendario 2026-10-10 en el `publishedAt` de un post que salió en vivo el 2026-09-28, y la auditoría, `/seo content` y `/seo geo` la marcaron por separado.
  • La entrega escribe un archivo borrador en tu repositorio con `draft: true` forzado y no borra nada. El humano lo chequea y publica desde su propio CMS.

Preguntas

¿Qué tipos de schema necesita de verdad un post de blog?
BlogPosting y BreadcrumbList, cada uno con sus propiedades requeridas completas, más la Organization y la Person que tu sitio ya declara y enlaza por `@id`. Nuestra auditoría encontró cortos a los dos primeros: faltaba `image` en BlogPosting en todo el blog, lo que bloquea el resultado enriquecido de artículo, y BreadcrumbList existía en las plantillas de precios, features, alternativas y herramientas mientras que los posts no tenían ninguno. Sumar tipos que la página no se ganó no compra nada; completar las propiedades requeridas de los tipos que ya tiene es el trabajo.
¿Conviene sumar marcado FAQPage igual?
Google retiró los resultados enriquecidos de FAQ para todos los sitios el 2026-05-07, así que hoy el marcado no gana ninguna función en la SERP. Nuestra auditoría lo registra como información en las páginas que ya lo llevan y recomienda dejarlas así, y el orquestador descartó la propuesta de su propio agente geo de sumar FAQPage a más páginas por ese mismo motivo. El bloque de FAQ visible sigue valiendo la pena, porque lo leen un lector con una pregunta y un motor de respuestas buscando un pasaje citable.
¿Por qué una fecha programada terminó como fecha de publicación?
El artículo estaba planificado para el 2026-10-10 en el calendario, y la entrega escribió ese día planificado en el campo `publishedAt` del archivo. El post salió en vivo el 2026-09-28 y contaba un fin de semana de septiembre, así que la página se publicó declarando una fecha futura en su línea visible, en `datePublished` y `dateModified`, en `article:published_time` y en cuatro valores de `lastmod` del sitemap. Lo corregimos en el repositorio al día real. El hábito que deja el episodio es barato: antes de publicar, leé la fecha en cada superficie que lleve una.

Clase siguiente

Búsqueda con IA y GEO

Qué hace que un pasaje sea citable por un motor de respuestas, qué puntúa el comando geo de claude-seo y qué mitad de ese informe es una estimación.

La misma clase, en Markdown plano: /es/learn/claude-seo/schema-and-publishing.md

Volver al curso