Fixing aggregateRating Schema Errors
aggregateRating is the markup behind the gold stars under a search listing: an average score and the number of ratings it is based on. It is also the markup Google polices most closely, because stars attract clicks.
Errors come in two kinds: technical ones, such as a missing count or a score outside the scale, which the testing tools report; and policy ones, such as ratings a business wrote about itself or ratings that are not shown on the page, which the tools may pass but Google will not display. This guide covers both, with the exact fix for each and examples you can copy.
- What aggregateRating is, and where Google shows stars
- The fields aggregateRating needs
- The errors you will see, and what each one means
- Getting the scale right
- Self-serving, third-party and hidden ratings
- Fixing JSON that cannot be read
- The fix, step by step
- Stopping it from coming back
- Questions and answers
What aggregateRating is, and where Google shows stars
AggregateRating is a schema.org type that summarises many individual ratings into one:
the average (ratingValue), how many ratings or reviews it is based on (ratingCount
or reviewCount), and the scale (bestRating and worstRating). Google
uses it to show a review snippet: the stars, the score and the count under a search
result.
An aggregateRating is never shown on its own. It always belongs to something being rated, and Google only shows stars when that something is one of the types it supports for review snippets:
- Product: physical and digital products, including product variants.
- Recipe, Book, Movie and CreativeWorkSeason or CreativeWorkSeries.
- Course and Event.
- SoftwareApplication, for apps and software.
- LocalBusiness and Organization, but only when the ratings are collected about another business, never about your own (see the self-serving section below).
A rating on any other type, such as a WebPage, an Article or a Service
with no supported parent, may be valid schema.org, but it will never produce stars, and the Rich Results
Test reports it as an invalid parent type.
The fields aggregateRating needs
| Field | Required? | What it holds |
|---|---|---|
ratingValue | Required | The average score, such as 4.6.
A number or a numeric string, with a full stop for the decimal. |
ratingCount or reviewCount | Required (one of them) | How many ratings (ratingCount) or written reviews (reviewCount) the average is based on. Must be above zero. |
itemReviewed | Required when not nested | The thing being rated. Not needed when the aggregateRating sits inside its parent, such as inside a Product. |
bestRating | Recommended | The top of the scale. Defaults to 5; give it for any other scale, such as 10 or 100. |
worstRating | Recommended | The bottom of the scale. Defaults to 1; give it if your scale starts at 0. |
A correct block you can copy: nested in a Product
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Oak chopping board, large",
"image": "https://example.com/images/oak-board.jpg",
"brand": { "@type": "Brand", "name": "Northwood" },
"offers": {
"@type": "Offer",
"price": "34.00",
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.6",
"reviewCount": "127",
"bestRating": "5",
"worstRating": "1"
}
}
</script>
The same rating as a separate node
If your markup keeps the rating apart from the product, for example in an @graph, it
must say what it rates with itemReviewed:
{
"@type": "AggregateRating",
"itemReviewed": { "@id": "https://example.com/oak-board#product" },
"ratingValue": "4.6",
"reviewCount": "127"
}
The errors you will see, and what each one means
These are the messages the Rich Results Test, the Search Console Review snippets report, the Schema Markup Validator and the Schema Debugger give for ratings, with the cause behind each one.
| Message | Cause | Fix |
|---|---|---|
| Either "ratingCount" or "reviewCount" should be specified | A ratingValue with no count. | Add the number of ratings or reviews the average is based on. |
| Invalid value in field "ratingCount" / "reviewCount" | The count is 0, blank, or text such as "127 reviews". | Use a whole number above 0. With no ratings yet, leave aggregateRating out. |
| Missing field "ratingValue" | The score is missing, or it is in rating or
value. | Put the average in ratingValue. |
| Rating is out of range / Value in "ratingValue" is out of range | The score is above bestRating or below worstRating, often a 10-point score with the default 5-point scale. | Add the right bestRating
and worstRating, or convert the score. |
| Missing field "itemReviewed" | A stand-alone AggregateRating that does not say what it rates. | Nest it inside its parent, or add itemReviewed. |
| Invalid object type for field "<parent_node>" | The rating sits on a type that cannot have review snippets, such as WebPage or Service. | Move it to a supported type such as Product or Recipe, or remove it. |
| Invalid value in field "ratingValue" | A decimal comma ("4,6"), a percentage ("92%") or stars as text ("โ โ โ โ "). | Write a plain number with a full stop: 4.6. |
| Multiple aggregate ratings for one item | A product plugin and a review plugin both add a rating to the same Product. | Keep the one that matches the ratings shown on the page. |
Getting the scale right
Google shows stars on a five-point scale. If your ratings use another scale, tell Google the scale and it converts the score. Get the scale wrong and the stars are wrong, or the rating is rejected as out of range.
| Your scale | Write | Google shows |
|---|---|---|
| 1 to 5 stars | "ratingValue": "4.2" (bestRating can be left out) | 4.2 stars |
| Out of 10 | "ratingValue": "8.4", "bestRating": "10" | 4.2 stars |
| Percentage | "ratingValue": "84", "bestRating": "100", "worstRating": "0" | 4.2 stars |
| 0 to 5, where 0 is allowed | "ratingValue": "3.9", "worstRating": "0" | 3.9 stars |
Rounding and freshness
Round the average to one decimal place, and keep the value and count in step with the ratings shown on the page. If the page says 4.6 from 127 reviews and the markup says 4.8 from 90, the markup is out of date, and a mismatch between markup and page is treated as misleading.
Self-serving, third-party and hidden ratings
Most ratings that pass every test but never show stars fail on policy, not syntax. The testing tools cannot see these problems, so they need checking by hand.
Self-serving reviews
Since 2019 Google does not show review snippets for a LocalBusiness or Organization
when the business collects and marks up ratings about itself on its own site. A plumber marking up its
own five-star average on its home page, or a company adding an aggregateRating to its Organization node,
falls into this rule. The markup is ignored for stars, and heavy use can be treated as spam.
Ratings of your products, on your own product pages, are fine. The rule is about a business rating itself.
Ratings from other sites
Ratings must be collected on your own site. Copying a Trustpilot, Google or Facebook average into your markup, or marking up a third-party review widget, breaks the review snippet rules. Show the widget if you like, but do not put its numbers in your structured data.
Hidden or invented ratings
- The rating in the markup must be visible on the same page, with the score and the count.
- Readers must be able to leave a rating, or see the reviews it was built from.
- Ratings written by the site owner, paid for, or made up to fill a template are fake reviews under Google's spam policies and can bring a manual action that removes stars from the whole site.
- A fixed rating hard-coded into a theme, the same 4.9 on every page, is the most common version of this we find in audits.
Fixing JSON that cannot be read
A rating inside an unparsable block is lost along with everything else in that block, including the Product or Recipe it belongs to. The usual faults are the same four as in every JSON-LD block.
- A trailing comma after the last field, often left when
worstRatingis deleted:"bestRating": "5", }. - Curly quotes around names or values, from text pasted out of a word processor.
- An unescaped quote in a product or review name, such as a size in inches:
12" panmust be written12\" pan. - A raw line break inside a review body.
A fifth problem is special to ratings: templates that print the value without quotes, such as "ratingValue": ,,
when a product has no ratings yet. The value is empty and the JSON is broken. The template must leave
the whole aggregateRating out when the count is zero.
{% if review_count > 0 %}
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{ rating_average | round: 1 }}",
"reviewCount": "{{ review_count }}"
},
{% endif %}
The fix, step by step
Step 1
Find every rating on the page
Open
the page source (Ctrl+U, or Cmd+Option+U on a Mac) and search for aggregateRating. Note
each match and where it comes from: the shop platform, a review plugin such as Judge.me, Yotpo or Reviews.io,
an SEO plugin, the theme or a widget. The Schema Debugger lists every rating together with its parent
type, which shows at once when two sources rate the same product.
Step 2
Put the rating on a supported parent type
Check what each rating is attached to. A rating on a Product, Recipe, Book, Course, Event or SoftwareApplication is fine. A rating on a WebPage, on your own Organization or on your own LocalBusiness will not show stars and may be treated as self-serving: move it to the product it actually describes, or remove it from the markup while keeping the visible reviews on the page.
Step 3
Add the required fields
Every
aggregateRating needs ratingValue and a ratingCount or reviewCount
above zero. A stand-alone rating in an @graph also needs itemReviewed pointing
at the product or recipe it rates. If an item has no ratings yet, the template should leave the whole
rating out rather than printing an empty value or a count of zero, which breaks the block. Re-test the
page after the change.
Step 4
Set the scale correctly
Match
bestRating and worstRating to the scale your readers actually use: leave them
out for 1 to 5 stars, give bestRating 10 for scores out of ten, and bestRating 100 with worstRating 0
for percentages. Write decimals with a full stop, never a comma, and round the average to one decimal
place so it matches the score shown to readers on the page.
Step 5
Check the rating is allowed and visible
Compare the markup with the page: the same score and the same count must be visible to readers, and readers must be able to leave a rating or see the reviews behind it. Remove self-serving ratings on your own business, ratings copied from Trustpilot, Google or other sites, and fixed ratings hard-coded into the theme that show the same score on every page.
Step 6
Test and request a recrawl
Test the live URL in the Rich Results Test: the parent, such as the Product or Recipe, should show a valid review snippet with no errors. Then use URL Inspection in Search Console and choose Request indexing, and watch the Review snippets report under Enhancements, pressing Validate fix once every affected page is corrected so Google confirms the whole group. Re-test after any review app update.
Stopping it from coming back
- One rating source. Let the review system you actually use output the rating, and switch off rating output in the theme and in any second plugin.
- Build it from live data. The markup should read the same average and count as the visible stars, so they cannot drift apart.
- No ratings, no markup. Make the template skip aggregateRating when the count is zero.
- Never rate yourself. Keep ratings off your own Organization and LocalBusiness nodes, on every page.
- Test after updates. Review plugins change their markup often. Re-run the Schema Debugger on one product page after each update.
1. Why are my star ratings not showing in Google?
First check the live page in the Rich Results Test for errors such as a missing count or a score out of range. If the test is clean, the usual reasons are policy ones: the rating is about your own business, it is copied from another site, it is not visible on the page, or it sits on a type Google does not show stars for, such as a WebPage. Valid markup makes a page eligible for stars, but Google decides whether to show them.
2. Can I add star ratings to my own business?
You can show reviews of your business on your own site, but Google will not display review snippets for a LocalBusiness or Organization that marks up ratings about itself. This self-serving rule has applied since 2019. Stars for your business in Google come from reviews on your Google Business Profile instead. Ratings of the products you sell, marked up on your own product pages, are allowed, because the rule is about a business rating itself.
3. What is the difference between ratingCount and reviewCount?
ratingCount is the total number of ratings behind the average, including star ratings left with no written text. reviewCount is the number of written reviews. Use whichever matches what your review system collects, and you can give both if you have both figures. At least one of them is required, and it must be a whole number above zero. With no ratings yet, leave aggregateRating out of the markup entirely.
4. Can I use my Trustpilot or Google rating in schema?
No. Ratings in your structured data must be collected on your own site from your own customers. Copying a Trustpilot, Google or Facebook average into your markup, or marking up a third-party review widget, breaks the review snippet rules, and heavy use can lead to a manual action. Showing the widget on the page is fine as a trust signal; simply keep its score and count out of your structured data.
5. What does rating out of range mean?
It means the ratingValue is higher than bestRating or lower than worstRating. The usual cause is a score on a 10-point or percentage scale with no bestRating given, so Google assumes the default 5-point scale and reads 8.4 as 8.4 out of 5. Add bestRating 10, or bestRating 100 with worstRating 0 for percentages, and Google converts the score to stars. A decimal comma such as 4,6 causes a similar error.
6. Should a product with no reviews have aggregateRating?
No. Leave aggregateRating out until the product has at least one real rating. A rating with a count of zero, a blank value or a placeholder such as 5 stars from 0 reviews is an error in the Rich Results Test, and a template that prints an empty value breaks the whole JSON block. Set the template to skip aggregateRating whenever the review count is zero, and it will appear on its own once the first review arrives.
7. How long before stars appear after the fix?
After you request indexing with URL Inspection, Google usually recrawls the page within a few days, and the Review snippets report in Search Console updates as pages are recrawled, which can take up to two weeks across a site. Stars can take longer to appear than the report takes to clear, and Google may still choose not to show them for a particular search or for a site it does not yet trust.
The Schema Debugger lists every aggregateRating on a page with its parent type, flags missing counts, scales out of range and self-serving ratings, and checks the score and count against the visible page.
Open Schema Debugger Fixes โ