eCommerce

Product Schema and Rich Results: How to Get Stars, Price, and Stock on Google

Lior Aharonov Lior Aharonov 16 min read

Product schema is a block of machine-readable code, usually JSON-LD, sitting invisibly on each product page and stating the product's name, image, price, currency, availability, and rating in a form Google can trust. When the markup is complete, valid, and matches what a shopper sees, Google may print those facts directly in your search listing: stars under the title, a price, and an "In stock" label. That decorated listing is a rich result, and it changes the click rather than the rank. Your page sits exactly where it sat before; it simply shows more than the plain blue links around it. Most store platforms already output a basic version of this markup, so the job is rarely to add it from scratch. The job is to make it complete, make it valid, and keep it truthful, in that order.

Google published its own evidence for what the decoration is worth. In a case study on Rotten Tomatoes, the site added structured data to 100,000 pages and measured a 25% higher click-through rate on the marked-up pages compared with the ones left plain. One domain, one crawler, two kinds of listing. The difference was that one set could show more.

The short version

  • Rich results are a click-through play, not a ranking play. Structured data does not move your position. It changes what your listing looks like at the position you already hold, and a listing with stars and a price beats a bare link for the same query.
  • Google shows a short list of fields. Price, currency, availability, rating and review count, and for stores, shipping and return details. Mark up those well before anything exotic.
  • Your platform probably outputs the basics already. WooCommerce prints product schema on every product page; most Shopify themes do too. The work is finding what is missing, duplicated, or wrong.
  • Validity is binary. One malformed field and the whole block is ignored. Google's Rich Results Test tells you exactly which field, in under a minute.
  • Eligible is not guaranteed. Clean markup makes a page eligible for rich results; Google decides per query whether to show them. Stars in particular need real reviews of that specific product.
  • Markup that drifts from the page costs you the feature. A price or stock claim that disagrees with the visible page can get rich results withdrawn for the whole site. Keep the markup wired to live data, never typed by hand.

What are rich results, and why do they lift clicks at the same rank?

A normal search listing is a title, a URL, and two lines of description. A rich result is the same listing with extra elements drawn from structured data: a row of stars with a count in parentheses, a price, an availability label, sometimes shipping cost and return window, sometimes a product image on mobile. Google could try to guess your price from the visible text, and sometimes it does, but it will not print a guess with confidence in a results page seen by millions. Structured data removes the guess.

The reason this moves clicks is that shoppers scan results looking for signals that a click will pay off. Stars answer "is it any good." Price answers "can I afford it." In stock answers "will this be a dead end." A listing that answers all three before the click has already done the first ten seconds of the product page's job. The competitor two spots above with a plain link is being read as a directory entry; your listing is being read as an answer.

There is a second effect that owners rarely count. Rich results filter clicks as well as attract them: a shopper who sees your $89 price and clicks anyway has accepted the price, and one who sees "Out of stock" and skips you saved you a bounce. The traffic is better qualified than what a plain listing sends.

Which product fields does Google actually show?

Google's Product structured data documentation describes two related experiences. Product snippets can appear for any page that discusses a product and draw on rating, price, and availability. Merchant listings are the richer treatment for pages where a shopper can buy, adding shipping, returns, and a product image. A store's product pages qualify for both.

  • Name and image. Required. The image must be the product, on a URL Google can crawl, and the markup should point at the same image the shopper sees, not a thumbnail buried in a plugin folder.
  • Price and currency. Required for merchant listings. The number must match the page, and the currency must be explicit. A dollar sign in the visible text is not a currency; USD in the priceCurrency field is.
  • Availability. A schema.org value such as InStock, OutOfStock, PreOrder, or BackOrder. This is the field behind the "In stock" label and the one most likely to drift from reality.
  • Aggregate rating and review count. The average rating, the scale it is on, and how many reviews it summarizes. Stars need all three, and the reviews behind them must be about this product, visible on this page.
  • Shipping and returns. Optional, and increasingly shown for US stores: shipping cost by region, delivery time, return window and fees. Stores that fill these in can show them in the listing; stores that do not, cannot.
  • Identifiers. GTIN, MPN, brand, and SKU. Not shown to shoppers, but they help Google match your page to the product it already knows, which improves how confidently it treats everything else.

None of those fields is difficult. The difficulty is keeping all of them present, correctly typed, and true at the moment of the crawl across thousands of pages nobody maintains by hand, which makes this a data plumbing problem more than an SEO one.

Does WooCommerce or Shopify already output product schema?

Yes, and that changes what the work is. WooCommerce generates a JSON-LD Product block on every single-product page out of the box, with name, image, SKU, offer price, currency, availability, and, when reviews exist, an aggregate rating. Popular SEO plugins replace or extend that block with brand, GTIN, and richer offer details. Most Shopify themes ship a product JSON-LD snippet, and the Google and YouTube sales channel feeds product data to Merchant Center separately.

