# Customer reviews: 1 in 4 equipped stores is silent to AI
> Measured across 457 French Shopify product pages: 24.5% of stores with a reviews app expose no rating without JavaScript. Google sees it, ChatGPT does not.
- Canonical HTML: https://verityscore.io/en/blog/customer-reviews-invisible-ai-engines/
- Markdown alternate: https://verityscore.io/en/blog/customer-reviews-invisible-ai-engines.md
- Language: en
- Content type: blog
- Published: 2026-08-13
- Updated: 2026-08-14
- Tags: customer-reviews, aggregaterating, schema-org, json-ld, javascript, shopify, judge-me, ai-overviews, chatgpt, claude
## The problem in 60 words

Google is the one engine that already sees your customer reviews, because it executes your widget's JavaScript. The engines behind ChatGPT and Claude do not. We measured 457 French Shopify product pages: among stores running a reviews app, **one in four exposes no rating at all without JavaScript**. The sample is French, the mechanism is not: it is how reviews apps ship by default.

### What we measured

On 13 August 2026, we read one product page on each of 480 French Shopify stores (clients of agencies listed in the Shopify partner directory), over plain HTTP, with no JavaScript execution. This is what a crawler that does not render pages sees.

| Measure | Result |
|---|---|
| Stores queried | 480 |
| Product pages resolved and analysed | 457 |
| Load a reviews app on the product page | 249 / 457 (54.5%) |
| **Of those 249: no review signal at all without JavaScript** | **61 (24.5%)** |
| Of those 249: rating readable in some form | 188 (75.5%) |
| Of those 249: `AggregateRating` attached to the `Product` | 27 (10.8%) |

**Method**: one product page per store, resolved through `/products.json` then the product sitemap as a fallback. Requests over plain HTTP with the user-agent `VerityScoreBot/1.0`, no JavaScript execution. We searched for the rating and review count in four forms: JSON-LD `aggregateRating`, `itemprop` microdata, widget attributes (`data-number-of-reviews`, `data-average-rating`), and visible text such as "128 reviews" or "4.6 / 5". Reviews apps were detected by their own markers: CDN domain and widget container present in the served DOM.

**Limits, and they matter.** A French sample of agency-supported stores, so probably better maintained than average.

One page per store, often a recent product that may legitimately have no reviews yet, in which case a missing rating is correct rather than broken. That is why the meaningful line is not "24.5% have no reviews" but "24.5% load a reviews app while no rating appears anywhere in the HTML".

23 of the 480 stores dropped out because no product page could be resolved: `/products.json` disabled, no product sitemap, or a non-200 response. Those are typically stores that filter bots or serve a decoupled front end, so they are likely *less* readable than average. **Excluding them makes our figures optimistic, not the reverse.**

Finally, we queried each store with an identifiable user-agent rather than impersonating an AI crawler. A store that serves different HTML per user-agent would appear here under its "unknown bot" face. We will re-run this measurement on the same corpus in February 2027.

One measured example makes the mechanism concrete. A fragrance store in the sample serves `data-number-of-reviews="13960"` and a 4.65 rating in its HTML, yet publishes no `aggregateRating` in its JSON-LD. Nearly 14,000 reviews exist, are counted server-side, and are never declared in the format engines look for.

## Why Google is not the issue

This runs against the mood of the moment. The French launch of AI Overviews put Google at the centre of every conversation, when Google is the engine that needs your help the least on this particular point.

Google documents three stages: crawling, rendering, indexing. Rendering runs through "a headless Chromium [that] renders the page and executes the JavaScript" ([Google Search Central](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics)). Your reviews widget runs, the rating appears, Google sees it. Google does add caveats: a page can sit in the render queue "a few seconds, but it can take longer than that", and the documentation still recommends server-side rendering, noting that not all bots can run JavaScript.

