Datos estructurados de Schema.org
Polski for WooCommerce no imprime datos estructurados propios. WooCommerce ya emite un grafo JSON-LD Product en cada página de producto, y el plugin añade campos a ese grafo mediante el filtro woocommerce_structured_data_product.
Es una decisión deliberada: dos grafos Product en una misma página son un error de duplicación, y los buscadores los tratan como uno solo. Todo lo que sigue es una adición a lo que emite WooCommerce, nunca un sustituto.
Qué viene de dónde
Sección titulada «Qué viene de dónde»| Origen | Campos |
|---|---|
| WooCommerce | name, description, image, sku, offers con precio, moneda, disponibilidad y estado, aggregateRating y review |
| Polski for WooCommerce | brand, manufacturer, gtin8 / gtin12 / gtin13 / gtin14, additionalProperty con el precio por unidad, shippingDetails, nutrition |
| Polski for WooCommerce, en la oferta | priceValidUntil y el precio mínimo Omnibus de 30 días como priceSpecification |
Si una página de producto no lleva datos estructurados de WooCommerce, no hay nada a lo que añadir y el plugin no añade nada. Esto importa cuando un plugin de SEO sustituye el grafo de WooCommerce por el suyo, consulta Plugins de SEO más abajo.
Activarlo y desactivarlo
Sección titulada «Activarlo y desactivarlo»Las adiciones del primer bloque tienen dos llaves: el módulo Datos estructurados (Schema.org) debe estar activo y, dentro de él, el interruptor Activar la integración de datos estructurados. Desactivar cualquiera de los dos deja el grafo de WooCommerce intacto y completo.
| Ajuste | Clave de opción | Por defecto | Controla |
|---|---|---|---|
| Activar la integración de datos estructurados | polski_seo[schema_enabled] |
activado | Todo lo de la tabla siguiente |
| Incluir la marca | polski_seo[schema_brand] |
activado | brand |
| Incluir el fabricante | polski_seo[schema_manufacturer] |
activado | manufacturer |
| Incluir códigos de barras (GTIN) | polski_seo[schema_gtin] |
activado | de gtin8 a gtin14 |
| Incluir el precio por unidad | polski_seo[schema_unit_price] |
activado | additionalProperty |
El plazo de entrega y la información nutricional no tienen interruptor propio. Aparecen cuando el producto tiene esos datos y desaparecen cuando no.
Las dos adiciones a la oferta van por separado. priceValidUntil se escribe con independencia del módulo, porque una oferta sin ese campo pierde la elegibilidad para resultados enriquecidos y no hay motivo para que una tienda lo quiera. La especificación de precio Omnibus sigue al módulo Omnibus y solo aparece mientras el producto está realmente rebajado.
Los campos que añade el plugin
Sección titulada «Los campos que añade el plugin»Marca y fabricante
Sección titulada «Marca y fabricante»{ "brand": { "@type": "Brand", "name": "MiMarca" }, "manufacturer": { "@type": "Organization", "name": "Fabricante XYZ Sp. z o.o.", "contactPoint": { "@type": "ContactPoint", "contactType": "product safety", } }}brand es la primera marca encontrada para el producto. manufacturer parte del nombre del fabricante del panel de producto, y un nombre de fabricante GPSR en el producto lo sustituye, añadiendo el contacto GPSR como contactPoint de tipo product safety. La dirección no se publica y el texto de contacto se imprime tal como lo escribiste.
El código de barras del panel de producto se publica bajo la clave que corresponde a su longitud: 8 dígitos son gtin8, 12 gtin12, 13 gtin13, 14 gtin14. Cualquier otra longitud se publica como gtin a secas, lo cual es Schema.org válido pero le dice menos a Google.
Precio por unidad
Sección titulada «Precio por unidad»Schema.org no tiene una propiedad para el precio por unidad, así que la cifra viaja en additionalProperty:
{ "additionalProperty": [ { "@type": "PropertyValue", "name": "Precio por unidad", "value": "8.90 / 100 g" } ]}Plazo de entrega
Sección titulada «Plazo de entrega»Cuando el producto resuelve un plazo de entrega, se añade un bloque OfferShippingDetails:
{ "shippingDetails": { "@type": "OfferShippingDetails", "deliveryTime": { "@type": "ShippingDeliveryTime", "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" }, "transitTime": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" } }, "shippingDestination": { "@type": "DefinedRegion", "addressCountry": "PL" } }}Conviene conocer dos límites antes de apoyarse en esto. El tiempo de preparación está fijado en 0 a 1 día en lugar de leerse de tus ajustes, y el máximo de tránsito se toma de los dígitos de tu texto de plazo de entrega, con 5 días como valor de reserva cuando el texto no lleva ninguno. Un plazo escrito como «2 a 3 días laborables» da por tanto un tránsito máximo de 23. Deja una sola cifra en el texto si ese número te importa.
El destino es Polonia.
Información nutricional
Sección titulada «Información nutricional»Los productos con datos nutricionales del módulo de alimentación reciben un objeto NutritionInformation:
| Nutriente guardado | Campo de Schema.org |
|---|---|
| Energía (kcal) | calories |
| Grasas | fatContent |
| de las cuales saturadas | saturatedFatContent |
| Hidratos de carbono | carbohydrateContent |
| de los cuales azúcares | sugarContent |
| Proteínas | proteinContent |
| Fibra | fiberContent |
| Sal | sodiumContent, convertido |
La última fila es la que conviene leer dos veces. El anexo XV del Reglamento 1169/2011 declara sal, mientras que Schema.org solo ofrece sodiumContent, y no son la misma cifra: la sal es el sodio multiplicado por 2,5. El valor se divide entre 2,5 antes de publicarlo, de modo que un producto etiquetado con 2,5 g de sal publica 1 g de sodio. Hasta la 1.36.7 la cifra se copiaba sin cambios, lo que publicaba cada producto alimenticio como dos veces y media más salado de lo que dice su propia etiqueta.
La energía en kJ no tiene equivalente en Schema.org y no se publica. Sigue apareciendo en la tabla de la ficha de producto, donde el reglamento la exige.
priceValidUntil y el precio Omnibus
Sección titulada «priceValidUntil y el precio Omnibus»{ "offers": [ { "priceValidUntil": "2026-12-31", "priceSpecification": { "@type": "UnitPriceSpecification", "priceType": "https://schema.org/MinimumPrice", "name": "Precio más bajo de los últimos 30 días", "price": "79.00", "priceCurrency": "PLN" } } ]}priceValidUntil usa la fecha de fin de la rebaja cuando el producto la tiene, y un año a partir de hoy cuando no. Solo se escribe si WooCommerce dejó el campo vacío.
La priceSpecification lleva el precio más bajo de los 30 días anteriores. Es la misma cifra que se muestra a la clientela bajo el precio, publicada en una forma que un buscador o un asistente puede citar, y solo aparece mientras el producto está rebajado y el módulo Omnibus está activo.
Los campos añadidos se guardan por producto en un transient polski_schema_<id> durante 12 horas, y el transient se borra cada vez que se guarda el producto.
Una consecuencia: cambiar los interruptores de arriba no vacía la caché. Un producto existente conserva sus campos anteriores hasta 12 horas, o hasta que se guarde. Guarda el producto para ver el cambio de ajustes de inmediato.
Extender
Sección titulada «Extender»El plugin no expone filtros propios para los datos estructurados. Usa el filtro de WooCommerce, con una prioridad superior a 10 para que tu callback se ejecute después del suyo:
add_filter( 'woocommerce_structured_data_product', function ( array $markup, WC_Product $product ): array { $markup['award'] = 'Producto del Año 2025';
if ( isset( $markup['offers'][0] ) ) { $markup['offers'][0]['warranty'] = [ '@type' => 'WarrantyPromise', 'durationOfWarranty' => [ '@type' => 'QuantitativeValue', 'value' => 24, 'unitCode' => 'MON', ], ]; }
return $markup;}, 20, 2 );Para quitar un campo que el plugin haya añadido, elimínalo en ese mismo callback. Para que el plugin deje de añadir nada, usa los interruptores en lugar de código.
Plugins de SEO
Sección titulada «Plugins de SEO»No hay detección ni comportamiento por plugin. Todo depende de lo que el plugin de SEO haga con el grafo de WooCommerce:
- Deja los datos estructurados de WooCommerce en su sitio. Las adiciones aparecen tal como se describe.
- Sustituye los datos estructurados de WooCommerce por su propio grafo. No se añade nada, porque el filtro nunca se ejecuta. Varios plugins de SEO tienen un interruptor justo para esto; vuelve a activar allí los datos estructurados de WooCommerce, o traslada los campos que necesites al grafo de ese plugin. Cuál de ellos los elimina, y si lo hace por defecto, cambia entre sus versiones, así que revisa el código fuente de tu propia página en vez de una lista.
Si ves dos bloques Product en el código fuente, el segundo no viene de este plugin. Búscalo en tu plugin de SEO o en el tema.
Validar
Sección titulada «Validar»El plugin no registra nada sobre datos estructurados, así que un debug.log vacío no demuestra nada en ninguna dirección. Lee el código fuente de la página o usa las dos herramientas anteriores.
Resolución de problemas
Sección titulada «Resolución de problemas»No aparece ningún campo añadido. Comprueba que los datos estructurados propios de WooCommerce estén en la página. Si no hay bloque Product, el filtro no tuvo sobre qué actuar.
Sigue faltando un campo aunque lo he rellenado. El producto debe tener el dato, el interruptor correspondiente debe estar activo y después hay que guardar el producto para vaciar la caché de 12 horas.
No hay valoraciones. aggregateRating viene de WooCommerce, no de este plugin, y necesita al menos una reseña con puntuación por estrellas.
Google no muestra resultados enriquecidos. Los resultados enriquecidos llegan tras la reindexación, que tarda semanas. Valida primero y luego espera.
Informar de problemas: github.com/wppoland/polski/issues