"Either 'offers', 'review', or 'aggregateRating' should be specified": completing your Product markup
Product markup qualifies for a product snippet only when it has a name and at least one of offers, review or aggregateRating. This error means all three are absent. Add offers with a price if you sell the item, or a genuine review or aggregateRating if you do not, and the error clears.
Search Console lists it in the Product snippets report under Shopping in the sidebar, and the Rich Results Test shows the same message for a single URL. It is an error, not a warning, so the affected pages get no product rich result at all.
What it looks like
Before
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Stoneware mug, 350 ml",
"image": "https://example.com/img/mug.jpg",
"description": "Hand-glazed stoneware mug."
}
After
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Stoneware mug, 350 ml",
"image": "https://example.com/img/mug.jpg",
"description": "Hand-glazed stoneware mug.",
"offers": {
"@type": "Offer",
"price": "18.00",
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock",
"url": "https://example.com/shop/stoneware-mug/"
}
}
Which of the three should you add?
You sell the product on this page: offers. An Offer with price and priceCurrency, and ideally availability. This is the right answer for any shop product page, and it is also the basis of merchant listings.
You review the product but do not sell it: review. An editorial review page can mark up one Review with an author and a reviewRating. The review must be visible on the page.
You show customer ratings: aggregateRating. A ratingValue plus ratingCount or reviewCount, reflecting ratings that visitors can see on the page.
Do not add a property only to silence the error. A made-up rating or a placeholder price of 0 on a product that is not free is a structured data policy violation, and that can lead to a structured data manual action. If none of the three honestly applies, the page should not carry Product markup: see the last section.
Why WooCommerce products trigger it
WooCommerce generates Product JSON-LD on single product pages automatically. It typically leaves out offers when the product has no price to state, and leaves out the rating properties when there are no reviews. The combination produces this error on:
- Products with an empty regular price, such as "price on request" or catalogue-only items.
- External or affiliate products saved without a price.
- Variable products whose variations have no prices set, or are all disabled.
- Products that are drafts in all but name: published, but never completed.
Open Products, sort or filter for items with no price, and either enter a price or decide the item is not a product for search purposes. For how the product page should be set up overall, see our guide to optimizing WooCommerce product pages.
Check the markup your page sends
curl -s https://example.com/shop/stoneware-mug/ | grep -o '<script type="application/ld+json">.*</script>' | head -c 2000
Or view source and search for "@type":"Product". Paste the JSON-LD block into our JSON-LD validator, which checks syntax and flags missing required properties. Look for two things beyond the missing property:
- More than one Product object. A theme, a reviews plugin and WooCommerce can each print one. If the block with
offersand the block Google is complaining about are different objects, removing the incomplete duplicate is the fix. offerspresent but empty or malformed. A price written as"£18"or"18,00"is not a valid number. Use a plain decimal with a full stop and put the currency inpriceCurrencyas a three-letter ISO 4217 code.
Adding the properties
For hand-written markup, generate a complete block with our schema markup generator, which has a Product form, and paste it into the page in a Custom HTML block.
In Hydrogen SEO, Product is one of the available schema types. Assign it to the product post type or to an individual page from the schema settings, and fill in price, currency and availability so the output includes offers; the type and its fields are described in the schema types reference. Keep the structured price in step with the visible price. A mismatch between the two is its own validation problem.
If both your SEO plugin and WooCommerce output Product markup for the same page, choose one source so that you do not create multiple aggregate ratings or conflicting prices.
When the page is not a product page
The error also appears on pages that should never have had Product markup:
- Category and listing pages. Google's product markup guidelines are for pages about a single product. A category page marked up as one Product is wrong; an
ItemListis the nearest fit, with no product snippet expected. - Service pages and landing pages tagged as Product to try for stars or a price in results.
- Blog posts mentioning a product where a plugin added Product markup because of a shortcode or block.
Remove the Product type from these. A page without Product markup produces no error and loses nothing, since it could not have earned the snippet anyway. The Product schema reference lists the required and recommended properties if you want to check eligibility first.
Validate and wait
- Test the URL in Google's Rich Results Test. Under Product snippets the item should show as valid, possibly with optional-field warnings.
- In Search Console, open the Product snippets report, select the error and click Validate fix.
- Validation recrawls the affected pages over several days. Rich results follow recrawling and are never guaranteed, even with valid markup.
Our free SEO audit checks that a page's JSON-LD blocks are parseable and declare @context and @type. It does not check type-specific requirements such as this one, so use the validator and the Rich Results Test for those.
Common questions
Do I need all three properties?
No. One is enough to clear the error. Shops normally have offers and add aggregateRating once real reviews exist.
Can I use a price of 0?
Only if the product is free. A false price is misleading markup. If you cannot state a price, use review or aggregateRating where genuine, or remove the Product type.
The price is on the page. Why does Google say offers is missing?
Google reads the structured data, not the visible text, for this check. The price has to be in the JSON-LD as an Offer.
Is this the same as the Merchant listings report?
No. Merchant listings have stricter requirements, including price and availability inside offers. A page can be valid for product snippets and still have merchant listing issues.