// blog / woocommerce

How I fix the error saying either offers, review or aggregateRating should be specified

The Search Console error Either "offers", "review", or "aggregateRating" should be specified means Google found Product markup carrying none of the three. The honest fix is almost always offers: price, currency and availability, which your product page already shows. I add review or rating markup only when real customer reviews are visible on that page.

By Muhammad Younus Updated 10 min read WooCommerce

WooCommerce and store SEO: illustration for "Fixing Product snippet errors, no fake reviews"
// 01 - the error

What does Either "offers", "review", or "aggregateRating" should be specified actually ask for?

It asks for one of three things, and it only needs one. Google's product snippet documentation says Product markup needs a name plus at least one of offers, review or aggregateRating. When Search Console flags a product with this error, it's found a Product with a name and nothing it can show beside it. That's a markup problem, the kind I fix through my schema markup services for WordPress, and it's most of what structured data work on a store comes down to.

The error sits in the Product snippets report as a critical issue, so the item it names is invalid. Google's help draws the line plainly: a valid item has no critical issues and can appear as a rich result, and an invalid item can't. Non-critical issues sit in a separate table and don't block anything.

There are two product reports, and they don't ask for the same things. Product snippets covers product pages broadly, including review and aggregator sites. Merchant listings covers pages where a shopper can buy the product, and it's stricter.

What each Search Console product report needs, from Google's own documentation
ReportRequired on the ProductRequired inside the offerReviews and ratings
Product snippetsname, plus one of offers, review or aggregateRatingpriceOptional, and they must follow the review snippet rules
Merchant listingsname, image and offersprice above zero, and priceCurrencyRecommended, never required

Read the two rows together and the answer's already there. Offers is required by one report and accepted by the other, so on a simple product it's the property that clears both.

// 02 - the honest fix

Why is offers the honest fix?

Because it's the only one of the three that every shop already has. A product page that sells something shows a price, a currency and whether it's in stock. Marking that up doesn't claim anything new. It repeats, in a format Google reads, what a shopper can already see.

Review and aggregateRating describe what customers said, and a store without reviews has nothing true to put there. So the fast fix and the honest fix are the same fix: a complete offer.

A minimal offer for a simple product looks like this in JSON-LD: "offers": { "@type": "Offer", "price": "49.99", "priceCurrency": "CAD", "availability": "https://schema.org/InStock" }. I make the price match the one on the page, with the same currency the checkout uses, because markup that disagrees with the page is exactly what structured data rules are there to catch.

With a price range on a variable product, WooCommerce prints an AggregateOffer. Product snippets accept it, but Google says not to use AggregateOffer for product variants, and merchant listings need an Offer, so the fix is an Offer per variation or ProductGroup markup with hasVariant. At one price, it prints a single Offer. Neither needs an invented figure; my WooCommerce SEO audit checklist covers the rest.

// 03 - the cause

Why does a WooCommerce store throw this error at all?

WooCommerce's own code is the clue. Core adds offers only when a product's price isn't empty. It adds aggregateRating and review only when ratings are switched on and the product has some. And when all three would be empty, it prints no Product markup at all. So core WooCommerce alone doesn't produce this error, and it's usually one of these four causes.

  1. i.

    A second Product block

    An SEO plugin, the theme, a page builder widget or a snippet someone pasted in prints its own Product markup beside WooCommerce's. If that block has only a name, it's the one Search Console flags, and the page carries two Products that disagree.

  2. ii.

    A product with no price

    Quote-only and call-for-price products often leave the price field empty. WooCommerce then leaves offers out, as its code says it will, and anything else that marks the page as a Product trips the error.

  3. iii.

    Product markup on the wrong page

    A category page, a blog post or a landing page with a Product type on it, usually from a builder template, has no single price to give. Google's product rich results are meant for pages that focus on one product or its variants.

  4. iv.

    Prices hidden by a customisation

    Catalogue-mode setups that hide prices from logged-out visitors, or a filter that edits WooCommerce's structured data, can strip offers out without anyone noticing. Staff who are logged in see a normal page, and Googlebot doesn't.

