Offer Schema — Price, Currency, and Availability
Offer is the part of your markup that says what something costs and whether people can buy it. It always sits inside a Product, Event, Course, or software listing.
Generate an OfferWhat is Offer structured data?
An Offer describes the terms for getting something: the price, the currency, whether it is in stock, its condition, and who sells it. It is never the main thing on the page. You place it in the offers property of the item being sold:
- Product: the price and stock shown in Google's product snippets and merchant listings.
- Event: ticket price, ticket availability, and when tickets go on sale.
- Course and SoftwareApplication: what the course or app costs.
Because Google reads Offer through those parent types, there's no separate "Offer rich result." Getting Offer right is what makes the price and availability in your Product or Event markup usable.
Required and recommended properties (merchant listings)
Google's merchant listing documentation requires two things on every Offer:
price: the current price as a number, for example199.00. You can put it inpriceSpecification.priceinstead.priceCurrency: the three-letter ISO 4217 code, such asUSD,EUR, orGBP.
Google recommends adding:
availability: a schema.org value such ashttps://schema.org/InStock,OutOfStock, orPreOrder.itemCondition:NewCondition,RefurbishedCondition, orUsedCondition.priceValidUntil: the date the price stops applying, for example the last day of a sale.url: the page where people can buy the item.shippingDetails: shipping cost and delivery time, using OfferShippingDetails.hasMerchantReturnPolicy: return window and fees, using MerchantReturnPolicy.
Price rules that trip people up
- Numbers only. Write
1299.99, not"$1,299.99". The currency goes inpriceCurrency, never in the price. - Merchant listings need a price above zero. Product snippets accept a price of 0, but merchant listings don't.
- Match the page. The price, currency, and availability in your markup must be what the visitor sees. If the page shows a sale price, the markup shows the sale price.
- One currency per Offer.
priceCurrencynames the currency of that Offer's price, so a price in another currency needs its own Offer.
Showing a sale price
To show a reduced price with the original price crossed out, use priceSpecification with two entries:
- The active sale price, with no
priceType. - The original price, with
priceTypeset tohttps://schema.org/StrikethroughPrice.
Google's docs are explicit that the active price must not carry a priceType. See the "Sale price with a strikethrough price" example on this page.
Offer vs. AggregateOffer
- Use Offer when you are the one selling the item. Merchant listings require an Offer, because the merchant has to be the seller.
- Use AggregateOffer on a page that compares several sellers, with
lowPrice,highPrice,priceCurrency, and optionallyofferCount. Product snippets accept it; merchant listings don't.
Offers on events
Event ticket offers use the same type with event-specific guidance. Google recommends:
price: the lowest available ticket price, including service charges and feespriceCurrency: the three-letter currency codeavailability:InStock,SoldOut, orPreOrdervalidFrom: when tickets go on sale, if sales start on a set dateurl: the page where people buy tickets
How to build an Offer here
- 01
Pick the parent type first: Product for things you sell, Event for tickets.
- 02
Enter the price as a number and the three-letter currency code.
- 03
Set availability and, for products, item condition.
- 04
Add priceValidUntil if the price ends on a known date.
- 05
Attach shipping and return details if you sell online.
- 06
Copy the JSON-LD into the page and test it in Google’s Rich Results Test.
Common errors and fixes
- Price written as text: the price contains a currency symbol, a comma, or words. Use a plain number.
- Missing
priceCurrency: every Offer needs a currency, even when the page only uses one. - Price in the markup doesn't match the page: update both together, especially when a sale starts or ends.
- Out-of-stock items marked
InStock: keep availability in sync with your inventory. - AggregateOffer on your own product page: if you are the only seller, use Offer so the page can qualify for merchant listings.
- Offer with no parent item: an Offer on its own describes nothing. Nest it under the Product or Event it belongs to.
Required properties
price (or priceSpecification.price)priceCurrency (or priceSpecification.priceCurrency)
Recommended properties
availabilityitemConditionpriceValidUntilurlshippingDetailshasMerchantReturnPolicyseller.namevalidFrom (event tickets)
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Ultra Wireless Headphones",
"image": "https://www.example.com/images/ultra-headphones.jpg",
"offers": {
"@type": "Offer",
"url": "https://www.example.com/headphones/ultra",
"price": 199,
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"priceValidUntil": "2026-12-31",
"seller": {
"@type": "Organization",
"name": "Example Audio"
}
}
}{
"@context": "https://schema.org",
"@type": "Product",
"name": "Ultra Wireless Headphones",
"image": "https://www.example.com/images/ultra-headphones.jpg",
"offers": {
"@type": "Offer",
"url": "https://www.example.com/headphones/ultra",
"availability": "https://schema.org/InStock",
"priceSpecification": [
{
"@type": "UnitPriceSpecification",
"price": 149,
"priceCurrency": "USD"
},
{
"@type": "UnitPriceSpecification",
"priceType": "https://schema.org/StrikethroughPrice",
"price": 199,
"priceCurrency": "USD"
}
]
}
}{
"@context": "https://schema.org",
"@type": "Product",
"name": "Ultra Wireless Headphones",
"image": "https://www.example.com/images/ultra-headphones.jpg",
"offers": {
"@type": "AggregateOffer",
"lowPrice": 179,
"highPrice": 219,
"priceCurrency": "USD",
"offerCount": 4
}
}{
"@context": "https://schema.org",
"@type": "Event",
"name": "Structured Data Summit 2026",
"startDate": "2026-11-12T09:00:00-05:00",
"location": {
"@type": "Place",
"name": "Riverside Conference Center",
"address": {
"@type": "PostalAddress",
"addressLocality": "Richmond",
"addressRegion": "VA",
"addressCountry": "US"
}
},
"offers": {
"@type": "Offer",
"url": "https://www.example.com/summit/tickets",
"price": 89,
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"validFrom": "2026-08-01T09:00:00-04:00"
}
}FAQs
Is there an Offer rich result?ShowHide
No. Offer always sits inside another item, usually Product. Google uses it for the price and availability shown in product and merchant listing results, and for ticket prices on events.
Should price be a number or text?ShowHide
A number, without a currency symbol or thousands separator: 1299.99, not "$1,299.99". Put the currency in priceCurrency as a three-letter ISO 4217 code such as USD.
Can the price be 0 for a free product?ShowHide
Product snippets accept it, but Google's merchant listings require a price greater than zero.
Offer or AggregateOffer?ShowHide
Use Offer when you are the seller. Use AggregateOffer (lowPrice, highPrice, offerCount) for a page that compares several sellers. Merchant listings require an Offer because the merchant has to be the seller.
How do I show a sale price?ShowHide
Give the active sale price normally, then add a second priceSpecification with priceType https://schema.org/StrikethroughPrice for the original price. Don't put a priceType on the active price.