An online store adds Product structured data to every listing page, runs each URL through Google’s Rich Results Test, and watches the tool hand back a clean green result. Weeks pass. The search snippets still show a plain blue link. No price, no availability, no stars. Nothing in the code is broken, and the developer has done nothing wrong. The gap is that valid markup and a visible rich result are two different things, and the page has quietly landed in the wrong lane.
Google reads the same Product markup in more than one way, depending on what a page lets a shopper do. Knowing which experience a page qualifies for, and what that experience needs, is often the difference between markup that sits idle and markup that changes how the listing looks in results.
One schema type, two search experiences #
Product structured data feeds two distinct appearances in Google Search, and Google’s documentation names them separately. A product snippet is meant for a page where a reader cannot buy the item on the spot, such as an editorial review that compares several models. A merchant listing is meant for a page where a customer can actually purchase the product from you.
The split is not cosmetic. Each experience unlocks a different kind of detail. Product snippets lean toward editorial signals, including pros and cons drawn from a review page. Merchant listings lean toward transactional detail, including price, availability, shipping estimates, and return terms. Google’s guidance puts the relationship plainly: adding the required properties for a merchant listing also makes the page eligible for a product snippet. So when a page genuinely sells something, the purchasable path is the more complete one to build toward.
This is where a lot of the confusion starts. A page marked up as if it were a shop window, but with no real way to buy, is asking Google for the wrong experience. According to Google’s documentation, merchant listing experiences require a price greater than zero, which means a “contact us for pricing” page or a bare spec sheet with no checkout is a product snippet candidate at best. Neither of these is Shopping ads, which is a separate paid program, not something plain markup buys you.
What each experience requires #
The required fields are short. The recommended fields are where most of the visible richness comes from, and skipping them is a common reason a listing looks thinner than a competitor’s in the same results.
For a merchant listing, Google’s current documentation lists three required properties on the Product object and a small set on the nested offer:
| Property | Object | Status | What it carries |
|---|---|---|---|
| name | Product | Required | The product name |
| image | Product | Required | URL of a product photo |
| offers | Product | Required | A nested Offer describing the sale |
| price | Offer | Required | The active price, which must be greater than zero |
| priceCurrency | Offer | Required | Currency in three-letter ISO 4217 form |
| availability | Offer | Recommended | Stock state, such as InStock or OutOfStock |
| shippingDetails | Offer | Recommended | Shipping rates and destinations |
| hasMerchantReturnPolicy | Offer | Recommended | Return terms |
| review / aggregateRating | Product | Recommended | Rating detail that can surface star ratings |
| brand | Product | Recommended | The manufacturer or brand |
A store with only the five required fields is technically valid and can be eligible. A store that also fills in availability, shipping, returns, and ratings gives Google more raw material to build a fuller result. The recommended fields are optional to validate, not optional to compete.
Why a page can pass validation and still show nothing #
Here is the part that catches people. A clean pass in the Rich Results Test confirms that the markup is well formed and eligible. It does not promise a rich result will appear. Google’s documentation is explicit that these enhancements are shown at the discretion of each experience and may change over time. Eligibility is a ticket to the drawing, not a seat.
Verification is the second reason. Google’s guidance notes that it may attempt to verify merchant listing product data before showing it in results. If the price or availability in the markup does not match what a shopper sees on the rendered page, that mismatch can hold the rich result back, and it will not always tell you why. Prices behind a script that loads after the initial HTML, a currency that disagrees with the page, or a stale “in stock” value are the usual culprits. The fix is boring but reliable: keep the structured data honest and matched to the visible page, on every template, not only the ones you spot-checked.
A common version of this plays out on a single sold-out item. A running-shoe page sells out, the visible page flips to a grey “out of stock” button, but the markup still declares InStock because the availability value is hardcoded in the template rather than pulled from inventory. The page can keep an eligible rich result that promises a purchase the shopper cannot make, or Google can drop the enhanced result once the mismatch is detected. Either outcome costs a click. Wiring availability, and price, to the same source the visible page reads from is what keeps the two in step as stock and pricing move.
Structured data, a Merchant Center feed, or both #
There is a second way to give Google product data, and the two paths are not rivals. You can mark up the page, you can send a feed through Google Merchant Center, or you can do both. Both is fine. Google states that providing both maximizes eligibility across experiences and helps it verify the data, and that some experiences combine information from structured data and a Merchant Center feed when both exist.
| Approach | Best when | Trade-off |
|---|---|---|
| Structured data only | A smaller catalog, or a team that controls the page templates directly | Relies on Google crawling and rendering each page; slower to reflect fast price or stock changes |
| Merchant Center feed only | A large catalog that already maintains a product feed | Adds an account and feed to manage, and the page itself carries no product markup for experiences that read it directly |
| Both | Most stores that want the widest eligibility and Google’s own recommendation | More to keep in sync, since the feed and the page must not contradict each other |
For a small shop with a few dozen products, on-page structured data alone often gets the job done, and it keeps the source of truth inside the pages the team already edits. For a catalog in the thousands, a feed carries prices and stock more quickly than crawl-and-render can, and pairing it with markup covers the surfaces a feed alone does not. The scale of the catalog, not a rule, decides which end you start from.
A short pre-publish check #
Before pushing product markup live across a template, a quick pass catches most of the failures above:
- Confirm the page lets a shopper buy. If it does not, target a product snippet, not a merchant listing.
- Fill the five required fields, then add availability, shipping, returns, and ratings where they are true.
- Match the markup to the rendered page, including price and stock, so verification does not stall the result.
- Test one live URL per template, not one URL for the whole site, since templates fail independently.
- Treat a green validation as eligibility, then watch Search Console over the following weeks to see what Google surfaces.
Product markup is an eligibility ticket, not a switch. The stores that get the visible result are usually the ones that picked the right experience for the page, filled the recommended fields instead of stopping at the required ones, and kept the data matched to what a shopper sees. The green checkmark is where that work starts, not where it ends.