Rank Math and Yoast each answer this error in their own docs. Rank Math builds Product schema from WooCommerce data, and when the error comes from product category pages, its knowledge base points to Titles & Meta, Product categories, Remove Snippet Data. Yoast's 2019 answer is its paid Yoast WooCommerce SEO add-on, which ties WooCommerce's product markup into Yoast's schema graph. Neither setting can give a product a price it doesn't have.

Off WordPress, the same logic holds. Shopify's structured_data Liquid filter outputs a Product, or a ProductGroup when there are variants, with offers in its documented example, so there I look for an app or theme snippet printing a second block. Squarespace generates Product markup itself and says it can't be edited or removed, so the fix lives in the product's own details.

Rather have me do this? One person, whole job.

Book a call on Upwork
// 04 - the method

How I fix either offers, review or aggregateRating should be specified on WooCommerce

I keep to this sequence. Nothing gets edited until I know which block of markup the error comes from, because removing the wrong one can turn a warning into an error.

  1. Step 01

    Export the affected URLs

    In the Product snippets report I open the error and export the example URLs, then sort them by template: simple products, variable products and categories. A pattern shows up quickly, because markup comes from templates. A WooCommerce store with 1,512 URLs in 13 sitemaps can't be fixed page by page, but a template fix reaches every product at once.

  2. Step 02

    Read the rendered markup, not the settings

    I run a few of those URLs through the Rich Results Test and the Schema Markup Validator, the pair WooCommerce's own code comments name, and read the JSON-LD in the page source. What counts is the markup the page serves, not what a settings screen promises.

  3. Step 03

    Count the Product blocks

    If a page carries two Product nodes, I find out which plugin or template prints each one. The incomplete one goes, or gets merged into the other, so the page ends up with one Product and one complete offer.

  4. Step 04

    Give it a real price, or drop the Product type

    A product that's for sale gets its real price in the product data. A page that has no price, like a quote-only item, isn't a merchant listing, so unless it has real reviews to mark up I remove the Product type there rather than invent a number.

  5. Step 05

    Check variable products on their own

    Variations are where offers go missing most often. I test one variable product with a single price and one with a price range, because WooCommerce prints the two differently.

  6. Step 06

    Test on staging, then on the live site

    Where there's a staging copy I test the change there first. Then I clear the cache and retest the same URLs live, since a cached page keeps serving the old markup.

  7. Step 07

    Validate the fix in Search Console

    Once every instance is fixed, I press Validate fix on the issue. Search Console's help says it rechecks only the URLs it had listed with that issue, not the whole site, and that validation typically takes up to about two weeks, sometimes much longer. So I keep an eye on the report instead of calling it done on day one.

// watch out

Don't clear the error by pasting in a rating block with a made-up score. It'll pass a syntax test today, and it breaks Google's review guidelines the day it goes live.

// 05 - warnings

Which merchant listings warnings can I leave alone?

Most of them, for now. In the merchant listings documentation, review and aggregateRating are recommended, not required, and so are shippingDetails, hasMerchantReturnPolicy, brand and gtin. An item missing a required property isn't eligible for rich results, while recommended ones only make the result richer, so a missing recommended property lands in the non-critical table.

That's why a store can see a long list of warnings, including the missing field review one, with nothing broken. I read each warning as a question: does the store have this fact? If it does, I mark it up. If not, the warning stays.

Common missing field warnings on a store, and what I do with each
Missing propertyWhat it describesWhat I do
priceValidUntilThe date the price stops applyingCore WooCommerce prints it, as the end of next year or the sale's end date, so a warning points at a second Product block. Google says a past date can stop the listing showing
skuThe store's own product codeCore WooCommerce prints the SKU, or the product ID when the field's empty, so I fill in the real SKU under Product data, Inventory
reviewA customer review of the productLeave it until real reviews are on the page
aggregateRatingThe average score across those reviewsSame: leave it until real ratings exist
shippingDetailsShipping cost and delivery timeAdd it once the store has fixed shipping rules to describe
hasMerchantReturnPolicyThe store's return termsAdd it once there's a written return policy to match
gtin or brandProduct identifiersAdd the real ones if the store holds them, never made-up codes
// 06 - the line

