Quick Answer: Product schema for ecommerce is JSON-LD markup that describes each product's name, image, description, sku, brand, offer, and ratings so Google can show price, availability, and stars directly in search results. Pages selling the product qualify for merchant listings; pages only describing it qualify for product snippets.
Here is the part most guides get backwards: the hard work of product schema is not writing the JSON. The syntax takes twenty minutes. The hard work is satisfying Google's eligibility rules, because a technically valid block that violates one of them earns nothing, silently, forever. This page gives you a complete worked example you can adapt, then walks through the eligibility layer where product markup actually succeeds or fails. This is Vector 6 in our methodology, Structure: markup a machine can trust without reading between the lines.
What the markup does that a product page alone cannot
Product schema converts the facts a shopper reads on your page into fields a crawler can extract without interpretation. Google's own Product structured data documentation lists the payoff plainly: price, availability, ratings, shipping cost, and return windows displayed in the result itself, plus eligibility for the Shopping tab, Popular Products, and product results in Google Images.
That display advantage compounds in a way plain blue links do not. A result showing a 4.7 rating, an in-stock badge, and a price answers three purchase questions before the click. Your competitor's unmarked result answers none. Click-through moves accordingly, and in a category where every store carries similar inventory, the result that resolves doubt first tends to take the sale.
There is a second audience now. AI shopping surfaces, from Google's AI Overviews to assistant-driven product recommendations, assemble answers from sources they can parse with confidence. Structured product data is the lowest-friction way to be one of those sources. We treat product markup as dual-purpose: rich results today, machine legibility for whatever recommendation surface arrives next.
Merchant listing vs product snippet: one type, two doors
Google splits Product markup into two experiences, and choosing wrong wastes the effort. The dividing question is simple: can a shopper buy the product on this page?
- Merchant listing. For pages where the visitor can purchase directly. This is the door for actual stores. It unlocks the richer surfaces: Shopping tab presence, Popular Products, product knowledge panels, image-result annotations. It also demands more: an
offersblock with price is required, and Google recommends shipping details, return policy, and apparel sizing where relevant. Per Google's merchant listing documentation, pages that merely link out to other sellers do not qualify. - Product snippet. For pages about a product the site does not sell: editorial reviews, comparison articles, roundups. It supports pros and cons markup that merchant listings do not, and it can satisfy the requirement with a review or rating alone, no offer needed.
An online store wants merchant listings on every product page. A blog reviewing gear wants product snippets. A store that also publishes buying guides wants both, on different templates. Mixing them up, say by putting offer-free snippet markup on a purchasable page, forfeits the stronger treatment.
The properties that decide eligibility
Strip away the optional fields and the skeleton is short. For a merchant listing, Google requires name and an offers block containing price (or a price specification) and expects priceCurrency. For a product snippet, you need name plus at least one of review, aggregateRating, or offers. Everything else is recommended, but "recommended" undersells it: the recommended fields are what separate a minimal listing from one that wins the richer placements.
The fields worth treating as mandatory in practice:
- image, as an array of crawlable URLs, ideally in multiple aspect ratios. Listings without images are weak candidates for visual surfaces.
- description, written for the product, not pasted from the manufacturer feed that fifty other stores also pasted.
- sku and, where you have them, gtin or mpn. Identifiers let Google reconcile your listing with its product graph, which is how you appear alongside competing sellers in product panels.
- brand, as a nested Brand object, not a bare string.
- availability, using the schema.org URL values such as
https://schema.org/InStock, kept current. Stale availability is a trust signal in the wrong direction. - aggregateRating, once you genuinely have reviews. Rules below.
A complete worked example you can adapt
The block below describes a queen duvet cover sold by Maple & Loom, an invented Ontario linen shop that exists only for this example. Swap the values for your own and it is deployable. It is valid JSON-LD as written.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Harbourline Linen Duvet Cover, Queen, Sage",
"image": [
"https://www.mapleandloom.example/img/harbourline-duvet-1x1.jpg",
"https://www.mapleandloom.example/img/harbourline-duvet-4x3.jpg",
"https://www.mapleandloom.example/img/harbourline-duvet-16x9.jpg"
],
"description": "Stonewashed 100% European flax linen duvet cover in queen size, with interior corner ties and a hidden button closure. Pre-washed for softness; colour is garment-dyed sage.",
"sku": "ML-DUV-Q-SAGE",
"brand": {
"@type": "Brand",
"name": "Maple & Loom"
},
"offers": {
"@type": "Offer",
"url": "https://www.mapleandloom.example/products/harbourline-linen-duvet-cover",
"priceCurrency": "CAD",
"price": 249.00,
"priceValidUntil": "2026-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.7,
"reviewCount": 38
}
}
</script>
Three details in that block deserve attention because they are where real implementations drift. The image array carries three aspect ratios, which Google's documentation asks for on merchant listings. The priceCurrency is explicit; a bare price with no currency is ambiguous to a parser and Canadian stores get mispriced as USD without it. And availability uses the full schema.org URL form, not the shorthand string, which some validators tolerate and some surfaces do not.
If you are new to placing JSON-LD on a page at all, our walkthrough on how to add schema markup covers the mechanics for every platform. The example above drops into the same <script type="application/ld+json"> pattern described there.
aggregateRating and the review rules that trip stores up
Review markup carries the strictest policy layer in the product ecosystem, mostly because it was the most abused. The rule set that matters, drawn from Google's review snippet documentation and its 2019 self-serving reviews change:
- Products are the exception to the self-serving ban. Google stopped showing stars for LocalBusiness and Organization markup when the reviews live on the entity's own site. Product ratings on the store that sells the product remain eligible. Rate the duvet cover, not the shop.
- Marked-up ratings must be visible on the page. If the JSON-LD says 4.7 from 38 reviews, a human on that page must be able to find that rating and those reviews. Invisible ratings are a manual-action risk, not a shortcut.
- The numbers must be real and unfiltered. An aggregateRating computed after deleting the one-star reviews is fabricated data wearing a schema costume. Beyond the policy risk, engines cross-reference; a 5.0 on your page against a 3.8 on Google Shopping reads as exactly what it is.
- No ratings yet means no aggregateRating yet. Ship the block without it and add it when the first genuine reviews land. An empty or invented rating is worse than none.
The full policy detail, including how review markup behaves outside ecommerce, is in our companion piece on review schema markup.
"The pattern I keep finding in ecommerce audits is a store with three schema apps installed and all three emitting a Product block, each slightly different. Google sees a page that states three prices for one item and quietly trusts none of them. Removing two apps has fixed more merchant listings for us than adding markup ever has."
Matt Griffin, Founder, Formative DigitalShopify: what the theme emits and where it stops
Most Shopify themes, including current Online Store 2.0 themes, emit a baseline Product block automatically: name, price, availability, URL. That baseline is why Shopify stores often show partial rich results with zero effort. It is also why store owners assume the job is done when it is roughly a third done.
The recurring Shopify gaps: the brand field mapped to the vendor value, which is frequently the store's own name rather than the product's brand; a single image instead of the multi-ratio array; sku omitted or mapped inconsistently across variants; and review data missing entirely unless a review app injects it. When a review app does inject it, you get the duplicate-block problem, two Product objects on one page disagreeing about the same item.
The clean fix is one source of truth: audit what the theme outputs with the Rich Results Test, then either extend the theme's JSON-LD in the layout or suppress it and ship one complete block from a single app or snippet. Shopify's own Liquid variables expose sku, barcode, and vendor per variant, so a developer can build the full example above natively without an app subscription.
WooCommerce: more control, more ways to misfire
WooCommerce outputs Product schema through its core plus whatever SEO plugin is active, and the flexibility cuts both ways. Yoast, Rank Math, and Woo's native output can each claim the job; sites running two of them at once ship the same duplicate-block conflict Shopify apps cause. Pick one emitter and disable the rest.
Watch the price field on variable products. Some configurations emit the lowest variant price while the visible page shows a range, and a mismatch between markup price and displayed price is a documented eligibility failure. For variable products the safer pattern is AggregateOffer with lowPrice and highPrice, or per-variant markup where the platform supports it. Also confirm the currency: multicurrency plugins have a habit of hard-coding the store default into the JSON-LD while the shopper sees a converted figure.
Common disqualifiers: why valid markup earns nothing
These are the failures we see most in the wild, all of them invisible to a syntax validator:
- Markup on category and search pages. Product structured data belongs on pages about one specific product. A category page listing forty products with forty Product blocks is explicitly out of scope and can drag trust down site-wide.
- Markup that disagrees with the page. Price changed in the store but not the schema, or availability flipped to out of stock while the JSON-LD still says InStock. Engines compare; disagreement forfeits the enhancement.
- One block describing many variants. "Available in 12 colours" is a fine sentence and a broken Product object. Each markup block should describe a specific, purchasable thing.
- JSON-LD injected after load by a tag manager or app, which some crawls execute and some do not. Server-rendered markup is the only version you can rely on. Our own stack is static HTML for exactly this class of reason.
- Duplicate emitters, the multi-app problem described above.
- Fabricated or filtered ratings, which risk manual actions rather than mere ineligibility.
Retail is where we have pressure-tested this discipline most heavily. Our engagement with Mattress Miracle, a Brantford retail client, paired structured data coverage with a large content program and grew the domain to 82,400 monthly organic visits by the SEMrush April 2026 snapshot. Structured data was one instrument in that result, not the whole orchestra, and results of that size depend on industry, competition, and the site's starting condition. But the schema layer is what let the product and content pages be read by machines at full fidelity, and none of it would have counted with the disqualifiers above in play. The full write-up is in the Mattress Miracle case study.
Validating, monitoring, and what good looks like
Two tools, used in sequence. The Rich Results Test checks a single URL and tells you which experience the page is eligible for, merchant listing or product snippet, and which recommended fields are absent. Search Console's Merchant listings report then watches the whole catalogue over time, surfacing errors per URL as they appear. New products, theme updates, and app changes all introduce regressions; the report is where you catch them before they compound.
A healthy catalogue reads like this in practice: every product URL eligible for merchant listings, zero errors, warnings limited to fields you genuinely cannot supply, and the schema regenerated server-side from the same database that renders the visible page so drift is structurally impossible. That last clause is the design principle worth stealing whatever your platform.
Where product markup fits in the wider schema graph
Product blocks do not float alone. The stores that read most coherently to machines connect them into a graph: Organization markup identifying the merchant, BreadcrumbList markup mapping the catalogue hierarchy, and, for stores with physical locations, LocalBusiness markup tying the web catalogue to the storefront entity. A shop in Hamilton selling online and in person needs both halves; our local business schema guide covers the storefront side of that pairing.
In Matt's experience with Ontario retailers, the graph question is where do-it-yourself implementations plateau: individual blocks validate, but nothing links them, so the machine sees fragments instead of a business. If you would rather hand the whole layer to a team that builds these graphs daily, that is our schema markup service, and our research library documents the methods behind it in the open.
Find out what machines see when they read your catalogue
Send us your store URL and we will map which product pages qualify for merchant listings, which are silently disqualified, and why, at no charge, with a reply inside one business day. The findings are yours to act on with any team you choose.
Product schema questions store owners actually ask
Do I need product schema if my Shopify theme already outputs some?
You need to check what it outputs, because most themes cover name, price, and availability and stop there. Brand, sku, full image arrays, and aggregateRating are usually missing. Run one product URL through the Rich Results Test, note the gaps, and fill them with a single corrected JSON-LD block rather than stacking multiple schema apps.
What is the difference between a merchant listing and a product snippet?
A merchant listing applies to pages where a shopper can buy the product directly, and it can surface in the Shopping tab, Popular Products, and image results. A product snippet applies to pages about a product you do not sell, such as reviews or comparisons, and shows stars, price, and availability in ordinary results. Same Product type, different eligibility.
Can I mark up ratings collected by my own review widget?
For products, yes. Google's self-serving review restriction applies to LocalBusiness and Organization types, where a business publishes ratings about itself. Ratings of individual products on the store that sells them remain eligible, provided the reviews are genuine, visible on the page, and not filtered to hide negative scores.
Why do my products show no rich results even though the schema validates?
Validation checks syntax, not eligibility. The usual culprits are markup on category pages instead of individual product pages, prices in the JSON-LD that disagree with the visible page, variant markup describing a range of products in one block, or a site quality level where Google declines the enhancement. Check Search Console's Merchant listings report for the specific complaint.
Does product schema matter for AI search tools like ChatGPT and Perplexity?
Yes, and increasingly so. Assistants that recommend products need machine-readable price, availability, and rating data to compare options with confidence, and structured data is the cleanest source of it. A product page an AI engine can parse without guessing is more likely to be named when a shopper asks for recommendations.
Sources
- Google Search Central (accessed July 2026): "Intro to Product Structured Data on Google."
- Google Search Central (accessed July 2026): "How To Add Merchant Listing Structured Data."
- Google Search Central (accessed July 2026): "Review Snippet (Review, AggregateRating) Structured Data."
- Google Search Central Blog (September 2019): "Making Review Rich Results more helpful" (self-serving reviews policy).
- Shopify (2026): "Ecommerce Schema: Your Structured Data Guide for 2026."
Questions about a specific catalogue, platform, or a Merchant listings report full of errors you cannot decode? Talk to us and bring the URL.