The problem: your JavaScript-loaded reviews are invisible to most AI
Customer reviews are one of the strongest trust signals for AI shopping agents. Yet on most Shopify stores, the stars shown to human visitors are never read by ChatGPT, Perplexity, Claude, Mistral Le Chat or most other LLMs.
The reason is technical. Loox, Judge.me, Yotpo, Reviews.io and the majority of review apps inject their AggregateRating client-side, via JavaScript, after the page loads. AI crawlers only retrieve the initial HTML returned by the server : they don’t execute JavaScript. In that source HTML, there are no stars, no average rating, no review count.
A store with 5,213 reviews and a 4.8/5 rating is therefore presented to AI as a store with zero reviews, zero stars.
The simple test to check your store
From a terminal, run this command replacing the URL with one of your product pages:
curl -A "GPTBot" -sL "https://your-store.com/products/example" | grep -i "aggregaterating"
If the command returns nothing, your AggregateRating isn’t in the native HTML. It’s injected via JavaScript, therefore invisible to GPTBot and all AI crawlers that work the same way.
You can validate with two official tools:
- Google Rich Results Test : “View tested source” tab to see exactly what Googlebot interprets
- Schema.org Validator : structure and JSON-LD validity
Why AI crawlers don’t render JavaScript
The main AI crawlers operate in simple HTTP mode, without a headless browser. They send a request, read the received HTML, and move to the next document. This isn’t trivial: it’s documented by the model providers, measured at scale, and cross-referenced between studies.
AI crawlers and JavaScript rendering matrix
| Crawler | Operator | Renders JavaScript? | Source |
|---|---|---|---|
| GPTBot | OpenAI | No | OpenAI docs, Vercel 500M+ req |
| OAI-SearchBot | OpenAI | No (not explicitly documented) | OpenAI bots |
| ChatGPT-User | OpenAI | No | Same |
| ClaudeBot | Anthropic | No (“don’t rely on JavaScript”) | Anthropic privacy |
| Claude-SearchBot | Anthropic | No | Same |
| PerplexityBot | Perplexity | No | Perplexity crawlers |
| Meta-ExternalAgent | Meta | No | Meta webmasters |
| CCBot | Common Crawl | No (official) | Common Crawl FAQ |
| MistralAI-User | Mistral | Browser-session-like, does not respect robots.txt | docs.mistral.ai/robots |
| Google-Extended | Yes (reuses Googlebot’s Web Rendering Service) | Google crawlers | |
| Applebot / Applebot-Extended | Apple | Yes | Apple support |
| Bingbot | Microsoft | Yes, partial (evergreen via Edge) | Bing blog |
Out of 12 major crawlers, only Googlebot, Bingbot and Applebot reliably render JavaScript. All others read only the initial HTML.
What it means for your store
If your AggregateRating is loaded via JavaScript and you want to appear in:
- ChatGPT text answers (via Bing + GPTBot/OAI-SearchBot): invisible
- Claude citations (via ClaudeBot): invisible
- Perplexity text answers (via PerplexityBot): invisible
- Mistral Le Chat: invisible
- Meta AI in WhatsApp, Instagram and Facebook: invisible
- Grok on X, DeepSeek, Qwen: invisible
- Custom MCP agents (Zapier, n8n, Make) proliferating in 2026: invisible
- Browser agents that scrape page HTML: invisible
The Google Merchant Center feed, detailed below, covers part of the problem : but only for 2 AI surfaces out of more than 12.
Why Shopify doesn’t natively expose AggregateRating
The official Liquid filter {{ product | structured_data }} produces a minimal Product schema containing @context, @id, @type, brand, category, description, image, name, offers and url. It does not include aggregateRating, review or rating, as documented on the Shopify reference.
The reason was given publicly by a Dawn theme maintainer in GitHub issue #3535:
“We are only returning fields in the structured data that come from concrete data, not sourced from metafields.”
Reviews live in third-party app metafields (Loox, Judge.me, Yotpo, etc.). Shopify therefore doesn’t surface them in its default schema. On an official Online Store 2.0 theme (Dawn, Craft, Sense, Studio, Crave, Taste, Ride, Origin, Colorblock, Publish), the server-side HTML of a product page contains no review data. Everything goes through the apps’ JS widgets.
Detailed analysis of the 7 main Shopify review apps
Loox
Widget rendering: app block via Shopify Online Store 2.0, loox core script executed client-side.
AggregateRating JSON-LD: Loox announces automatic generation of Product, Offer and AggregateRating JSON-LD (Loox rich results blog). Public documentation doesn’t explicitly specify whether this injection is server-side via a theme app extension Liquid block, or client-side via script : in practice, it operates as a JS injection into the DOM.
Google Merchant Center syndication: available starting on the Scale plan, requires at minimum 50 published reviews, syndicates all verified reviews without filter (Loox GMC help).
Judge.me
Widget rendering: Liquid template <div class="jdgm-widget jdgm-preview-badge" data-id="{{ product.id }}">{{ product.metafields.judgeme.badge }}</div> hydrated by widget.js client-side (Judge.me Liquid code).
JSON-LD rich snippets: togglable in Settings → Advanced → Rich Snippets. Judge.me recommends enabling JSON-LD and disabling microdata to avoid duplicates.
Google Merchant Center syndication: manual setup via Settings → Google and SEO → Google Shopping. Requires a minimum of 50 reviews, product identifiers (GTIN preferred), and Google manual approval of 2 to 4 weeks (Judge.me GMC help).
Yotpo
Widget rendering: Yotpo admits in its own documentation: “Yotpo’s JavaScript automatically loads on your product pages, detects the product, fetches the latest review data, and injects the perfect JSON-LD schema into the page’s code” (Yotpo blog). This is client-side injection by construction.
Google Merchant Center syndication: available on Starter, Pro, Premium, Enterprise (not on Free). Requires 50 total reviews and 3 reviews minimum per product. UGC photos restricted to Premium and Enterprise (Yotpo GMC syndication).
Stamped
Widget rendering: client-side via <script> before </body> (Stamped install).
AggregateRating JSON-LD: Stamped provides a JSON-LD block to manually paste into product.liquid, which reads Stamped metafields and produces server-side AggregateRating (Stamped rich snippets). Without this manual installation, nothing appears server-side.
Reviews.io
Default rendering: 3 <script> before </body> + a <div data-sku> placeholder (Reviews.io rich snippets). Client-side injection. Rich snippets limited to Start-Up, Grow, Plus, Launch, Launch Plus plans.
Okendo
Widget rendering: server-side pre-rendering per Okendo marketing docs (site speed reviews).
AggregateRating JSON-LD: Okendo is the only app that officially documents server-side injection via a Liquid snippet. The official guide asks to create snippets/okendo-reviews-json-ld.liquid, include {% render 'okendo-reviews-json-ld' %} in theme.liquid, and read the metafields product.metafields.okendo.summaryData.reviewAverageValue and product.metafields.okendo.summaryData.reviewCount (Okendo rich snippets).
It’s currently the only app on the Shopify market with a clearly documented native SSR path.
Opinew
Hybrid approach: Opinew provides a snippet that reads server-side metafields (product.metafields.opinew_metafields.reviews_count, .reviews_rating), then uses a client-side script to create a <script type="application/ld+json"> element and inject it into the DOM after load (Opinew rich snippets).
Opinew also integrates with third-party SEO apps like JSON-LD for SEO, Yoast SEO and SEO Booster, which read Opinew metafields server-side and emit JSON-LD in native HTML. This is the path that guarantees AI visibility with Opinew.
Summary: server-side AggregateRating per app
| App | Widget | Default JSON-LD | Documented SSR path |
|---|---|---|---|
| Loox | Client-side | JS injection | Not publicly documented |
| Judge.me | Client-side | Togglable option, JS injection | Not publicly documented |
| Yotpo | Client-side | JS injection (Yotpo-admitted) | No |
| Stamped | Client-side | No (manual install required) | Yes, manual |
| Reviews.io | Client-side | Client scripts by default | Not documented |
| Okendo | Server-side | Native Liquid snippet | Yes, documented |
| Opinew | Client-side | JS by default, or third-party SEO app | Yes, via third-party app |
The Google Merchant Center feed: a partial solution
All major review apps offer syndication to Google Merchant Center. This path feeds the ChatGPT product carousel (83% of carousels come from Google Shopping per the Peec AI study covered by Search Engine Land) and Perplexity’s carousel.
What the GMC feed covers
- The ChatGPT product carousel (via Google Shopping)
- The Perplexity product carousel if the merchant is enrolled in the Perplexity Merchant Program
- Classic Google Shopping
- Partially Google AI Mode carousels
What the GMC feed doesn’t cover
- ChatGPT text answers and citations (Bing crawler pipeline, 87% of SearchGPT citations match Bing top 20 per Seer Interactive)
- Perplexity text answers (PerplexityBot crawler on HTML)
- Claude, Mistral Le Chat, Meta AI, Grok, DeepSeek, Qwen, Pi, Cohere (all crawler-only)
- Citations in Google AI Overviews
- Custom MCP agents (Zapier, n8n, Make, ChatGPT Apps)
- Live browser agents (Comet, Claude Computer Use, Browser Use)
For these surfaces, AggregateRating must be present in native HTML, as JSON-LD or microdata, extractable without JavaScript execution.
GMC feed setup: not default, not automatic
None of the 3 main apps (Loox, Judge.me, Yotpo) enable GMC syndication by default. Each requires a manual toggle, specific prerequisites, and Google validation over several weeks. See the table above for requirements per app.
The fix: expose AggregateRating in server-side HTML
Even with a client-side widget, all review apps write data to Shopify metafields accessible server-side. These metafields are read at Liquid render time, which allows emitting JSON-LD directly in the initial HTML.
Here’s a Liquid snippet example to place in sections/main-product.liquid or templates/product.liquid:
{% if product.metafields.reviews.rating_count and product.metafields.reviews.rating_count != "0" %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"@id": "{{ shop.url }}{{ product.url }}#product",
"name": {{ product.title | json }},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{ product.metafields.reviews.rating.value }}",
"reviewCount": "{{ product.metafields.reviews.rating_count }}",
"bestRating": "5",
"worstRating": "1"
}
}
</script>
{% endif %}
The namespace product.metafields.reviews.* is the historical one of the official Product Reviews by Shopify app (now deprecated). For other apps, adapt the namespace:
| App | Namespace to use |
|---|---|
| Judge.me | product.metafields.judgeme.badge (contains HTML) + exposed numeric metafields |
| Okendo | product.metafields.okendo.summaryData.reviewAverageValue and .reviewCount |
| Opinew | product.metafields.opinew_metafields.reviews_rating and .reviews_count |
| Yotpo | product.metafields.yotpo.reviews_average and .reviews_count (community-confirmed, not publicly documented) |
Rules for valid JSON-LD
Per the official Google spec:
ratingValueis required- At least one of
ratingCountorreviewCountis required ratingValuemust be betweenworstRatingandbestRating(default 1 and 5)- Don’t emit AggregateRating if the product has 0 reviews (triggers Search Console warnings)
Final validation
After adding the snippet, validate through 3 channels:
curl -A "GPTBot" -sL "PRODUCT-URL" | grep aggregaterating: must return a line with JSON-LD- Google Rich Results Test : must display valid “Review snippets”
- Schema.org Validator : must validate the structure
Context data: how many AI read your HTML?
Vercel, which operates a CDN measuring AI crawler traffic, published in 2025 an analysis of over 500 million GPTBot requests and 370 million ClaudeBot requests per month. On this sample, neither crawler executes JavaScript (Vercel AI crawler).
Yext analyzed 6.8 million AI citations and identified that 86% of AI citations come from brand-managed sources (own site, feeds, structured FAQs) (Yext press release). Investing in your own HTML is therefore more effective than relying exclusively on third-party sources.
Related articles
- Schema.org Product on Shopify: complete guide
- Sell on ChatGPT: Shopify guide 2026
- Perplexity Shopping: Shopify merchant guide
- robots.txt and AI crawlers: what to allow
- E-E-A-T for AI: how agents evaluate trust
- Golden Record: product data completeness
Ready to check your store? Run a free GEO audit →