One Product block with an Offer inside it is the core
Every product page needs a single Product entry, and inside it an Offer carrying the commercial details. That structure is the thing that lets a search engine or an assistant understand that this page sells a specific item at a specific price.
The fields that matter in practice: the product name as a shopper would recognise it, at least one image, a description, the brand, and an identifier such as a manufacturer part number or a global trade item number where one exists. Then, inside the Offer, the price, the currency, the availability, and the URL of the page itself.
The single most important rule is that all of it has to match what a visitor sees. A price in the markup that differs from the price on the page is the most common cause of a rich result disappearing, and it is also treated as a mismatch by shopping surfaces. The markup describes the page. It is not a place to state what you wish the page said.
Use the JSON format in a script tag rather than attributes scattered through the markup. It is easier to validate, easier to keep in step with the page, and far easier to debug when something is wrong.
Identifiers, condition and the fields that make the entry complete
Beyond the core, a small set of fields decide how completely your product can be understood and how it can appear.
Identifiers are the most valuable addition. A product with a recognised identifier can be matched to the same product elsewhere, which affects both how it is displayed and whether shopping surfaces can associate reviews and specifications with it. Include the brand and the manufacturer part number, and the trade item number where the product has one. For products you make yourself and which have no such number, say so consistently rather than inventing one.
Condition is worth stating explicitly for anything that is not new. Refurbished, used and open box items are treated differently, and leaving it unstated means the default assumption applies.
Where your setup supports it, delivery and returns information can be included in the Offer. This is genuinely useful, because it is the information shoppers most often go looking for, and stating it in the markup means it can be presented alongside the listing rather than found on a separate page.
For products with variants, decide deliberately whether the page represents one item or a group, and mark it up accordingly rather than describing one variant while the page sells several.
Ratings and reviews: only where they are real and visible
Include rating markup only when genuine customer reviews are collected and displayed on that page. This is the area with the strictest rules and the one where stores get into trouble.
The conditions are consistent. The rating must come from real reviews of that product. It must be visible to a visitor on the page, not held in a database and expressed only in the markup. It must not be a rating you wrote about yourself. And the count in the markup must match the count shown.
An aggregate rating needs both the value and the number of reviews behind it. A rating claiming a perfect score from one review is technically valid and does very little for you.
Where a review platform injects markup of its own, check you have not ended up with two rating entries on the same page, one from the platform and one from your theme. Duplicate or conflicting entries can cause the whole block to be ignored.
And if you have no reviews yet, leave the field out entirely rather than marking up a placeholder. An empty or invented rating is the fastest way to get structured data ignored across the whole site, which costs you far more than the rating was worth.
Breadcrumbs, organisation and the rest of the site
Product markup does not stand alone. Two other pieces make the whole store easier to understand.
Breadcrumb markup on product and collection pages describes where the product sits in your catalogue. It can change how the URL is presented in results, and more usefully it makes the structure of your site explicit rather than something that has to be inferred from links.
Organisation markup, placed once at site level, states who you are: the legal name, the logo, the site URL, contact routes and the social profiles that belong to you. This is what connects your product pages to a recognised entity rather than leaving them as pages from an unknown site. For a store trying to be recommended by an assistant, that connection matters.
Search action markup for your site search is a small addition worth having.
What to be careful with is question and answer markup. It has legitimate uses, and it has been widely abused by stores adding invented questions to every page. If you use it, use it for questions customers actually ask, displayed on the page, and do not add it to templates where the questions are identical across hundreds of products.
The mistakes that make valid markup useless
Most structured data problems are not syntax errors. They are correct markup describing something other than the page.
The frequent ones. Two Product blocks on the same page, usually because a theme and a plugin both output one. A price that is stale because the markup is generated from a cached value. Availability that says in stock on a page that says sold out. A currency that does not change when the storefront switches market. A URL in the Offer that points at a different page from the one being viewed.
Then there is markup for content that is not on the page. Ratings without reviews, offers on a page that is not a product, and descriptions taken from a different product entirely.
Check it with a validator, and then check it again by comparing the output against the visible page for several products, including one that is out of stock and one that is on sale. Those two edge cases catch most problems.
And re-check after any theme update, app installation or template change. Structured data breaks silently, and the first sign is usually a rich result quietly disappearing weeks after whatever caused it.
Worked example, not a result
Fields on one product page
- Product name
- Matches the visible page title
- Image
- Main product image URL
- Brand and part number
- Both present
- Trade item number
- Present where the product has one
- Offer price and currency
- Matches the displayed price
- Availability
- Matches the buy button state
- Aggregate rating
- Only where reviews are shown
- Breadcrumb
- Home, category, product
Worked example, not a result