Write your product page for two audiences: the person who decides and the robot that extracts.
The first paragraph stands on its own, the facts (price, stock, size, material, reviews) appear in plain text in the served HTML, and a single Product markup repeats exactly the same values.
On Shopify, that "single" is the hardest part to hold: each fact should appear twice, in the text and in the markup, with the same value, and we sometimes find it three times, with two values.
The benchmark
An e-commerce manager asked me whether markup, the structured data a page declares to robots, had anything to do with her page titles. I answered:
"The robot that comes to read your site doesn't care about design, brand positioning, or marketing. What it actually does is manage to read, or not, whether the product is in stock, the price, the rating, the features, the SKU."
Yet when Adobe measured, in April 2026, what machines can read on US retail sites, product pages scored 66 out of 100, against 75 for home pages. That means a third of their content is unreadable to a robot.
The most likely cause is the HTML. According to Vercel's measurement from December 2024, the ChatGPT, Claude, and Perplexity robots fetch the document without running JavaScript.
Google does run it, but warns that dynamically generated markup can make its Shopping crawls "less frequent and less reliable." So none of them reliably reads what an app adds afterward in the browser.
As of July 10, 2026, according to Profound's data, the merchant feed drives nearly two-thirds of recommendations in ChatGPT's Shopping mode.
That feed comes from your catalog, and the remaining third is still read from web pages, yours included.
The rule
Every fact exists twice, with the same value: in plain text on screen, then in the markup. The example below is fictional.
| Fact | On screen | In the markup |
|---|---|---|
| Price | €119 incl. VAT | price 119.00, priceCurrency EUR, priceValidUntil on sale |
| Availability | "In stock, ships tomorrow" next to the button | availability InStock (PreOrder for preorder), synced with stock |
| Material | "100% washed linen, 190 g/m²" in the first two lines | material, identical value |
| Reviews | Rating and number of reviews at the top of the page | aggregateRating equal to the published reviews |
| Shipping and returns | "Shipping €4.90, free returns within 30 days" | shippingDetails, hasMerchantReturnPolicy for France |
This rule follows Google's guidelines, which prohibit marking up invisible content and require structured data to represent the page faithfully.
Don't expect a citation from it, though, since Google also writes that this data is "not a requirement for generative AI search." In our view, markup mainly makes your facts verifiable, because a robot finds in it the price it just read in the text.
The steps
- The first paragraph. It says what the product is, who it's for, what material it's made of, and how it fits, using the category word your customers use.
- The served HTML. View the page's source code (the browser inspector shows the page after JavaScript runs), then search it for the price, the stock, and the rating.
- The markup in place. In that same source code, search for
"@type"and count theProductandProductGroupentities. Shopify's Dawn theme already produces one with thestructured_datafilter, and a review or SEO app may add its own. - The single entity. Keep only one, written from
productandproduct.selected_or_first_available_variantso the marked-up amount follows the one on screen, and attach the rating to it. - The properties. Google requires
name,image, andofferswithpriceandpriceCurrency, and recommends the ones in the table. - The validation. Run the page through the rich results test, then track the merchant listings report in Search Console.
The trap
The duplicate doesn't show on screen. In a recent audit of a clothing brand the authors work with, reading the source code showed that the page "exposes two product entities: a Shopify ProductGroup without reviews and a Product [from the review app] with aggregateRating."
At an accessories brand, the theme and an SEO app each declared their own Product, so a search engine can pick the wrong version of the same fact.
We share some of the blame: in March, our audit guide still listed "Enable the JSON-LD option in the review app" among the quick wins.
In September, we recommended turning it off and merging everything into the theme. In our recent recommendations, the fix is estimated at between one hour, to remove an extra markup, and six hours, to rewrite the JSON-LD by hand.
The finding to present
Take your five bestsellers and repeat steps 2 and 3 on each, noting every gap between the markup and the screen.
For your leadership, then copy this sentence and rewrite it with your own findings (the example is fictional):
"On our five bestsellers, the page declares two products instead of one, and the rating is attached only to the second. The fix is estimated at six hours of development, and I propose doing it before the next sales campaign."