Product Schema Markup: What Google Actually Reads
Product schema markup is structured data, usually JSON-LD built from schema.org's Product and Offer types, that tells Google what a page sells: the product's name, image, price, availability, identifiers and reviews. Google reads it for two kinds of search results, product snippets and merchant listings, and each has its own required properties (Google Search Central).
Everything else in this guide follows from that split. Once you know which experience a page qualifies for, you know which fields matter.
Key takeaways
- Google reads product schema markup for two kinds of results, product snippets and merchant listings, and each has its own required properties, per Google Search Central.
- Google's merchant listings require a name, an image and an offer with a price above zero and a currency, per Google Search Central.
- For products with sizes or colors, Google asks for the ProductGroup class with
variesBy,hasVariantandproductGroupID, plus Product markup for each variant, per Google Search Central. - A structured data manual action removes a page's eligibility for rich results but does not affect how it ranks in Google web search, per Google Search Central.
Product snippets vs merchant listings
Google describes product snippets as being "for product pages where people can't directly purchase the product," and merchant listings as being for "pages where customers can purchase products from you" (Google Search Central).
The requirements differ. Product snippets need a name and "either review or aggregateRating or offers," and only "editorial product review pages are eligible for the pros and cons appearance" (Google Search Central). Merchant listings need a name, an image and an offers object with a price and currency, and "unlike product snippets, merchant listing experiences require a price greater than zero" (Google Search Central).
| Product snippets | Merchant listings | |
|---|---|---|
| Typical page | Review sites, editorial roundups, product pages with no checkout | Store product pages with a cart |
| Required | name, plus review, aggregateRating or offers | name, image, offers with price and currency |
| Price | Offer is optional | Price must be greater than zero |
| Extras | Pros and cons, on editorial review pages only | Shipping, returns, sizing and other shopping details |
Google states that "only pages where a shopper can purchase a product are eligible for merchant listing experiences," and that these experiences include "the shopping knowledge panel, Google Images, popular product results, and product snippets" (Google Search Central). For a store, merchant listings are the target.
The format Google prefers
Google supports JSON-LD, Microdata and RDFa, and says it "recommends using JSON-LD for structured data if your site's setup allows it" (Google Search Central). JSON-LD sits in its own script block, separate from your visible HTML, which makes it easier to generate from product data and to audit.
Here is an illustrative example for a single product with no variants. The store, product, identifiers and price are invented:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Washed Linen Shirt, Regular Fit",
"image": [
"https://example.com/images/linen-shirt-square.jpg",
"https://example.com/images/linen-shirt-wide.jpg"
],
"description": "A regular-fit shirt in washed linen with a button-down collar.",
"sku": "LS-REG-NAVY-M",
"brand": { "@type": "Brand", "name": "Example Clothing" },
"offers": {
"@type": "Offer",
"url": "https://example.com/products/washed-linen-shirt",
"price": "68.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
}
It goes inside a <script type="application/ld+json"> element on the product page. The schema.org definitions for Product and Offer list every available property; Google's product documentation names the ones it reads for these results.
Required first, then recommended
For merchant listings, the required set is short: name, image, and an Offer with price (or priceSpecification.price) and priceCurrency "in three-letter ISO 4217 format" (Google Search Central). Google's general rule is "You must include all the required properties for an object to be eligible," and it advises you to "supply fewer but complete and accurate recommended properties" rather than many sloppy ones (Google Search Central).
These recommended properties, all listed in Google's merchant listing documentation, are the ones worth prioritizing for a store:
| Property | Goes on | What it tells Google |
|---|---|---|
gtin (or another GTIN property) | Product | The exact product, across sellers |
brand.name | Product | The manufacturer or label |
sku, mpn | Product | Your identifier and the manufacturer's |
color, size, material, pattern | Product | Shopping attributes for apparel and similar goods |
aggregateRating, review | Product | Ratings and reviews, if they meet the review guidelines |
availability | Offer | In stock, out of stock, preorder |
itemCondition | Offer | New, used or refurbished |
shippingDetails | Offer | Shipping cost and delivery time |
hasMerchantReturnPolicy | Offer | Return window and conditions |
priceValidUntil | Offer | When a sale price ends |
Be careful with priceValidUntil. Google warns that "your listing may not display if the priceValidUntil property indicates a past date" (Google Search Central). If you set it for a sale, update or remove it when the sale ends.
Shipping and returns belong at the store level
Google recommends defining return and shipping policies once, under your Organization markup, and using offer-level versions only to override them or when there is no standard policy (Google Search Central).
If you also use Google Merchant Center, the two sources meet: "Some experiences combine data from structured data and Google Merchant Center feeds if both are available" (Google Search Central). For shipping and returns, Google's order of precedence puts product-level feeds submitted in Merchant Center first (Google Search Central). Keep the feed and the markup consistent so one doesn't contradict the other.
Variants: ProductGroup, not a pile of Products
When a product comes in sizes or colors, Google asks you to "use the ProductGroup class with associated properties variesBy, hasVariant, and productGroupID," with Product markup for each variant (Google Search Central). On schema.org, ProductGroup is a subtype of Product that "represents a group of Products that vary only in certain well-described ways" (schema.org).
Google's variant documentation sets a few rules. "Each variant must have a unique ID in its corresponding structured data markup," such as a sku or gtin. variesBy should reference full schema.org URLs, and the supported values are color, size, suggestedAge, suggestedGender, material and pattern (Google Search Central).
URLs matter as much as markup. "The site must have the ability to preselect each variant directly with a distinct URL (using URL query parameters)," and preselecting includes "showing the right image, price, and availability." When all variants share one page, "there must be only one distinct canonical URL for the overall ProductGroup," usually the base URL with no variant selected (Google Search Central).
An illustrative, trimmed example with one variant shown (values invented):
{
"@context": "https://schema.org",
"@type": "ProductGroup",
"name": "Washed Linen Shirt",
"productGroupID": "LS-REG",
"variesBy": ["https://schema.org/size", "https://schema.org/color"],
"hasVariant": [
{
"@type": "Product",
"sku": "LS-REG-NAVY-M",
"name": "Washed Linen Shirt, Navy, M",
"size": "M",
"color": "Navy",
"image": "https://example.com/images/linen-shirt-navy.jpg",
"offers": {
"@type": "Offer",
"url": "https://example.com/products/washed-linen-shirt?color=navy&size=m",
"price": "68.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
}
]
}
On Shopify, themes "automatically include schema markup for products" (Shopify Help Center), and Shopify's structured_data Liquid filter outputs a schema.org Product for products with no variants and a ProductGroup for products that have them (Shopify developer docs). Check what your theme already outputs before adding an app that writes a second block.
Reviews and ratings
aggregateRating and review come with their own rules. Google's review snippet guidelines say "ratings must be sourced directly from users," that the review content you mark up must be "readily available to users from the marked-up page," and "Don't aggregate reviews or ratings from other websites" (Google Search Central).
The same guidelines restrict self-serving reviews on pages that use LocalBusiness or other Organization markup, where the business controls the reviews about itself. That rule names those types, not Product (Google Search Central).
What gets your markup ignored
Markup has to match the page. Google's policies say "your structured data must be a true representation of the page content" and "don't mark up content that is not visible to readers of the page" (Google Search Central). Mismatches that turn up on stores include a price in the markup that differs from the displayed price, InStock on a sold-out item, and ratings in JSON-LD with no reviews on the page.
The penalty is to rich results, not rankings. Per the same policies, a structured data manual action "means that a page loses eligibility for appearance as a rich result," and "it doesn't affect how the page ranks in Google web search." Valid markup is no promise either: "Google does not guarantee that your structured data will show up in search results" (Google Search Central).
How to test
Google recommends checking structured data "using the Rich Results Test during development" and using the rich result status reports in Search Console after deployment (Google Search Central). Product pages have two reports: Merchant listings, "for pages where shoppers can buy products," and Product snippets, for other product pages such as reviews and aggregator sites (Google Search Central).
The Rich Results Test catches syntax errors and missing required fields. It won't catch everything; Google notes that some problems are "not a syntax issue, and so the Rich Results Test won't be able to identify these issues" (Google Search Central).
That is why the check against the visible page matters.
If you would rather not hand-write JSON, the free schema markup generator builds Product JSON-LD you can paste into a page and then verify in the Rich Results Test.
Markup describes the page; it doesn't replace it
Structured data tells Google what a page offers. It doesn't make the page worth choosing. Shoppers, and the AI assistants some of them now ask for recommendations, still read the visible description. We cover what that copy needs in why Shopify product descriptions are invisible to AI.
Related reading
Schema Markup Types Worth Adding in 2026, and the Ones to Skip
Which schema markup types are worth adding in 2026: Organization, Article, Product, LocalBusiness and Breadcrumb first, plus FAQ, HowTo and retired types.
Read more →Your Shopify Product Descriptions Are Invisible to AI: Here's What to Fix
Many Shopify stores have product descriptions that AI can't use. Thin content, no structure, nothing quotable. Here's how to rewrite them so ChatGPT, Gemini and Claude have something to recommend.
Read more →The Complete Guide to Answer Engine Optimization (AEO)
Learn how to optimize your content for AI search engines like ChatGPT, Perplexity, and Google AI Overviews. 18 AEO signals, structured data, and practical implementation.
Read more →Ready to optimize your search rankings?
XeoRank connects to Google Search Console, analyzes content gaps with AI, and gives you actionable fixes — from the terminal or dashboard.