Product schema: the complete markup for a product page, with price, stock, shipping and returns
Published 7 October 202610 min readBy the SmoothSeen editorial team
Product schema is the markup that hands Google and other systems the data on a product page so they do not have to infer it: name, brand, price, currency, availability, ratings, shipping and returns. Google only requires a name, an image and an offer with price and currency, but markup that contradicts the page works against you: mark up less, and mark it up right.
Key points
- For merchant listings, Google only requires name, image and an offer with a price above zero and its currency; everything else is recommended.
- Returns and shipping policies that apply to the whole shop are declared once, in your Organization markup; a product page only repeats them when they differ.
- If you provide shipping or returns settings in Merchant Center or Search Console, Google gives them precedence over the markup on your pages.
- Marked-up ratings must be visible on the page and come directly from users; Google forbids aggregating ratings from other websites.
- Variants are grouped with ProductGroup, and each one needs a distinct URL that preselects it.
To check it on your own site: Online shops
On this page
- What is Product schema and what is it for?
- Which fields are required and which are recommended?
- A commented JSON-LD example
- How do you mark up product variants?
- How do you mark up shipping and returns?
- Ratings: only real ones
- How do you validate the markup?
- Markup does not replace the text
- Frequently asked questions
- What to do next
This guide goes deep on the markup; the rest of the work on a shop (product pages, categories, filters, speed and AI assistants) is in the guide to e-commerce SEO for AI search. A declaration of interest: this blog belongs to SmoothSeen, a web audit tool that measures visibility in search engines and AI assistants.
What is Product schema and what is it for?
Product schema is a block of structured data, usually JSON-LD, that uses the schema.org vocabulary to declare which product a page sells. Schema.org defines Product as any offered product or service1, and the sales offer sits inside it, in an Offer. What structured data is in general, and which other types Google uses, is covered in the guide to structured data.
Google uses this markup for two kinds of result2:
- Product snippets, for pages where people cannot buy the product directly, such as a review.
- Merchant listings, for pages where customers can buy the product from you. They can show price, availability, shipping and returns.
If you run a shop, the second one is yours. Google is explicit: only pages where a shopper can buy the product are eligible for merchant listings, not pages that link to another site that sells it3. It adds that search result enhancements are shown at the discretion of each experience2: correct markup makes you eligible, it guarantees nothing.
Which fields are required and which are recommended?
This table summarises Google's documentation for merchant listings3:
- Field
- Name
- Property
name- Where it goes
Product- Google says
- Required
- Field
- Image
- Property
image- Where it goes
Product- Google says
- Required
- Field
- Offer
- Property
offers- Where it goes
Product- Google says
- Required
- Field
- Price
- Property
price- Where it goes
Offer- Google says
- Required, greater than zero
- Field
- Currency
- Property
priceCurrency- Where it goes
Offer- Google says
- Required
- Field
- Availability
- Property
availability- Where it goes
Offer- Google says
- Recommended
- Field
- Condition
- Property
itemCondition- Where it goes
Offer- Google says
- Recommended
- Field
- Shipping
- Property
shippingDetails- Where it goes
Offer- Google says
- Recommended
- Field
- Returns
- Property
hasMerchantReturnPolicy- Where it goes
Offer- Google says
- Recommended
- Field
- Brand
- Property
brand.name- Where it goes
Product- Google says
- Recommended
- Field
- Identifiers
- Property
gtin,mpn,sku- Where it goes
Product- Google says
- Recommended
- Field
- Description
- Property
description- Where it goes
Product- Google says
- Recommended
- Field
- Ratings
- Property
aggregateRating,review- Where it goes
Product- Google says
- Recommended
Three details that prevent mistakes. The price must be greater than zero: unlike product snippets, merchant listings do not accept a price of 03. For barcodes, Google recommends the most specific GTIN property that applies (gtin8, gtin12, gtin13, gtin14) over the generic gtin3. And Google may try to verify product data before showing it3, so what you mark up has to be what shoppers see.
A commented JSON-LD example
This example is for a fictional shop: example.com is a domain reserved for examples, and the product, price and ratings are made up.
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Example Moka stovetop espresso maker, 6 cups",
"image": [
"https://www.example.com/img/moka-6-front.jpg",
"https://www.example.com/img/moka-6-open.jpg"
],
"description": "Aluminium stovetop espresso maker for 6 cups, suitable for gas and ceramic hobs; not suitable for induction.",
"sku": "MOKA-6-AL",
"gtin13": "0000000000000",
"brand": { "@type": "Brand", "name": "Example Kitchen" },
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.4,
"reviewCount": 27
},
"offers": {
"@type": "Offer",
"url": "https://www.example.com/espresso-makers/moka-6",
"price": "29.99",
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": 3.95, "currency": "GBP" },
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "GB" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" }
}
}
}
}What to look at in each part:
priceuses a full stop as the decimal separator and no currency symbol, andpriceCurrencyis an ISO 4217 code:GBP. The page can show "£29.99"; the markup cannot.availabilityanditemConditionuse schema.org URLs (https://schema.org/InStock), not free text such as "in stock".gtin13carries the product's real barcode number. The one in the example is a placeholder: if your product has no GTIN, leave the property out rather than invent one.deliveryTimesplits two periods: the warehouse handling time (handlingTime) and the carrier's transit time (transitTime), each with its minimum, maximum and the unitDAY3.- Ratings are the ones shown on the page: the same average and the same number of reviews.
One last practical point: generate the markup from your platform, using catalogue data, not by hand. Hand-written JSON goes stale with the first price change, and markup that says one thing while the page says another is exactly what to avoid. Put it in the initial HTML, too: Google warns that Product markup generated with JavaScript can make Shopping crawls less frequent and less reliable, a problem for data that changes as fast as price and stock4.
How do you mark up product variants?
Sizes, colours or materials of the same product are grouped with the ProductGroup type. The only property Google lists as required is the name, but its guidelines say the group must have a unique ID, usually productGroupID (the parent SKU), and each variant its own, with sku or gtin4. Google also recommends stating what the variants differ by with variesBy and linking them with hasVariant4. Each variant is a full Product.
variesBy only accepts six values, each written as its schema.org URL4:
https://schema.org/colorhttps://schema.org/sizehttps://schema.org/suggestedAgehttps://schema.org/suggestedGenderhttps://schema.org/materialhttps://schema.org/pattern
Google supports two designs4. If every variant lives on one page, that page has a single canonical URL for the whole group, normally the one with no variant preselected. If each variant has its own page, each page carries full, self-contained markup, with the whole ProductGroup repeated. In both designs the variants can be nested in hasVariant or kept separate, pointing back to their group with isVariantOf.
One requirement often fails: the site must be able to preselect each variant with a distinct URL, for example with a parameter (?colour=blue)4. Preselecting means showing that variant's image, price and availability and letting the shopper add it to the basket. If the colour only changes with a JavaScript click and the URL stays the same, Google has nowhere to send someone searching for the blue one.
How do you mark up shipping and returns?
The cleanest way is to declare them once for the whole shop, in your Organization markup, and repeat them on a product only when that product has different terms. Google recommends this for both3: the returns policy with hasMerchantReturnPolicy and the shipping policy with hasShippingService, both under Organization.
Returns: MerchantReturnPolicy
For a returns policy, Google requires the country it applies to (applicableCountry, a two-letter ISO 3166-1 code such as GB) and the type of policy (returnPolicyCategory)5. If the return window is limited, add the number of days (merchantReturnDays). The minimal alternative is to link to the policy page with merchantReturnLink.
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Example Kitchen",
"url": "https://www.example.com/",
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "GB",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn"
}
}The possible values, according to Google5:
- Property
returnPolicyCategory- Values
MerchantReturnFiniteReturnWindow(limited window),MerchantReturnUnlimitedWindow(no time limit),MerchantReturnNotPermitted(no returns)
- Property
returnMethod- Values
ReturnByMail(by post),ReturnInStore(in store),ReturnAtKiosk(at a kiosk)
- Property
returnFees- Values
FreeReturn(free),ReturnFeesCustomerResponsibility(the customer arranges and pays for return shipping),ReturnShippingFees(the shop charges a return shipping fee, declared withreturnShippingFeesAmount)
Shipping: shippingDetails or ShippingService
On a product page, shipping goes in shippingDetails, as in the example above. For the whole shop, Google documents hasShippingService under Organization, with a ShippingService that groups conditions (shippingConditions): cost and delivery times by destination, order value, weight or number of items6.
Which source wins when data lives in several places
Google applies an order of precedence, strongest first, and it is the same for shipping and returns65:
- Settings sent through the Content API for Shopping.
- Settings in Merchant Center or Search Console.
- Markup on the product page (
shippingDetails,hasMerchantReturnPolicyon the offer). - Markup on
Organization.
The upshot: if you already have shipping and returns set up in Merchant Center, Google will use those. For shipping, Google says it outright: if you provide the policy both in your markup and in Search Console, it will only use the Search Console settings6. Markup is still useful if you do not use those tools, but every source should say the same thing.
Ratings: only real ones
The aggregateRating block is the one that can bring stars to a result, and also the one most often marked up badly. Google requires the average rating (ratingValue) and at least the number of ratings (ratingCount) or reviews (reviewCount)7. If your scale does not run from 1 to 5, declare bestRating and worstRating as well.
Google's guidelines that matter most to a shop7:
- Marked-up reviews must be readily available to users on the marked-up page.
- Do not aggregate reviews or ratings from other websites. Reviews of your shop on a marketplace or a review platform do not belong in your product markup.
- Ratings must come directly from users, with no fake or undisclosed incentivised reviews.
- Each rating is about one specific item, not a category or a list of items.
A few real, visible reviews are worth more than a rounded average nobody can check. If a product has no reviews yet, leave aggregateRating out: it is not required.
How do you validate the markup?
With three free Google tools, in this order:
- Rich Results Test. Google asks you to validate the code with it and fix any critical errors3. It tells you whether the page is eligible for merchant listings and which properties are missing.
- URL Inspection in Search Console. It shows how Google sees the live page. Google reminds you that the page must not be blocked by robots.txt, a
noindextag or a login3. - The Merchant listings report in Search Console, under Shopping. It shows whether Google has found valid items of that markup on your site8, and is worth checking after every template change.
Run them on the template, not on a single product: a fault in the product template is on every product page, and fixing it once fixes them all. How fast that same template loads is a separate matter, with its own metrics, covered in the guide to Core Web Vitals for e-commerce.
Markup does not replace the text
Markup repeats what the page says; it does not stand in for it. For its AI features, Google asks that structured data matches the visible text and that important content is available in textual form9. Price, delivery time and returns policy have to be written on the product page, not only in the JSON. How to write those facts so an assistant can quote them is covered in the guide on how to get cited by AI.
SmoothSeen checks, on every product page it analyses, whether the product markup declares price, availability, brand and description, whether it includes shipping, returns, ratings and specifications, and whether the page has an original description and an FAQ. It does not connect to Merchant Center or Search Console: it reads the live page, as a search engine does.
Frequently asked questions
Which fields are required in Product schema?
For merchant listings, Google requires the name, the image and the offer (offers) on the Product, and on the offer a price above zero and its currency. Everything else is recommended: availability, condition, shipping, returns, brand, identifiers such as the GTIN, description and ratings. Recommended does not mean optional in practice: these are the facts that decide whether a result can show more than a price.
Can I mark up ratings from another website?
No. Google's review snippet guidelines say explicitly not to aggregate reviews or ratings from other websites, that ratings must come directly from users and that marked-up reviews must be available on the page. If your reviews live on an external platform, link to it; in the product markup, only include the reviews published on that page.
How do I mark up a returns policy?
If it is the same across the shop, declare it once with hasMerchantReturnPolicy in your Organization markup: country, policy type and, for a limited window, the number of days. You only need it on a product's offer when that product has different terms. If you have already set returns up in Merchant Center or Search Console, Google gives those settings precedence over the markup.
Does Product schema get my products into ChatGPT?
OpenAI says ChatGPT considers structured metadata from first-party and third-party providers, such as price and product description10, but it does not say it reads the markup on your page. What is documented is that Google asks for structured data that matches the visible text for its AI features. Complete, consistent markup is the groundwork for both.
What to do next
Run one product page from each template through the Rich Results Test and compare the result with the field table in this guide. If shipping or returns are missing, start with the Organization markup, which you only do once. For the rest of the shop, go back to the guide to e-commerce SEO for AI search.
Sources
- 1Product, Schema.org, version 30.1, 16 September 2026.
- 2Introduction to Product structured data, Google Search Central, updated 10 December 2025.
- 3Merchant listing (Product, Offer) structured data, Google Search Central, updated 8 September 2026.
- 4Product variant (ProductGroup, Product) structured data, Google Search Central, updated 8 September 2026.
- 5Merchant return policy (MerchantReturnPolicy) structured data, Google Search Central, updated 8 September 2026.
- 6Merchant shipping policy (ShippingService) structured data, Google Search Central, updated 8 September 2026.
- 7Review snippet (Review, AggregateRating) structured data, Google Search Central, updated 8 September 2026.
- 8Shopping reports and tools, Search Console Help, accessed 7 October 2026.
- 9AI features and your website, Google Search Central, updated 10 December 2025.
- 10Shopping with ChatGPT Search, OpenAI Help Center, accessed 7 October 2026.
How to cite this article
SmoothSeen. (2026, October 7). Product schema: the complete markup for a product page, with price, stock, shipping and returns. https://smoothseen.com/en/blog/product-schema/
Keep reading
E-commerce SEO for AI search: product and category pages that Google and ChatGPT understand
How to rank an online shop in Google and get products into ChatGPT: product pages, categories, Product schema, filters, speed, reviews and Merchant Center.
Core Web Vitals for e-commerce: what breaks LCP, INP and CLS on product and category pages
What breaks LCP, INP and CLS on an online shop's product and category pages, why you measure by template and which fixes to make first, with code.
How to track ChatGPT and AI traffic in GA4, and AI Overviews in Search Console
How to see ChatGPT, Gemini and Perplexity visits in GA4, what the AI Assistant channel is, and what Search Console shows for AI Overviews and AI Mode.