Part of our guide to Shopify Custom Sections: The Complete Guide.
Reviews are one of the most-requested storefront additions, and there are three honest ways to get them on a Shopify page: use a dedicated reviews app, build a review section yourself from data you already store, or place a review app block where an app provides one. This guide covers all three, with real section code for the do-it-yourself route, so you can pick the one that matches how your reviews are collected and where they live.
This page is part of the
Shopify custom sections guide. If you have
never built a section file before, read
How to create a custom section
first — this guide assumes you are comfortable with a sections/*.liquid file and
its {% schema %}.
First, decide where your reviews come from
The right approach depends entirely on where the review data lives:
- A reviews app collects and stores them (Shopify's own Shopify Product Reviews successor apps, Judge.me, Loox, Okendo, and so on). The app almost always ships its own section or app block — you place that, and it handles collection, moderation, and display.
- You store reviews yourself, as product metafields or in a spreadsheet you paste in. Then you build a section that reads and renders them.
- You want star ratings in search results. That is a schema.org question, not only a layout one — covered at the end.
Do not build a review-collection system from scratch in Liquid. Liquid renders data; it cannot receive and store a shopper's submitted review without a backend. For collection, an app is the practical answer. For display of data you already have, a section is the right tool.
Option 1 — Use a reviews app's section
If a reviews app is installed, it typically exposes an app block you add in the theme editor. Open Online Store → Themes → Customize, go to a product template, click Add block (or Add section) inside the product information area, and look for the app's review widget in the Apps group of the picker. Position it, save, and the app renders the stars and review list from its own stored data.
Because that block is rendered by the app rather than written into your theme files, it survives theme updates — the same reason app-rendered sections are more durable in general, explained in Shopify Theme App Extensions.
Option 2 — Build a review section from metafields
If you keep a handful of curated testimonials or editorial reviews per product, store them as a metafield and render them in your own section. This gives you full control of the markup with no third-party widget.
First, define the metafield under Settings → Custom data → Products. A
list.metaobject or a JSON metafield both work; the simplest is a
list-of-metaobjects, each with author, rating, and body fields. If you prefer
to avoid metaobjects, a single JSON metafield holding an array is fine too.
Then create sections/product-reviews.liquid and render the list:
{% assign reviews = product.metafields.custom.reviews.value %}
<section class="product-reviews">
<h2 class="product-reviews__title">{{ section.settings.heading }}</h2>
{% if reviews != blank %}
<ul class="product-reviews__list">
{% for review in reviews %}
<li class="product-reviews__item">
<div class="product-reviews__stars" aria-label="{{ review.rating }} out of 5">
{% for i in (1..5) %}
{% if i <= review.rating %}★{% else %}☆{% endif %}
{% endfor %}
</div>
<p class="product-reviews__body">{{ review.body }}</p>
<cite class="product-reviews__author">{{ review.author }}</cite>
</li>
{% endfor %}
</ul>
{% else %}
<p class="product-reviews__empty">No reviews yet.</p>
{% endif %}
</section>
{% schema %}
{
"name": "Product reviews",
"tag": "section",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "What customers say"
}
],
"presets": [{ "name": "Product reviews" }]
}
{% endschema %}
A few things worth calling out:
- The star loop draws filled (
★) and empty (☆) glyphs against the storedrating. Thearia-labelon the wrapper gives screen readers the numeric value instead of a row of symbols. - Everything reads from the metafield, so editors update reviews under the product, not in code. That is the same pattern as any data-driven section — see the tokens and metafields note in How to create a custom section.
- The
{% else %}branch avoids an empty, ragged block on products with no reviews yet.
Add a small stylesheet in the same file to space the list and size the stars:
{% stylesheet %}
.product-reviews { padding: 2rem 1.5rem; }
.product-reviews__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.5rem; }
.product-reviews__stars { color: #d9a441; font-size: 1.1rem; letter-spacing: 0.1em; }
.product-reviews__author { display: block; margin-top: 0.5rem; font-style: normal; opacity: 0.7; }
{% endstylesheet %}
Option 3 — Star ratings in Google results
Showing an average star rating in Google's search snippet requires valid
Product structured data with an
aggregateRating — and Google's policy is that the rating must reflect genuine,
site-visible reviews, not invented numbers. Most reviews apps output this schema
for you. If you render your own reviews, add the aggregateRating block to your
product JSON-LD and compute the average from the same metafield you display, so the
markup and the visible reviews always match. Never hard-code a rating that is not
backed by real reviews on the page.
Keep the review section update-safe
If you built Option 2 as a theme file, be aware of the trade-off: product-reviews.liquid
now lives inside your theme. When you update or switch themes, Shopify publishes a
fresh copy of the theme's files and your section file is not carried over — the
review block can vanish, even though the review data in your metafields stays put.
The full mechanics are in
Update your theme without losing customizations.
If your reviews are a permanent part of the product page, rendering the section from an app via a Theme App Extension means no theme update or swap can remove it. That is exactly what SectionGuard does — it renders your sections from the app, with the same in-editor configuration, so they survive every theme update. You can try it with Add to Shopify — Free.