So a store that shows nothing but a blue link is usually not missing schema. It has schema that is broken, duplicated, incomplete, or contradicted, and we see the same short list of causes on nearly every audit.

  • The theme strips or overrides it. A custom or heavily modified theme replaces the product template and drops the hook that prints the markup, or prints its own outdated version.
  • Two plugins output two blocks. The platform prints one Product, an SEO plugin prints another, a review plugin prints a third with different numbers. Google sees a page that disagrees with itself and trusts none of it.
  • Variable products expose the wrong price. A parent product with sizes from $40 to $70 is marked up as a single offer at one of those numbers, or as a range Google cannot pin down. Google's product variant markup, ProductGroup with hasVariant entries, exists for exactly this, and few themes use it yet.
  • Reviews live in a plugin the schema cannot see. The rating plugin renders stars on the page beautifully but never feeds aggregateRating into the schema block, so Google sees a product with no ratings.
  • Availability is hard-coded. Some themes print InStock on every product regardless of inventory. The label shows up, then it lies, then it goes away.

The store's performance history often explains the mess. Years of plugin stacking leave overlapping code paths on the product page, the same accumulation that makes a WooCommerce store slow, and the fix for the schema is usually the same as the fix for the speed: fewer things printing to the page, each one doing a known job.

How do you set up product schema step by step?

  1. Pick three representative product pages. A simple product, a variable product, and your best-selling one. Fixing schema on the hardest template fixes the rest.
  2. Run each URL through Google's Rich Results Test. It fetches the live page, lists every structured data item it found, and flags errors and warnings by field name. Errors block the rich result; warnings block individual features such as stars or shipping.
  3. Count the Product blocks. If the test lists more than one for a single page, find the sources and turn off all but the most complete, usually the SEO plugin's.
  4. Fill the required fields from live data. Price, currency, availability, and image must be read from the product record at render time. Anything typed into a static field will be wrong within a month.
  5. Connect ratings. Make sure the reviews shown on the page are the ones feeding aggregateRating, with ratingValue, reviewCount, and bestRating all present. If reviews are disabled, remove the empty rating rather than shipping a zero.
  6. Handle variable products deliberately. Either mark up the parent as a ProductGroup with each variant's own offer, or mark up the lowest-priced in-stock variant as the offer and make sure the visible page shows that same price first. Do not leave the parent with a price the shopper cannot actually pay.
  7. Add shipping and return details. Filling shippingDetails and hasMerchantReturnPolicy from your real policy is a one-time job per store, not per product.
  8. Retest, then request indexing in Search Console. Recrawling takes days. Watch the Merchant listings and Product snippets reports for valid items to climb and errors to fall.

That sequence is a diagnostic first and a build second, and we price it that way: a short fixed-fee review reports what the markup does today and which of the five failure causes apply. Often the outcome is a settings change or a plugin retirement the owner can do themselves, and there is nothing to build. When there is, the fix is a small custom snippet that reads the platform's own product data and prints one correct block, the pattern of a small purpose-built WooCommerce plugin rather than another marketplace download.

Before you consider the job finished, check every item on this list against a real product URL:

  • Exactly one Product item appears in the Rich Results Test for the page.
  • Zero errors, and every warning is one you have consciously accepted.
  • The price in the markup equals the price on the page, including any active sale price.
  • Availability matches stock, and changes when stock changes, verified by setting a test product to zero and refetching.
  • Stars on the page and stars in the schema agree on both the average and the count.
  • The image URL loads without a login and shows the product.
  • Variable products expose a payable price, not a placeholder or a range with no anchor.

Why do stars refuse to show up?

Stars are the feature owners want most and the one that fails most, because it has more preconditions than the others, and valid markup satisfies only the first of them.

The first precondition is real reviews of that specific product, visible on that page. Google's guidelines require that the rating you mark up be about the item on the page and that the reviews behind it be readily available to a visitor. A store that stamps its overall 4.8 Trustpilot rating into every product's aggregateRating is marking up a rating of the store, not the product, and that pattern is a documented violation, not a clever shortcut. A new product with zero reviews correctly shows no stars, and the fix is to earn reviews, which is a post-purchase email job rather than a markup job.

The second is that the count must be honest and the scale declared: a ratingValue without a bestRating on a ten-point scale gets misread as a five-point one.

The third is patience. Google renders rich results per query, weighing the page, the competing results, and its own confidence. A page can be valid on Monday and show stars in March. What you control is eligibility; what you watch is the Search Console report; what you should not do is add a second rating plugin because the first one "did not work."

How do you keep the markup truthful as prices and stock change?

