Offer
Offer is the transaction layer of schema.org. It wraps around a price, a currency, an availability status, and an item condition. Without an Offer block, a Product has no price in search results. Google, Bing, and AI crawlers all read Offer properties to populate the price badge, the availability label, and the condition tag in rich results. If your page sells something and the price is not showing up in search, a missing or malformed Offer is almost always the reason.
Offer appears inside many schema.org types. Product uses it in the offers property for purchase pricing. Event uses it for ticket pricing. Service uses it for rate tables. SoftwareApplication uses it for pricing tiers. Course uses it for enrollment cost. In every case, the Offer carries the same core set of properties: price, priceCurrency, availability, and itemCondition. Google requires an Offer block for the Product rich result, and since 2023 it also requires shippingDetails and hasMerchantReturnPolicy for Merchant Listing eligibility.
Full example of schema.org/Offer json-ld markup
The markup is verified as valid with Rich Results Test from Google.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Offer",
"@id": "https://xoocode.com/shop/dunmore-1290#xootee-offer",
"name": "XooTee Classic in Cerulean Blue",
"url": "https://xoocode.com/shop/xootee-classic-cerulean",
"price": 39.95,
"priceCurrency": "CAD",
"priceValidUntil": "2026-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "LocalBusiness",
"@id": "https://xoocode.com/shop/dunmore-1290",
"name": "Xoo Code Shop Dunmore"
},
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": {
"@type": "MonetaryAmount",
"value": 5.99,
"currency": "CAD"
},
"shippingDestination": {
"@type": "DefinedRegion",
"addressCountry": "CA"
},
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": {
"@type": "QuantitativeValue",
"minValue": 1,
"maxValue": 2,
"unitCode": "d"
},
"transitTime": {
"@type": "QuantitativeValue",
"minValue": 3,
"maxValue": 7,
"unitCode": "d"
}
}
},
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "CA",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn"
}
}
</script>price and priceCurrency
price must be a number (not a string), and priceCurrency must be a 3-letter ISO 4217 code. A common mistake is writing "39.95" (a quoted string) instead of 39.95 (a number), or writing "dollars" instead of "CAD". Google is somewhat forgiving about quoted prices, but other processors reject them outright. The currency code is strict: USD, EUR, GBP, CAD, and JPY are valid. Dollar signs, euro symbols, or spelled-out currency names are not.
availability and itemCondition
availability and itemCondition are schema.org enumeration values. They must use PascalCase: InStock, OutOfStock, PreOrder, NewCondition, UsedCondition, RefurbishedCondition. You can use either the full URL form (https://schema.org/InStock) or the shorthand (InStock). A common mistake is writing "instock" (wrong casing) or bare words like "in stock" without the namespace. Google silently drops values it cannot match to the enumeration.
Minimal valid version
The smallest markup that still produces a valid Offer entity. Use it as the floor. Reach for the advanced example above when you want search engines and AI agents to understand more about your content.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Offer",
"price": 39.95,
"priceCurrency": "CAD",
"availability": "https://schema.org/InStock"
}
</script>Google rich results this unlocks
Offer is a structural type. It does not produce a rich result on its own.
Its value comes from combining it with a primary type whose markup earns a rich result (Article, Product, Event, and so on). Offer becomes the trunk that the primary type branches off viamainEntityorbreadcrumb. Include it on every page as the backbone of your markup.
Common Offer mistakes
Mistakes that pass validation but silently fail to earn rich results or mislead consumers walking the graph. Avoid these and your markup will be ahead of most sites in the wild.
- 01
Price as a quoted string instead of a number
Wrong"price": "39.95"Right"price": 39.95schema.org defines price as a Number. A quoted string passes JSON validation but is semantically wrong. Google is forgiving about this, but some processors reject it. Always use an unquoted numeric value.
- 02
Currency as a word instead of ISO 4217 code
Wrong"priceCurrency": "dollars"Right"priceCurrency": "CAD"priceCurrency must be a 3-letter ISO 4217 code. Common codes: USD, EUR, GBP, CAD, AUD, SEK, JPY. Writing the currency name or symbol ($, €) instead of the code causes Google to drop the price from the rich result entirely.
- 03
Availability with wrong casing
Wrong"availability": "instock"Right"availability": "https://schema.org/InStock"Availability values are schema.org enums and must use PascalCase: InStock, OutOfStock, PreOrder, BackOrder, Discontinued. The full URL form (https://schema.org/InStock) or the shorthand (InStock) both work. Lowercase versions like "instock" or "in stock" are not recognized.
- 04
Missing shippingDetails and hasMerchantReturnPolicy
Wrong{ "@type": "Offer", "price": 39.95, "priceCurrency": "CAD", "availability": "https://schema.org/InStock" }Right{ "@type": "Offer", "price": 39.95, "priceCurrency": "CAD", "availability": "https://schema.org/InStock", "shippingDetails": { "@type": "OfferShippingDetails", "..." }, "hasMerchantReturnPolicy": { "@type": "MerchantReturnPolicy", "..." } }Since 2023, Google requires shippingDetails and hasMerchantReturnPolicy for Merchant Listing eligibility. Without them, your Product falls back to the weaker Product Snippet rich result. The shipping block needs a rate, destination country, and delivery time. The return policy needs a return window, method, and fee structure.
Schema properties in this example
About the example data
This example is a standalone Offer for the XooTee Classic shirt at Xoo Code Shop Dunmore. It includes every property Google checks for the Product and Merchant Listing rich results: price and currency, availability and item condition, a valid-through date, a seller cross-reference via @id, a full OfferShippingDetails block with rate, destination, and delivery time, and a MerchantReturnPolicy block with return window, method, and fee structure.
Comments
Loading comments...