Why won't I add review markup without real reviews?

Because Google's rules say no, and they're specific. Its general structured data guidelines name fake reviews as misleading content you shouldn't mark up. The review snippet guidelines say marked-up reviews have to be readily available to users from the marked-up page, with no fake or undisclosed incentivised reviews, and not aggregated from other websites, so stars copied from a marketplace or a Google Business Profile don't qualify either. For a Review on a Product, the author has to be a Person or Organization with a valid name.

The cost isn't only the fake stars. Google says a structured data manual action means the page loses eligibility to appear as a rich result, though it doesn't change how the page ranks in web search. The honest price markup sits on the same page, so a made-up rating can take the product snippet down with it until the action's lifted.

A hard-coded rating in a theme, or a schema plugin's demo defaults, is the same mistake in quieter form, and I take it out.

When a store has real reviews, WooCommerce handles the honest version itself: with ratings on and at least one rating, core prints aggregateRating from that page's reviews. I check it matches what a shopper sees. The wider product page work, titles, categories and internal links, is part of the WooCommerce work I do on product and category pages.

// when to hand this over

If you'd like one person to trace your product markup to its source and fix it without inventing a single star, that's the structured data work I do, remotely, over Zoom, Meet or async notes. Here's how I scope a job.

Book a call on Upwork

Is this your site? Send me the URL.

Book a call on Upwork
// questions - woocommerce

What else do people ask about this?

Can I add aggregateRating just to make the error go away?

Only if the product has real customer ratings visible on that page. Google's review guidelines rule out fake or undisclosed incentivised reviews, and a made-up score risks a manual action that leaves the page with no rich result at all.

Do I have to fix the missing field review warning?

No. It's a non-critical issue in the merchant listings report, so the item stays valid and can still appear as a rich result. Review markup is recommended there, not required, so I leave it until real reviews exist.

Why does the error only show on some of my products?

Because markup comes from templates and product data. Products with an empty price, variable products set up differently, or pages built on a separate template usually explain the split, so I sort the affected URLs by type first.

Should a category page carry Product markup?

Usually not. Google's product rich results support pages that focus on one product or its variants, so a Product block on a category page is often where this error starts.

// sources - checked

Where do these rules come from?

Platform and Google documentation, opened and read on the day this was written. Everything else is how I work.

  1. Google Search Central: product snippet structured data
  2. Google Search Central: merchant listing structured data
  3. Google Search Central: review snippet structured data and guidelines
  4. Google Search Central: general structured data guidelines and manual actions
  5. Search Console Help: rich result status reports
  6. Search Console Help: Page indexing report (validation flow)
  7. WooCommerce source on GitHub: class-wc-structured-data.php
  8. Rank Math knowledge base: Google Search Console missing field warnings
  9. Yoast: Search Console showing errors in your product structured data
  10. Shopify developer docs: the structured_data Liquid filter
  11. Squarespace Help Center: how Squarespace optimizes your site for search
  12. Schema Markup Validator
Muhammad Younus, WordPress technical SEO consultant
// who wrote this

One consultant, writing down his own method

I'm Muhammad Younus, a WordPress technical SEO consultant with 8+ years of experience and 100+ client sites fixed. Top Rated Plus on Upwork with a 100% Job Success Score. Every post here is the way I actually do the job, written in the first person because it's one person doing it, remotely, with no team behind the name.

Nothing in these posts is a client I can't name or a number I can't show. Where a figure comes from a client's Search Console, it's from a published case study, and where a rule comes from Google or a platform, the source is linked at the bottom of the post.

// the service behind this post
Muhammad Younus with his arms folded and a relaxed, confident smile
// next step

Want this done on your own site?

Book a call on Upwork, send the URL and read-only Search Console access, and you'll get a written scope for the search side before any work starts. One person does the whole job, remotely.

Book a call on Upwork