AI engine crawlers are exactly those bots. The joint [Vercel and MERJ](https://vercel.com/blog/the-rise-of-the-ai-crawler) analysis found no evidence of JavaScript execution by GPTBot, ClaudeBot, PerplexityBot, Bytespider or meta-externalagent. They sometimes fetch JavaScript files, between 11% and 24% of requests depending on the crawler, but never execute them. They read the HTML as it leaves your server. The finding converges with more recent independent measurements ([SearchOptimo, June 2026](https://searchoptimo.com/blog/do-ai-crawlers-render-javascript)), and Anthropic explicitly recommends not relying on JavaScript for its crawler to read a page.

Hence the asymmetry nobody is looking at:

| Engine | Executes JavaScript | Sees a widget-only rating | Evidence |
|---|---|---|---|
| Google (Search, AI Overviews, AI Mode) | Yes, headless Chromium | Yes, after deferred rendering | Documented by Google |
| ChatGPT (GPTBot) | No | No | Measured |
| Claude (ClaudeBot) | No | No | Measured |
| Perplexity (PerplexityBot) | No | No | Measured |
| ChatGPT and Claude, other agents | Not expected | Not expected | Inferred, not measured |

Three honest caveats on this table, because it carries the whole thesis.

The Vercel/MERJ measurement covers `GPTBot`, `ClaudeBot`, `PerplexityBot`, `Bytespider` and `meta-externalagent`. It does **not** cover `OAI-SearchBot`, `ChatGPT-User`, `Claude-SearchBot` or `Claude-User`, some of which did not exist when the study ran. We group them by infrastructure consistency, not on direct evidence.

On the Google side, "Yes" deserves an asterisk: rendering goes through a queue. On a product whose rating moves, Google may read a stale value rather than no value.

Finally, OpenAI's documentation describes its crawlers and their roles but says nothing about JavaScript. Anthropic, by contrast, explicitly recommends not relying on it. So the absence of execution is established by measurement on the OpenAI side, and by documentation on the Anthropic side.

## What Google actually says about AI Overviews

Precision matters here, because the market says the opposite. Google states plainly that **no particular structured data is needed** to appear in AI Overviews or AI Mode: "You don't need to create new machine readable files, AI text files, or markup to appear in these features" ([Google Search Central](https://developers.google.com/search/docs/appearance/ai-features)).

So no, publishing an `AggregateRating` will not get you into an AI Overview. Selling that would be false.

What the markup actually does, and it is more than enough to justify the work:

1. **It gates the review snippet in Google results.** To show stars, Google asks you to "mark up an aggregate evaluation of an item by many people with schema.org/AggregateRating", with at least `ratingCount` or `reviewCount`, and requires the review content to be visible to users on the page ([Google Search Central](https://developers.google.com/search/docs/appearance/structured-data/review-snippet)).
2. **It makes the rating readable by engines that do not execute JavaScript.** That is the subject of this article.

Two concrete benefits, neither of which is "appearing in AI Overviews". That distinction is what separates a verifiable recommendation from a sales pitch.

## Five levels of machine readability

Behind an identical on-screen result (stars under the product title), our measurement surfaces five situations. The counts are mutually exclusive and sum to the 249 equipped stores.

| What the served HTML contains | Stores | Share |
|---|---|---|
| 1. `AggregateRating` attached to the `Product` | 27 | 10.8% |
| 2. Structured rating, but not attached to the `Product` | 10 | 4.0% |
| 3. Proprietary widget attribute only | 130 | 52.2% |
| 4. Visible text only | 21 | 8.4% |
| 5. No trace without JavaScript | 61 | 24.5% |

**Level 1, the standard (10.8%).** The rating is attached to the `Product`, in JSON-LD or microdata. Google accepts both, plus RDFa: it states that all three formats are "equally fine", JSON-LD being merely the easiest to maintain ([Google Search Central](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data)). This is the safest form for any engine parsing the page.

**Level 2, the orphaned rating (4.0%).** An `aggregateRating` exists, but on an entity other than the product, typically the `Organization`. These stores believe they are at level 1. They are not: a company-level rating does not make a product page eligible for stars.

**Level 3, the proprietary attribute (52.2%).** The rating lives in a widget container attribute, typically `data-number-of-reviews="128"` with Judge.me. The HTML does contain it, so a crawler that does not render JavaScript can read it if it knows where to look. But nothing is normalised, and Google does not use it for review snippets. This is the most common case, and it is half a signal.

**Level 4, text only (8.4%).** No markup and no attribute, but "128 reviews" and "4.6 / 5" are written into the server-rendered HTML. That is worse than markup for Google, and paradoxically rather good for a conversational engine, which reads text.

**Level 5, silence (24.5%).** The served HTML contains an empty widget container. No rating, no count, no text. JavaScript fills everything at load time. For Google, no problem. For ChatGPT and Claude, this store has no reviews at all.

### An important caveat on level 1

JSON-LD is the best guarantee for engines that index, not a universal one. When browsing live, ChatGPT and Claude often read the visible text rather than the markup: our own per-engine extraction measurement gives 0% for Claude and 37.5% for ChatGPT when the price exists only in JSON-LD ([see the detail](/en/blog/schema-org-chatgpt-citations-myth/)).

So the safe rule is not "use JSON-LD" but **both at once**: the rating written in plain text in the server-rendered HTML, and an `AggregateRating` attached to the `Product`. Level 1 without visible text is still a bet.

<figure>
  <picture>
    <source media="(max-width: 640px)" srcset="/diagrams/avis-lisibilite-moteurs-mobile-en.svg" type="image/svg+xml" />
    <img src="/diagrams/avis-lisibilite-moteurs-en.svg" alt="Levels of review readability: AggregateRating attached to the Product read by all engines, proprietary attribute read by Google but not guaranteed elsewhere, JavaScript-only widget invisible to ChatGPT, Claude and Perplexity but visible to Google" width="800" height="420" loading="lazy" decoding="async" style="width:100%;height:auto;" />
  </picture>
  <figcaption style="text-align:center;font-size:0.875rem;color:#6B6B76;margin-top:0.5rem;">Figure 1: the same on-screen result covers several levels of machine readability. Only the first is a recognised standard.</figcaption>
</figure>

### The silence clusters on three apps

This is the most counter-intuitive result of the measurement. Fully silent stores are not spread at random: it depends on the app installed.

| App | Stores | At the standard (level 1) | Silent without JavaScript (level 5) |
|---|---|---|---|
| Judge.me | 154 | 13 (8.4%) | **0 (0%)** |
| Trustpilot | 50 | 6 (12.0%) | 26 (52.0%) |
| Loox | 31 | 5 (16.1%) | 13 (41.9%) |
| Yotpo | 24 | 5 (20.8%) | 14 (58.3%) |
| Other vendors, grouped | 33 | — | — |

**Judge.me is never silent.** Across 154 stores, none is at level 5: the app always writes its counter into an attribute of the served HTML. That is half a signal rather than the standard, but a crawler reading raw HTML always finds something. Yotpo, Trustpilot and Loox, by contrast, leave between 42% and 58% of their stores completely silent.

Two caveats. Vendors under 20 observations are grouped: at those counts a "0%" reads as noise, not as a ranking. And **Trustpilot is a special case**: it is a business review platform, not a product review app. A correctly implemented Trustpilot score rates the `Organization`, so it is not supposed to produce a product-level `AggregateRating`. Its row measures a reality, not a fault.

## The check, in three minutes

**Step 1. Open the page source, not the inspector.** This is the one real trap in the procedure. `Ctrl+U` (`Cmd+Option+U` on Mac) shows the HTML as the server sent it. The element inspector shows the DOM after JavaScript has run: your reviews always appear there, and you wrongly conclude everything is fine.

**Step 2. Search for `aggregateRating`.** With `Ctrl+F` in the source. Present with a `ratingValue` and attached to a `Product` block: you are at level 1, nothing to do. Present but attached to `Organization`: you are at level 2, the rating does not count for the page. Absent: go to step 3.

**Step 3. Search for your review count as a number.** If the page shows "128 reviews", search for `128`. Found inside an attribute like `data-number-of-reviews`: level 3. Found only in the text: level 4. Not found at all while the page displays it: **level 5, and that is the priority fix.**

For the fix, order matters, and the obvious shortcut does not work:

1. **Do not expect everything from your app's "rich snippets" toggle.** It is the natural reflex and it is often inert: with Judge.me, Loox and Yotpo, the markup that option produces is itself injected in JavaScript, so it stays invisible to the very engines discussed here. Only Okendo publicly documents server-side injection, and Stamped offers it as a manual theme snippet. Turn the option on, then **check the page source**: if `aggregateRating` does not appear, the toggle changed nothing for you.
2. **The reliable fix goes through the theme.** If your theme already publishes a `Product` JSON-LD (most recent Shopify themes do), add the `aggregateRating` field to it, fed by your review app's metafields. That is the only route that guarantees server-side rendering.
3. **Serve the rating as text too.** Markup serves Google; server-rendered text serves conversational engines. Together they cover every case.
4. **Never mark up a rating the page does not display.** Google requires review content to be visible to users. An `AggregateRating` without visible reviews is a policy violation, not an optimisation.

On multiple blocks: several `Product` blocks on one page are not a problem in themselves, Google reconciles them by `@id`. What causes problems is two blocks **declaring different values**. The full app-by-app fix procedure lives in our [AggregateRating](/en/kb/aggregate-rating/) reference.

Then verify with Google's Rich Results Test, and reload your product page with JavaScript disabled in the browser. What you read then is a good approximation of what a non-rendering crawler receives. The caveat: some servers vary their response by user-agent, so what `GPTBot` actually sees may differ. To remove the doubt, replay the request with its user-agent:

```
curl -A "GPTBot" -sL "https://your-store.com/products/your-product" | grep -c aggregateRating
```

## What the measurement says about the rest of the page

Reviews are the widest gap, but the same read gives the state of every other signal. Across the 457 pages, in raw HTML:

| Signal | Present |
|---|---|
| JSON-LD `Product` | 86.9% |
| Price | 67.4% |
| Availability | 66.7% |
| Brand | 85.6% |
| SKU | 35.7% |
| GTIN | 10.9% |
| Structured shipping | 4.6% |
| Structured return policy | 4.6% |
| `AggregateRating` in JSON-LD attached to the `Product` | 6.1% |

Two points deserve attention. Price is missing in 32.6% of cases, but the cause differs from reviews: 60 pages have no `Product` JSON-LD at all, and 89 publish a `Product` without a price. The price almost always stays readable in the page text, because Shopify themes render it server-side. That is a loss of precision, not a disappearance. And 4.4% of pages carry at least one JSON-LD block the parser rejects: an invalid block is worth an absent one.

Structured shipping and returns, both under 5%, remain the blind spot of the French market. Yet they are two purchase-decision criteria that conversational engines quote readily when they find them.

## What to take away

22 July shifted attention to Google. That is understandable, and it is not where your machine readability is decided, because Google already executes your widgets' JavaScript. The gap sits elsewhere: for a quarter of stores running a reviews app, engines that read raw HTML see no rating at all. Those engines are where assisted buying conversations happen today.

The fix needs no redesign and no budget, but it does need to target the right place: a field added to the theme's JSON-LD, rather than an app toggle that also produces JavaScript. What is usually missing is simply having looked at the right HTML.

One last caution on reading these numbers. They describe a population, not a product. At the scale of a single store the outcome depends on the integration mode chosen, not on the app's name: our [three store-by-store tests from 23 July](/en/blog/shopify-geo-optimization-guide/) produced three different results for identical apps.

*Kamil Kaderbay, founder of Verity Score. Measured 13 August 2026; method and limits detailed above. Next measurement on the same corpus: February 2027.*

---

## Related articles

- [AggregateRating: the rating AI engines actually read](/en/kb/aggregate-rating/)
- [The schema.org = ChatGPT citations myth](/en/blog/schema-org-chatgpt-citations-myth/)
- [Optimising your Shopify store for GEO](/en/blog/shopify-geo-optimization-guide/)
- [Blocked AI crawlers: the verification procedure](/en/blog/check-blocked-ai-crawlers-store/)

---

**Want to know what engines read from your pages?** The Verity Score Shopify app reads your product pages without executing JavaScript, like the ChatGPT and Claude crawlers, and lists the missing signals. [Install Verity Score from the Shopify App Store →](https://apps.shopify.com/verity-score)
## FAQ

### How do I know if my reviews are readable by AI engines?

Open your product page and view the page source with Ctrl+U (Cmd+Option+U on Mac). Use view-source, not the element inspector: the inspector shows the DOM after JavaScript has run, which gives a false sense of safety. Then search for aggregateRating with Ctrl+F. If it is not there, your rating is not in the standard format. Also search for your review count as a number: if the page displays it but the source does not contain it, the widget is injecting it in JavaScript.

### Does Google see my reviews if a JavaScript widget displays them?

Yes, in most cases. Google documents a three-stage process: crawling, rendering by a headless Chromium that executes JavaScript, then indexing. Google adds two caveats: pages sit in a render queue that can take longer than a few seconds, and the documentation still recommends server-side rendering because not all bots can run JavaScript. To display a review snippet in its results, however, Google requires explicit AggregateRating markup.

### Do the ChatGPT and Claude crawlers execute JavaScript?

No. The joint Vercel and MERJ analysis, covering hundreds of millions of crawler requests, found no evidence of JavaScript execution by GPTBot, ClaudeBot, PerplexityBot, Bytespider or meta-externalagent. These crawlers sometimes download JavaScript files without executing them. They read the HTML as your server sends it. OpenAI's own bot documentation describes its crawlers and their roles but says nothing about JavaScript execution.

### Do I need schema.org markup to appear in Google's AI Overviews?

No, and this is a common confusion. Google states explicitly that no special structured data is required to appear in AI Overviews or AI Mode. AggregateRating does something else: it earns a review snippet in classic results, and it makes your rating readable by engines that do not execute JavaScript. Both are real benefits. Neither is an AI Overviews benefit.

### My reviews app does not publish AggregateRating. What should I do?

Beware the shortcut: turning on the app's rich snippets option often changes nothing. With Judge.me, Loox and Yotpo, the markup that option produces is itself injected in JavaScript, so it stays invisible to the very engines this article is about. Only Okendo publicly documents server-side injection, and Stamped offers it as a manual theme snippet. Turn the option on, then check the page source: if aggregateRating is still absent, go through the theme instead by adding the field to the existing Product JSON-LD, fed by your review app's metafields.

### Is a data- attribute instead of markup a real problem?

It is better than nothing and worse than the standard. An attribute like data-number-of-reviews is served in the HTML, so a crawler that does not render JavaScript can read it if it knows where to look. But it is not a normalised format: no engine commits to interpreting a proprietary attribute, and Google does not use it for review snippets. It is nonetheless the most common case in our sample, 52.2% of equipped stores, and it is why Judge.me is never completely silent.

### My AggregateRating sits on the Organization rather than the product. Same thing?

No. A rating attached to the Organization describes your company, not the item on the page, so it does not make the product page eligible for review stars. In our sample 4% of equipped stores are in this position and believe they are compliant. It is also why a Trustpilot score, which by design rates the business, is not meant to produce a product-level AggregateRating.

### How many stores expose a price without JavaScript?

Of the 457 pages measured, 67.4% expose a price in their JSON-LD and 66.7% an availability value. The remaining third splits between pages with no Product JSON-LD at all (60 pages) and pages publishing a Product without a price (89 pages). Unlike reviews, the price almost always remains readable in the page text, because Shopify themes render it server-side.

### Does this measurement apply to non-Shopify stores?

The mechanism is universal: anything written only by JavaScript is invisible to a crawler that does not execute it. The figures, however, are specific to this sample of French Shopify stores. On a stack where the price itself is client-rendered, the gap is wider than reviews alone.

## Sources

- [Google: AI Overviews and AI Mode launch in France (22 July 2026)](https://blog.google/intl/fr-fr/nouveautes-produits/explorez-obtenez-des-reponses/recherche-ia-apercus-mode/) (official)
- [Google Search Central: JavaScript SEO basics, crawl then render then index](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics) (official)
- [Google Search Central: AI features and your website, no special structured data required](https://developers.google.com/search/docs/appearance/ai-features) (official)
- [Google Search Central: review snippet structured data, AggregateRating required](https://developers.google.com/search/docs/appearance/structured-data/review-snippet) (official)
- [Google Search Central: JSON-LD, microdata and RDFa are equally supported](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) (official)
- [Vercel and MERJ: AI crawlers do not render JavaScript (17 December 2024)](https://vercel.com/blog/the-rise-of-the-ai-crawler) (industry)
- [SearchOptimo: do AI crawlers render JavaScript, 2026 measurement (June 2026)](https://searchoptimo.com/blog/do-ai-crawlers-render-javascript) (industry)
- [OpenAI: crawler documentation for GPTBot, OAI-SearchBot and ChatGPT-User](https://developers.openai.com/api/docs/bots) (official)
- [Anthropic: crawler behaviour and its JavaScript recommendation](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler) (official)

