When an AI shopping assistant or Google's merchant crawler looks at a product page, it rarely "sees" the page. It reads the structured data: the Product JSON-LD block with price, availability, identifiers, shipping and returns. Whatever is not in that block may as well not exist for a machine.
On 4 November 2026 I checked one product page each from 21 well-known Shopify brands. 14 came back with a readable page; the rest are covered at the end.
Disclosure: I built the checker used here, the Product Schema Checker on Apify. How to run it on your own pages is at the end.
How the pages were picked and checked
- Brands: Shopify DTC stores from the US, Canada and Germany (fashion, cosmetics, food, furniture, accessories). For each, I took the first product from the store's public
/products.jsonfeed, so the sample is not cherry-picked. - Each page was fetched once as plain HTML, without a browser, the way most crawlers and agents do it.
- All structured data was extracted (JSON-LD, microdata, RDFa, Open Graph) and the
Productwas scored against what Google's merchant listings and AI shopping agents use: name, image, price, currency, availability, brand, identifiers (GTIN/SKU/MPN), rating, reviews, item condition, shipping details and return policy.
The good news: the basics are always there
All 14 pages had a Product in JSON-LD with:
- name, image, price, currency and availability: 14 of 14
- brand: 14 of 14
- none of Google's required fields missing, so all 14 are technically eligible for merchant listings
That is Shopify's theme layer doing its job. Any store on a modern theme gets these for free.
The gap: everything an agent needs to decide
The median score was 75 of 100. The points were lost on the same fields again and again:
| Field | Pages that have it |
|---|---|
shippingDetails (shipping cost and time) |
2 of 14 |
hasMerchantReturnPolicy |
3 of 14 |
aggregateRating (star rating) |
4 of 14 |
gtin (barcode) |
4 of 14 |
review (individual reviews) |
0 of 14 |
itemCondition |
5 of 14 |
Only Outdoor Voices (94) and Taylor Stitch (92) declared both shipping and returns in their markup. Everyone else leaves an assistant to guess the two questions shoppers ask most: "what does delivery cost?" and "can I send it back?"
Three observations from the details:
1. Ratings may be on the page, but not in the data. In the plain HTML, only 4 of 14 expose aggregateRating, and none has individual reviews. Most review widgets load with JavaScript after the page renders, so if a store shows stars that way, a crawler that does not run scripts never sees them. Most review apps can write a JSON-LD rating into the theme. It is usually one setting.
2. GTINs are rare and not always real. Only 4 pages had a gtin field. One of them contained 15U2UGGFXG60, which is not a valid GTIN at all (GTINs are 8, 12, 13 or 14 digits with a check digit). It looks like an internal SKU in the wrong field. Google matches products across shops by GTIN, so a wrong value can hurt more than a missing one.
3. "Out of stock" is often the theme's default. 4 of the 14 pages declared OutOfStock, although the product was listed in the store's live feed. One possible cause on Shopify: the markup describes only one variant (for example a sold-out size). An agent then reads the whole product as unavailable.
The 7 pages I could not read
-
6 returned HTTP 429 (too many requests) on the first request from a cloud server, including Gymshark, ColourPop, Everlane, Fenty Beauty and Death Wish Coffee. (Their
/products.jsonfeed had answered minutes earlier.) - 1 (Brooklinen) returned a bot challenge page instead of the product.
So a third of the sample turned away a polite, single request from a data center. That is a defensible security choice. But it is worth knowing that some AI assistants fetch pages from similar infrastructure, and a shop that rate-limits them by default may be invisible to them.
Fixes, in order of effort
-
Return policy and shipping: add
hasMerchantReturnPolicyandshippingDetailsto the product JSON-LD. Google also lets you set them once at the organization level. Both are static for most shops: write them once and you are done. -
Ratings: switch on the JSON-LD output of your review app, so
aggregateRatingis in the HTML and not only in the widget. - GTINs: fill the barcode field per variant in Shopify with real EAN/UPC codes, and check them. A check-digit validator catches values like the one above in seconds.
-
Availability: make sure the JSON-LD describes all variants (
ProductGroupor multipleOffers), not just the first.
How to run this on your own store
curl -X POST "https://api.apify.com/v2/acts/fast_data_asap~product-schema-checker/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"startUrls": ["https://your-store.com/products/your-product"]}'
You get one flat row per URL: all schema types found, the product fields, missingRequired, missingRecommended, a score and grade, and concrete fix hints. It costs $0.002 per product page found; pages without product markup, blocked pages and errors are free. The 21 pages here took a few seconds.
For barcodes, the EAN/GTIN Lookup validates check digits and looks up open product data for $0.0002 per code.
Data: one product page each from 21 Shopify stores, plain HTTP, 4 November 2026. A different product or a crawl from another network can give different results.
Top comments (0)