DEV Community

Fast Data
Fast Data

Posted on

I checked the product markup of 14 well-known Shopify brands: all pass Google's minimum, only 2 tell machines what shipping costs

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.json feed, 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 Product was 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.json feed 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

  1. Return policy and shipping: add hasMerchantReturnPolicy and shippingDetails to 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.
  2. Ratings: switch on the JSON-LD output of your review app, so aggregateRating is in the HTML and not only in the widget.
  3. 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.
  4. Availability: make sure the JSON-LD describes all variants (ProductGroup or multiple Offers), 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"]}'
Enter fullscreen mode Exit fullscreen mode

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)