Home / Blog / Product Schema Markup: Get Stars, Price and Stock in Google

Product Schema Markup: Get Stars, Price and Stock in Google

Product schema markup is structured data, usually JSON-LD, that uses the schema.org Product type to tell Google a page’s product name, price, stock status, ratings and shipping terms. Done right, it makes the page eligible for richer Google results: star ratings, prices and availability under…

Product Schema Markup: Get Stars, Price and Stock in Google

Product schema markup is structured data, usually JSON-LD, that uses the schema.org Product type to tell Google a page’s product name, price, stock status, ratings and shipping terms. Done right, it makes the page eligible for richer Google results: star ratings, prices and availability under the blue link, plus shopping placements like product carousels.

Eligible. Not guaranteed. Google decides whether to show any of it, and the markup doesn’t push your rankings up by itself, but what it does do is remove the guesswork, so Google reads your price, stock and rating from clean data instead of trying to scrape them out of whatever your theme happens to render that week.

The catch is that Google runs two separate product experiences with two different rule sets. Pick the wrong one, or mix them up, and your markup sits there valid but useless. So before any code, let’s sort out which one you’re building for.

Which Questions Decide Your Product Schema Setup?

When I audit a store’s structured data, I answer five questions first. Every section below branches off one of them.

  1. Can a shopper buy the product on this page? Yes means merchant listings. No (reviews, comparisons, affiliate pages) means product snippets.
  2. Is there one seller and one price, or many? One seller uses Offer. A page listing several sellers’ prices can use AggregateOffer, but only for product snippets.
  3. Does the product come in sizes, colors or materials? Then you need ProductGroup and variant markup.
  4. Do you collect real customer reviews shown on the page? No reviews on the page means no rating markup. Simple rule.
  5. Which platform runs the store? Shopify and WooCommerce both print some markup already, so you may be fixing, not starting from zero.

Product Snippets vs Merchant Listings: Which One Applies to You?

Google’s intro to product structured data splits product markup into two classes. Product snippets suit pages where people can’t buy the product directly. Merchant listings suit pages where they can, and they unlock more detail like apparel sizing, shipping and returns.

QuestionProduct snippetsMerchant listings
Which pages?Editorial reviews, review aggregators, other non-store pagesPages where a shopper can buy the product
Requiredname, plus one of review, aggregateRating or offersname, image, offers with price and priceCurrency
Offer typeOffer or AggregateOfferOffer only
Price rulePrice can be any value you showPrice must be greater than zero
Pros and consEditorial reviews onlyNot eligible
Search Console reportProduct snippetsMerchant listings

The same Product block can qualify for both. Google checks each page against both rule sets, and Search Console reports them separately. My take: if you run a store, write for merchant listings. Those requirements are stricter, so meeting them usually covers product snippets too.

One line from Google’s merchant listing docs settles a common argument. Only pages where a shopper can buy the product qualify, “not pages with links to other sites that sell the product.” Affiliate sites, that means you.

The Main Path: One Product, One Price, One Page

This is the setup most stores need. A single product, sold by you, at one price, on its own URL.

If you have all the data, mark up the name, images, description, SKU, GTIN, brand, and an Offer with price, currency, availability, condition and URL. If you don’t have a GTIN, leave it out rather than inventing one; Google lists it as recommended, not required. If you have no reviews yet, skip aggregateRating entirely. An empty or zero rating helps nobody.

Here’s a product schema example for a merchant listing. It follows the property names in Google’s merchant listing documentation. The product, store and numbers are illustrative.

{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "Trailmark 40L Waterproof Hiking Backpack",
  "image": [
    "https://example.com/photos/1x1/trailmark-40l.jpg",
    "https://example.com/photos/4x3/trailmark-40l.jpg",
    "https://example.com/photos/16x9/trailmark-40l.jpg"
  ],
  "description": "A 40 litre roll-top hiking backpack with a waterproof shell, padded hip belt and side bottle pockets.",
  "sku": "TM-40L-GRN",
  "gtin13": "0012345678905",
  "brand": {
    "@type": "Brand",
    "name": "Trailmark"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": 4.6,
    "reviewCount": 38
  },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/products/trailmark-40l",
    "priceCurrency": "USD",
    "price": 129.00,
    "itemCondition": "https://schema.org/NewCondition",
    "availability": "https://schema.org/InStock",
    "shippingDetails": {
      "@type": "OfferShippingDetails",
      "shippingRate": {
        "@type": "MonetaryAmount",
        "value": 0,
        "currency": "USD"
      },
      "shippingDestination": {
        "@type": "DefinedRegion",
        "addressCountry": "US"
      },
      "deliveryTime": {
        "@type": "ShippingDeliveryTime",
        "handlingTime": {
          "@type": "QuantitativeValue",
          "minValue": 0,
          "maxValue": 1,
          "unitCode": "DAY"
        },
        "transitTime": {
          "@type": "QuantitativeValue",
          "minValue": 2,
          "maxValue": 5,
          "unitCode": "DAY"
        }
      }
    }
  }
}