Google's structured data policies require that the markup reflect the page's visible content and be kept up to date, and it enforces this two ways. Algorithmically, mismatches between marked-up price or availability and what it observes on the page reduce how often the enhancements show. Manually, a reviewer can apply a "spammy structured markup" action that removes rich results for the entire site until the problem is fixed and a reconsideration request is approved. Owners imagine that outcome comes from deliberate cheating. It far more often comes from decay: a sale ended, the visible price reverted, the schema did not.

The defense is architectural rather than procedural. Markup that is generated from the same product record the page itself renders cannot disagree with the page, because they are the same read. Markup that is maintained in a separate field, a plugin setting, or a spreadsheet import will disagree eventually. This is the same single-source discipline that keeps inventory counts truthful across sales channels: one system owns the number and everything else reads it. On Shopify, where the theme reads from the product object and custom fields live in metafields, the same rule applies: put brand, GTIN, and material in metafields the schema snippet reads, never in a description paragraph someone has to remember to update in two places.

Page caching is the one exception to that guarantee: a cached copy of the page carries yesterday's schema until it is purged, so product updates, including a stock change that flips availability, must clear the cache for that page.

Finally, replatforming and redesigns are when schema most often silently vanishes. A new theme, a migration, or a headless front end will not carry the old markup across by itself, and the loss shows up weeks later as a click-through decline nobody attributes correctly. Re-creating product structured data belongs on the launch checklist alongside redirects, as we cover in migrating to WooCommerce without losing SEO.

Common pitfalls

A case with the details changed. A US home-goods store with around 1,200 products had solid rankings, a five-year review history, and not a single star in its search listings. The owner had already bought two schema plugins on the theory that more markup would help. What the Rich Results Test showed on the first product URL was three Product items: the platform's default, an SEO plugin's version quoting the regular price instead of the active sale price, and a review plugin's block with a rating but no offer at all. Google, faced with three contradictory descriptions of one product, featured none of them. The fix took an afternoon and removed code rather than adding it: one block kept, sourced from the SEO plugin, with the review plugin configured to feed its rating into that block instead of printing its own. Stars appeared across the catalog over the following three weeks as pages were recrawled. Two years of missing stars had cost more than any plugin purchase would have, and the cause was never a missing feature.

Two more traps come up often enough to name.

The hand-typed price. A store enters prices into a schema plugin's custom fields at launch, runs a sale six months later, and the markup keeps quoting the old number. Shoppers arrive expecting it, and the mismatch eventually costs the enhancement. Any field a human types separately from the product record is a liability.

Marking up the category page. Owners sometimes add Product schema to collection pages listing thirty items, hoping for stars on the category. Google's guidelines are explicit that product markup describes a single product, and category pages marked this way tend to lose the feature rather than gain it. Category pages can carry ItemList markup pointing to the products; the stars belong on the product pages themselves.

If your products show a bare link while competitors show stars and prices at the same rank, send us three product URLs and we will tell you which of the failure modes above you are looking at, including the honest version where the fix is a checkbox and you do not need us.

FAQ

What is product schema markup?

It is a structured block of code, typically JSON-LD following the schema.org Product vocabulary, placed on a product page to declare the product's name, image, offer price, currency, availability, and rating in machine-readable form. Search engines read it to understand the page with certainty rather than by inference, and Google uses it to power the stars, price, and stock labels in rich results.

Does structured data improve search rankings?

Not directly. Google has said structured data is not a ranking factor, and the observed benefit is higher click-through at an unchanged position, which the Rotten Tomatoes case study measured at 25%. Higher engagement over time may feed back into performance, but the reliable, immediate gain is winning more of the clicks a ranking already earns.

Why does my WooCommerce store show no stars on Google?

The usual culprits, in order of frequency: the product has no reviews or reviews are disabled, so there is nothing to summarize; two or more plugins each print their own product schema and contradict each other; the theme drops the default markup; or the review plugin renders stars visually without feeding them into the aggregateRating field. Running the URL through Google's Rich Results Test identifies which one applies.

How long does it take for rich results to appear after fixing schema?

Validation is immediate in the testing tool, the Search Console report typically updates within days of a recrawl, and the visible rich result follows at Google's discretion, often within a few weeks. Requesting indexing for key pages speeds up the recrawl; nothing speeds up Google's decision to show the enhancement.

Can wrong product schema hurt my site?

Yes. Markup that misstates price, availability, or ratings relative to the visible page violates Google's structured data policies and can trigger a manual action that strips rich results from the whole domain until fixed and reviewed. The most common cause is not deception but stale data, so the safeguard is generating markup from the live product record instead of maintaining it separately.

Do I need product schema on Shopify?

Most Shopify themes include a product JSON-LD snippet already, and the Google and YouTube channel sends product data to Merchant Center in parallel, so a typical store is covered for the basics. The worthwhile checks are that the snippet exposes the selected variant's real price and availability, and that ratings from your review app flow into the markup.