Skip to content
Published Authored byBilly Reiner

Schema · How-to

Shopify AggregateRating schema

AggregateRating is the Schema.org type for an average rating based on multiple individual ratings or reviews1. On a Shopify PDP, it lives as a sub-object on Product. Properties: ratingValue, ratingCount, reviewCount, bestRating, worstRating. The catch is narrower than most guides claim. Google's self-serving rule covers a business that controls reviews about itself, on pages using LocalBusiness or Organization markup2. Customer ratings of a product, shown on your own product page, are not self-serving under that rule.

What this means in practice on Shopify: the review app you use (Judge.me, Yotpo, Okendo, Stamped.io, Reviews.io or an in-house system) doesn't decide eligibility. What decides it is whether the ratings come directly from your customers, are visible on the page, and weren't copied from another website or bought with an undisclosed incentive. A store rating its own business with testimonials on an Organization page is the self-serving case.

What AggregateRating is

Per Schema.org v30.0, AggregateRating is 'the average rating based on multiple ratings or reviews.' Type hierarchy: Thing > Intangible > Rating > AggregateRating. The required-by-Google fields are ratingValue, ratingCount or reviewCount (at least one), itemReviewed (handled implicitly when AggregateRating is a sub-object on Product). Recommended: bestRating and worstRating to disambiguate the rating scale.

Mental model: AggregateRating is the summary statistic; Review is the individual data point. A Shopify product with 47 reviews averaging 4.8 stars has one AggregateRating object (the summary) and up to 47 Review objects (each individual rating). Most Shopify schema work emits AggregateRating only — Review objects are heavier to emit and rarely needed for the rich snippet, which uses the aggregate.

The self-serving review rule on Shopify

Google's review snippet documentation words the self-serving rule precisely: if the entity being reviewed controls the reviews about itself, its pages that use LocalBusiness or any other Organization structured data are ineligible for the star review feature. The rule is about businesses rating themselves. A Product's AggregateRating, built from ratings your customers gave the product and shown on the product page, falls outside it. The rules that do apply to product ratings: they must be sourced directly from users, visible on the page, not aggregated from other websites, and not fake or undisclosed incentivized reviews.

Shopify review apps that emit AggregateRating cleanly

The 2026 Shopify review-app market splits into two groups. (1) Review apps such as Yotpo, Stamped.io, Judge.me, Reviews.io, Okendo and Loox, some of which print their own AggregateRating from an app block. (2) Custom in-house systems built on Shopify metafields or metaobjects, which require the merchant to author AggregateRating JSON-LD by hand. Shopify's own Product Reviews app is no longer available on the App Store. Either way, Shopify defines two standard metafields for the summary: reviews.rating (type rating, the average) and reviews.rating_count (an integer, the number of ratings), and asks rating apps to keep them updated.

Audit step before authoring: install the review app in a staging store, view source on a PDP with reviews, find-on-page for AggregateRating. If the app emits its own block, you do not need to author one. If it doesn't, author the block via Liquid from the standard metafields5, which is what Dawn's product cards already read to draw their stars7.

AggregateRating fields

The properties that matter: ratingValue (Number/Text — the average, e.g. 4.8), ratingCount (Integer — total ratings received), reviewCount (Integer — total reviews received; can equal ratingCount), bestRating (Number/Text — the highest possible, e.g. 5), worstRating (Number/Text — the lowest possible, e.g. 1).

  • ratingValue — required. The average rating. Typical scale: 1–5.
  • ratingCount OR reviewCount — at least one required by Google.
  • bestRating — recommended. Default is 5 if omitted, but emitting it removes ambiguity.
  • worstRating — recommended. Default is 1 if omitted.
  • itemReviewed — required when AggregateRating is top-level; implicit when nested as a sub-object of Product.

JSON-LD example — AggregateRating from a third-party review app

The block below shows AggregateRating inside a Shopify Product block, built from Shopify's standard product-rating metafields. reviews.rating is a rating-type metafield, so its .value is a rating object with rating, scale_min and scale_max properties; reviews.rating_count is a whole number. The scale comes from the metafield, so bestRating and worstRating always match the app's scale.

JSON-LD AggregateRating inside Product, from Shopify's standard reviews.rating and reviews.rating_count metafields
{%- assign sr_rating = product.metafields.reviews.rating.value -%}
{%- assign sr_count = product.metafields.reviews.rating_count.value | default: 0 -%}
{%- if sr_rating != blank and sr_count > 0 -%}
"aggregateRating": {
  "@type": "AggregateRating",
  "ratingValue": {{ sr_rating.rating | json }},
  "bestRating": {{ sr_rating.scale_max | json }},
  "worstRating": {{ sr_rating.scale_min | json }},
  "ratingCount": {{ sr_count | json }}
},
{%- endif -%}

Validation

Rich Results Test against a PDP with AggregateRating should report Product detected with the AggregateRating parsed and no errors, under Product snippets or Merchant listings. Errors come from missing required properties: ratingValue, or both ratingCount and reviewCount. A clean test means the markup is eligible; Google still decides whether stars appear.

A subtle gotcha: the Rich Results Test checks structure, not policy. It can't tell whether the ratings were copied from another site, whether they're visible on the page, or whether a review was incentivized. Those are Google's content guidelines2, and breaking them can cost the snippet even when the test passes. Audit the source of the ratings yourself.

Shopify gotchas on AggregateRating

Four gotchas. First: emitting AggregateRating with ratingValue '0' and ratingCount '0' on products that haven't been reviewed (branch on the metafields, see above). Second: reading a metafield that doesn't exist. There is no reviews.rating_value; the standard keys are reviews.rating (a rating object, so you need .value.rating) and reviews.rating_count. Third: emitting AggregateRating both from your manual block AND from a review-app's auto-emitted block, producing duplicate AggregateRating on one Product. Fourth: hard-coding bestRating as 10 when the app uses a 1–5 scale, causing 4.8 to render as '4.8 out of 10'. Reading scale_max from the metafield avoids it.

A fifth gotcha: ratingValue must be a plain number with a period as the decimal separator (4.8, not 4,8). The standard rating metafield stores a number, and printing it through | json keeps it that way. The risk comes from apps that store their own rating as text; if yours writes '4,8', fix it at the source rather than patching the output.