Every value in that block must match what the visitor sees. If the page says $119 in a sale banner and the markup says $129, you have a mismatch, and mismatches are how merchant listings get flagged. My rule? Generate these values from the same product database that renders the page. Never type them by hand.

What Belongs in the Offer, and When Do You Use AggregateOffer?

The Offer is where most errors live. For merchant listings, Google needs price and priceCurrency, and the price has to be above zero. Currency is an ISO 4217 code like USD or GBP, not a symbol.

For availability, Google accepts ten schema.org values: InStock, OutOfStock, BackOrder, PreOrder, PreSale, SoldOut, Discontinued, LimitedAvailability, InStoreOnly and OnlineOnly. Use exactly one. Google’s merchant listing docs say plainly not to specify more than one value. Which one to pick when stock runs out is its own decision, and I cover that in my guide to out of stock products SEO.

itemCondition takes NewCondition, UsedCondition or RefurbishedCondition. If you add priceValidUntil, keep it in the future. Google warns that a listing may not display when that date is in the past, and I still find stores with a 2023 date baked into their theme.

If you’re the only seller, always use Offer. If your page compares prices from several shops, use AggregateOffer with lowPrice and priceCurrency (both required), plus highPrice and offerCount if you have them. Just remember that AggregateOffer only counts toward product snippets. It can’t earn a merchant listing, because the merchant has to be the one selling.

Should Shipping and Return Policies Go on Every Product?

Usually not. Google’s docs recommend putting your store-wide return policy under Organization markup with hasMerchantReturnPolicy, and store-wide shipping under Organization with hasShippingService. Product-level shippingDetails and hasMerchantReturnPolicy then act as overrides for the items that differ.

I showed shipping at the offer level in the example because it’s easier to read. On a real store with one flat shipping rule, I’d put it once on the Organization and keep product markup lean.

There’s a precedence order worth knowing. According to Google’s return policy documentation, settings in the Content API for Shopping win first, then Merchant Center or Search Console settings, then product-level markup, then organization-level markup last. If you’ve set returns in Search Console, Google uses that and ignores your markup. Honestly, that surprises a lot of store owners who spend hours on policy JSON-LD.

Can You Mark Up Your Own Customer Reviews?

Yes, for products. This is where I see the most confusion in store audits, mostly because people read the self-serving rule once, panic, and rip out perfectly good rating markup that was earning them stars.

Google’s review snippet guidelines have a self-serving review rule. If an entity controls the reviews about itself, its pages using LocalBusiness or Organization markup aren’t eligible for star ratings. That rule targets reviews of your business. It doesn’t stop a store from marking up genuine customer reviews of the products it sells.

The rules that do apply to product ratings:

  • Reviews must be visible. Google says it must be immediately obvious to users that the page has review content.
  • Don’t import ratings from elsewhere. Google’s guidelines say not to aggregate reviews or ratings from other websites.
  • Counts must be real. aggregateRating needs ratingValue plus ratingCount or reviewCount. The scale defaults to 1 to 5 unless you set bestRating and worstRating.
  • Pros and cons are editorial only. positiveNotes and negativeNotes work on editorial review pages, not merchant product pages or customer reviews.

What I tell clients: if your review app shows the stars on the page and prints matching markup, you’re fine. If the markup shows a rating the visitor can’t see, fix it before Google notices.

Branch 1: When Your Products Have Variants

Sizes, colors and materials change the markup. Google’s product variant documentation uses a ProductGroup as the parent and a Product for each variant.

If each variant has its own URL or URL parameter, give each variant a unique sku or gtin and its own offer URL. If you show all variants on one page, the group sits on one canonical URL and nests variants with hasVariant. Either way, Google says the site must be able to preselect each variant with a distinct URL, so a size picker that never changes the URL is a problem.

The variesBy property takes color, size, suggestedAge, suggestedGender, material and pattern. A trimmed example, again illustrative:

{
  "@context": "https://schema.org/",
  "@type": "ProductGroup",
  "name": "Trailmark Merino Hiking Socks",
  "productGroupID": "TM-SOCK",
  "brand": { "@type": "Brand", "name": "Trailmark" },
  "variesBy": ["https://schema.org/size"],
  "hasVariant": [
    {
      "@type": "Product",
      "sku": "TM-SOCK-M",
      "name": "Trailmark Merino Hiking Socks, Medium",
      "size": "M",
      "image": "https://example.com/photos/tm-sock-m.jpg",
      "offers": {
        "@type": "Offer",
        "url": "https://example.com/products/tm-sock?size=m",
        "price": 18.00,
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock"
      }
    },
    {
      "@type": "Product",
      "sku": "TM-SOCK-L",
      "name": "Trailmark Merino Hiking Socks, Large",
      "size": "L",
      "image": "https://example.com/photos/tm-sock-l.jpg",
      "offers": {
        "@type": "Offer",
        "url": "https://example.com/products/tm-sock?size=l",
        "price": 18.00,
        "priceCurrency": "USD",
        "availability": "https://schema.org/OutOfStock"
      }
    }
  ]
}

Notice the large size is out of stock while the medium isn’t. That’s the point of variant markup. One sold-out size shouldn’t mark the whole product unavailable.

