# Offer de Schema.org: precio y disponibilidad en el marcado

> Qué es el tipo Offer de Schema.org, cómo se escriben el precio, la moneda y la disponibilidad, qué pide Google y en qué se diferencia de AggregateOffer.

URL: https://clione.ai/es/glosario/schema-offer/
Lang: es

En el marcado de una ficha, Offer responde a dos preguntas que el producto no contesta: **a qué precio se vende y si se puede comprar hoy**. Es un tipo de [Schema.org](/es/glosario/schema-org/) y se escribe en inglés porque es un nombre del vocabulario. No tiene nada que ver con una oferta en el sentido de rebaja: una camisa a precio normal también tiene su Offer. Y no es el producto, que tiene su propio tipo, [Product](/es/glosario/schema-product/). Te importa porque es la parte de los [datos estructurados](/es/glosario/datos-estructurados/) que Google necesita para enseñar el precio en los [resultados enriquecidos](/es/glosario/resultados-enriquecidos/), y porque es la que más se desajusta: cada rebaja, cada cambio de existencias, la deja vieja si no se actualiza a la vez que la ficha.

## Cómo funciona

Schema.org define Offer como un ofrecimiento para transferir algún derecho sobre un artículo o para prestar un servicio, con ejemplos como vender entradas, alquilar una película, reparar una moto o prestar un libro. Si no se indica otra cosa, **una Offer se entiende como una oferta para vender**.[^schema-org-offer] En una ficha, el producto la lleva dentro con la propiedad `offers`.

Las propiedades que importan en una tienda, según Schema.org:[^schema-org-offer]

| Propiedad                 | Qué dice                                                                              |
| ------------------------- | ------------------------------------------------------------------------------------- |
| `price`                   | El precio. Con punto como separador decimal, nunca coma, y con los dígitos del 0 al 9 |
| `priceCurrency`           | La moneda, en formato ISO 4217, como `EUR` o `USD`                                    |
| `availability`            | La disponibilidad: en existencias, agotado, en preventa                               |
| `itemCondition`           | El estado del artículo, por ejemplo nuevo o usado                                     |
| `priceValidUntil`         | La fecha a partir de la cual el precio deja de estar disponible                       |
| `seller`                  | Quién vende: una organización o una persona                                           |
| `shippingDetails`         | Las condiciones de envío                                                              |
| `hasMerchantReturnPolicy` | La [política de devoluciones](/es/glosario/politica-de-devoluciones/) que se aplica   |

Google toma ese vocabulario y fija sus mínimos. Para las [fichas de comerciante](/es/glosario/fichas-de-comerciante/), **la oferta tiene que llevar un precio mayor que cero y la moneda en código ISO 4217 de tres letras**. Recomienda además la disponibilidad, con valores como `https://schema.org/InStock`, `OutOfStock`, `BackOrder` o `PreOrder`; el estado, como `https://schema.org/NewCondition`; la fecha de validez del precio; los detalles de envío; la política de devoluciones, con el tipo [`MerchantReturnPolicy`](/es/glosario/merchantreturnpolicy/); y la URL desde la que se compra.[^google-merchant-listing]

Hay una condición más que no está en el vocabulario. Las fichas de comerciante **solo aceptan Offer, no [AggregateOffer](/es/glosario/aggregateoffer/)**, porque para optar a ellas el comerciante tiene que ser quien vende el producto. Los fragmentos de producto, en cambio, aceptan las dos.[^google-merchant-listing] Para ellos el precio es obligatorio si usas Offer, la moneda es recomendable y Google avisa de que el fragmento puede no mostrarse si `priceValidUntil` indica una fecha pasada.[^google-product-snippet]

Y una advertencia que es casi exclusiva de Offer. Google puede leer datos estructurados añadidos con JavaScript, pero avisa de que **el marcado generado dinámicamente puede hacer que los rastreos de Shopping sean menos frecuentes y menos fiables, un problema para lo que cambia rápido, como el precio y la disponibilidad**.[^google-js-sd]

## En una tienda

La oferta de una camisa en rebajas, con lo que muestra la ficha y cómo se escribe en el marcado. **Ejemplo ficticio**: la tienda, el producto, el precio y las fechas son inventados.

| Lo que muestra la ficha                | Cómo se escribe en la oferta                                                                                                                    |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| 29,90 € (antes 39,90 €)                | `"price": "29.90"` y `"priceCurrency": "EUR"` |
| «En stock»                             | `"availability": "https://schema.org/InStock"`                                                                                                  |
| «Nuevo»                                | `"itemCondition": "https://schema.org/NewCondition"`                                                                                            |
| «Precio válido hasta el 31 de octubre» | `"priceValidUntil": "2026-10-31"`                                                                                                               |

```json
"offers": {
  "@type": "Offer",
  "price": "29.90",
  "priceCurrency": "EUR",
  "availability": "https://schema.org/InStock",
  "itemCondition": "https://schema.org/NewCondition",
  "priceValidUntil": "2026-10-31",
  "url": "https://www.example.com/camisa-lino-calella"
}
```

Tres cosas que el ejemplo enseña. El precio de la oferta es el que paga hoy el cliente, el rebajado, porque los datos tienen que representar la página tal como está.[^google-sd-policies] La fecha de validez solo se pone si la ficha la dice; aquí la rebaja tiene un final anunciado. Y la disponibilidad es una dirección del vocabulario, no la frase que ve el cliente: «Últimas unidades» o «Envío en 48 horas» no tienen traducción literal, así que se marca el hecho (hay existencias) y el resto se queda en la página.


Escribir el precio como se ve en una tienda española, «29,90 €», dentro de `price`. Schema.org pide punto como separador decimal y la moneda en su propia propiedad, con su código ISO 4217.[^schema-org-offer]


## Cómo comprobarlo

1. **Busca `offers` en el código fuente de la ficha** y apunta el precio, la moneda y la disponibilidad que declara.
2. **Compáralos con lo que ve un cliente en ese momento**, precio rebajado incluido. Si no coinciden, los datos no representan la página.[^google-sd-policies]
3. **Mira la fecha de `priceValidUntil`**, si existe. Si ya pasó, el fragmento de producto puede no mostrarse.[^google-product-snippet]
4. **Comprueba si la oferta está en el HTML que sirve el servidor** o la añade JavaScript después: para el precio y la disponibilidad, Google avisa de que lo segundo hace los rastreos de Shopping menos frecuentes y menos fiables.[^google-js-sd]
5. **Pasa la URL por la [Prueba de resultados enriquecidos](/es/glosario/prueba-de-resultados-enriquecidos/)** para ver qué experiencias detecta y con qué errores.[^rich-results-test]


## Concepto cercano: AggregateOffer

AggregateOffer es el tipo que Schema.org propone **cuando un mismo producto tiene varias ofertas**, por ejemplo el mismo par de zapatos vendido por comercios distintos, y resume el conjunto con el precio más bajo (`lowPrice`), el más alto (`highPrice`) y el número de ofertas (`offerCount`).[^schema-org-aggregateoffer] Encaja en un comparador o en un _marketplace_; en la ficha de una tienda que vende lo suyo, lo que corresponde es Offer, y Google solo acepta Offer para las fichas de comerciante.[^google-merchant-listing]

Para seguir, la [ruta de lectura de datos estructurados](/es/aprender/datos-estructurados/) ordena el resto de términos, y la entrada de [JSON-LD](/es/glosario/json-ld/) enseña dónde va esta oferta dentro del bloque de la ficha.