Branch 2: When You Review or Compare Products

Review blogs, comparison sites and affiliate pages live in product snippet territory, because nobody can check out on them, and no amount of clever markup changes the fact that Google wants merchant listings to point at the actual seller. Stop chasing it.

If you wrote an editorial review, mark up a Product with a review by a named author, and add positiveNotes and negativeNotes if the page shows a pros and cons list. If you list prices from several shops, use AggregateOffer. If you have neither a review nor a price, the page has nothing for product markup to describe. Leave it off.

What Do Shopify and WooCommerce Output by Default?

Current Shopify themes can print product markup through the structured_data Liquid filter, which outputs a Product or, for products with variants, a ProductGroup. Ratings don’t come from Shopify itself, so your review app has to add them. I go deeper on that in is Shopify good for SEO.

WooCommerce prints JSON-LD Product markup with offers on single product pages. SEO and schema plugins often extend or replace it. I compare both platforms in Shopify vs WooCommerce SEO.

On both platforms, the biggest risk I find is duplication. The theme prints one Product block, a review app prints another, and an SEO plugin prints a third, each with slightly different prices or ratings. Messy. Pick one source and switch the others off.

How Do You Test Product Schema Markup?

I test in three places, in this order:

  1. Rich Results Test (search.google.com/test/rich-results). Paste a live URL or code. It tells you whether the page qualifies for product snippets, merchant listings or both, and lists errors and warnings.
  2. Schema Markup Validator (validator.schema.org). It checks general schema.org syntax, which is handy for catching typos the Rich Results Test ignores.
  3. Search Console, under Shopping. The Merchant listings and Product snippets reports show valid items, errors and warnings across the whole site. After a fix, use the report’s validate button so Google recrawls the affected pages.

Errors block eligibility. Warnings don’t. Most warnings I see are missing recommended fields like GTIN, shipping or return details, and filling them in is usually the cheapest way to make a listing richer without touching the page design at all.

Common Product Schema Errors and Their Fixes

These are the issues I see most in store audits:

  • Missing “offers”, “review” or “aggregateRating”. A Product with only a name qualifies for nothing. Add the offer.
  • Price of zero or “Call for price”. Merchant listings need a numeric price above zero. If you don’t show a price, don’t mark one.
  • Price or stock doesn’t match the page. Usually a cached template or a sale price only in the banner. Pull values from the live product data.
  • Expired priceValidUntil. Remove it or update it.
  • Rating with no visible reviews. Show the reviews or remove the markup.
  • Two or three Product blocks per page. Theme, app and plugin all printing markup. Keep one.
  • Variants without unique IDs. Each variant needs its own sku or gtin.

Product Schema Markup Decision Matrix

If the page…And…Then use
Sells one product at one priceNo variantsProduct + Offer, aim for merchant listings
Sells a product in sizes or colorsEach variant has a distinct URLProductGroup + variant Product items with unique SKUs
Sells productsReal reviews shown on the pageAdd aggregateRating and review
Sells productsNo reviews on the pageSkip rating markup completely
Reviews a product editoriallyShows a pros and cons listProduct + review + positiveNotes / negativeNotes
Compares prices from several shopsNo checkout on your siteProduct + AggregateOffer, product snippets only
Has one shipping and return policy site-wideMost products follow itOrganization-level policies, product overrides only where needed

When Should You Hand This to a Developer?

Hand it off when your markup has to come from the product database rather than a template, when variants use JavaScript pickers that don’t change the URL, or when several apps fight over the same markup. Those are engineering problems. Not copy problems.

If you’d rather have someone look at the whole store, product schema is one of the first things I check in our ecommerce SEO service, which we quote after a free SEO audit. Want the AI search side of structured data? Read my take on schema markup for AI search.

Frequently Asked Questions

Does Product Schema Markup Improve Rankings?

Not directly. Google uses structured data to understand the page and decide whether to show rich results, not as a ranking boost. The payoff is a more useful result: price, stock and stars in the snippet, and eligibility for shopping placements that plain pages can’t reach. Better clicks can follow, but I’d never promise a ranking jump from markup alone.

Why Aren’t My Product Stars Showing in Google?

Valid markup only makes a page eligible. Google may still choose not to show stars. Check the Rich Results Test and the Product snippets report first, then confirm the reviews are visible on the page, the counts are real and the ratings weren’t pulled from another site. If all of that is clean, it’s Google’s call.

Do I Need Merchant Center if I Already Have Product Schema?

You don’t need it, but Google recommends both. Its product structured data docs say that providing structured data and a Merchant Center feed together maximizes eligibility and helps Google verify your data. If you already run Google Shopping, connecting the two is easy.

Should I Add FAQ Schema to Product Pages?

No. Google limited FAQ rich results to government and health sites in 2023, and its FAQ documentation now says the feature stopped appearing in Google Search from May 7, 2026. Keep the questions as normal on-page content, where shoppers still read them.

Last updated: September 2026 by Mizanur Rahman

Put this guide to work.

Want help applying it? Start with a free audit of your site. We’ll show you what to fix first.

Get a free SEO audit