Widget data API
Every widget is one static JSON file on our CDN. Use our script to show it, or read the file and build your own display.
1. How it works
Each widget has a key, for example kroonvosdemo2026widget01. You find it in the embed code in your Shopreviews account. The key gives you two public URLs:
The first is the script that draws the widget. The second is the widget's data: its settings, your score and the reviews it shows. Shopreviews rewrites that file whenever something changes. Showing a widget only reads the file, so it stays fast however busy your site is.
The key never changes. You can switch plan, layout or review sources and the embed code on your site keeps working. Only the content of the file changes.
2. Embed code
Paste this where the widget should appear. Add the script once per page, even with several widgets.
<script src="https://cdn.shopreviews.com/widget.js" async></script>
<div data-shopreviews-widget="kroonvosdemo2026widget01"></div>
The widget renders inside a Shadow DOM, so your CSS and ours do not affect each other. It loads when it scrolls near the visible part of the page.
The script sends a shopreviews:render event on the element when a widget is drawn:
document.addEventListener('shopreviews:render', (event) => {
console.log(event.detail.key, event.detail.layout);
});
3. Embed attributes
The settings saved in your account apply by default. These optional attributes override them for one place on your site:
| Attribute | Values | What it does |
|---|---|---|
data-layout | carousel, grid, list, badge, text, popup | Shows the same widget in another layout. |
data-limit | a number | Shows fewer reviews. It cannot show more than the widget is set to. |
data-min-rating | 1 to 5 | Hides reviews below this rating. The score at the top does not change. |
data-lang | en, nl, de, fr, es | Language of the labels, such as "Read more". Without it the widget follows the lang of your page. Only works when the widget language is set to automatic. |
data-theme | light, dark, auto | Colour theme. |
data-accent | a hex colour, e.g. #1E204F | Accent colour. |
data-lazy | false | Loads the widget at once instead of when it scrolls into view. |
Example:
<div data-shopreviews-widget="kroonvosdemo2026widget01"
data-layout="grid"
data-limit="3"
data-lang="de"
data-theme="dark"></div>
4. Reading the JSON yourself
You do not need our script. The file is plain JSON, open to any site, and needs no API key.
curl https://cdn.shopreviews.com/w/kroonvosdemo2026widget01.json
| Method | GET |
| Authentication | None. The file holds only what the widget shows in public. |
| CORS | Access-Control-Allow-Origin: *, so you can fetch it in the browser. |
| Content type | application/json; charset=utf-8 |
| Caching | Cache-Control: public, max-age=300 |
| Key format | 8 to 64 letters and digits |
An unknown, paused or deleted widget does not give an error. It answers with status 200 and this body, so check for it first:
{"off":true}
JavaScript
const res = await fetch('https://cdn.shopreviews.com/w/kroonvosdemo2026widget01.json');
const doc = await res.json();
if (!doc.off) {
console.log(doc.summary.average, doc.summary.count); // 4.5 60
for (const review of doc.reviews) {
console.log(review.rating, review.author ?? doc.i18n.anonymous, review.body);
}
}
PHP
$json = file_get_contents('https://cdn.shopreviews.com/w/kroonvosdemo2026widget01.json');
$doc = json_decode($json, true);
if (empty($doc['off'])) {
printf("%.1f from %d reviews\n", $doc['summary']['average'], $doc['summary']['count']);
}
5. Sample document
This is a shortened document of a demo shop with three review sources. The complete file is at /docs/sample-widget.json. The shop and its reviews are made up.
{
"v": 1,
"published_at": "2026-11-12T09:30:00+00:00",
"widget": {
"key": "kroonvosdemo2026widget01",
"layout": "carousel",
"settings": {
"accent_color": "#FB3B39",
"theme": "light",
"ui_language": "nl",
"min_rating": 4,
"limit": 6,
"sort": "recent",
"show_summary": true,
"header_text": "Wat klanten over ons zeggen"
}
},
"summary": {
"average": 4.5,
"count": 60,
"distribution": {
"5": 39,
"4": 16,
"3": 3,
"2": 2,
"1": 0
},
"providers": [
{
"provider": "google",
"label": "Google Business Profile",
"logo": "https://portal.shopreviews.com/images/providers/google.svg",
"count": 34,
"average": 4.5
},
{
"provider": "trustpilot",
"label": "Trustpilot",
"logo": "https://portal.shopreviews.com/images/providers/trustpilot.svg",
"count": 16,
"average": 4.4
}
]
},
"reviews": [
{
"id": 55,
"provider": "google",
"provider_label": "Google Business Profile",
"provider_logo": "https://portal.shopreviews.com/images/providers/google.svg",
"author": "Sanne de Wit",
"rating": 5,
"title": null,
"body": "Mijn e-bike was binnen twee dagen afgesteld en klaar. Duidelijke uitleg en geen verkooppraatje.",
"language": "nl",
"date": "2026-11-10T14:12:00+00:00",
"verified": true,
"reply": "Dank je wel Sanne, veel fietsplezier!",
"product_sku": null,
"product_name": null
},
{
"id": 56,
"provider": "trustpilot",
"provider_label": "Trustpilot",
"provider_logo": "https://portal.shopreviews.com/images/providers/trustpilot.svg",
"author": "Mark Jansen",
"rating": 5,
"title": "Snelle levering, goed verpakt",
"body": "Besteld op maandag, woensdag in huis. De fiets was voor 95% gemonteerd en de handleiding klopte.",
"language": "nl",
"date": "2026-11-07T14:12:00+00:00",
"verified": true,
"reply": null,
"product_sku": null,
"product_name": null
}
],
"branding": false,
"i18n": {
"based_on": "Gebaseerd op {count} reviews",
"verified": "Geverifieerd",
"read_more": "Lees meer"
},
"i18n_all": {
"en": {
"based_on": "Based on {count} reviews"
},
"nl": {
"based_on": "Gebaseerd op {count} reviews"
}
},
"schema": null,
"links": {
"powered_by": "https://www.shopreviews.com/?utm_source=widget&utm_medium=referral"
},
"domains": [
"kroonenvos.example"
]
}
6. Field reference
Top level
| Field | Type | Meaning |
|---|---|---|
v | number | Version of the document format. Now 1. |
published_at | string | When the file was last written, ISO 8601. |
widget | object | Key, layout and display settings. |
summary | object | Score and counts over all visible reviews of the widget, not only the ones in reviews. |
reviews | array | The reviews the widget shows, already filtered, sorted and limited. |
branding | boolean | True when the plan shows the "Powered by Shopreviews" label. |
i18n | object | Labels in the widget language. |
i18n_all | object | Labels in every language, keyed by language code. Only present when the widget language is automatic. |
schema | object or null | JSON-LD AggregateRating for search engines, when enabled for the widget. |
links.powered_by | string | Link behind the label. |
domains | array | Only present when the widget is limited to certain sites. *.example.com covers subdomains. |
off | boolean | Only present, and true, when there is no widget to show. |
widget
| Field | Type | Meaning |
|---|---|---|
key | string | The widget key. |
layout | string | carousel, grid, list, badge, text or popup. |
settings.accent_color | string | Hex colour. |
settings.theme | string | light, dark or auto. |
settings.ui_language | string | Language of the labels. |
settings.min_rating | number | Lowest rating shown. 0 means all. |
settings.limit | number | Highest number of reviews, 1 to 50. |
settings.sort | string | featured, recent or highest. |
settings.show_* | boolean | Which parts are visible: summary, platform logos, dates, titles, verified badge, replies. |
settings.header_text | string or null | Heading above the widget. |
settings.cta_label, settings.cta_url | string or null | Optional button. |
| Other settings | Layout details such as grid_columns, border_radius and the popup position. See the sample. |
summary
| Field | Type | Meaning |
|---|---|---|
average | number | Average rating on a scale of 1 to 5, one decimal. |
count | number | Number of reviews the average is based on. |
distribution | object | Number of reviews per star, keys "5" down to "1". |
providers | array | Per review source: provider, label, logo, count and average. Largest source first. |
reviews[]
| Field | Type | Meaning |
|---|---|---|
id | number | Identifier of the review within Shopreviews. |
provider | string | Source, such as google, trustpilot or kiyoh. A source the shop made itself is custom- followed by a number; its name and icon are in the next two fields. |
provider_label, provider_logo | string | Name and logo URL of the source. The logo can be null. |
author | string or null | Name as shown at the source. Null means anonymous. |
rating | number | 1 to 5, one decimal. |
title | string or null | Title, when the source has one. |
body | string or null | Review text in its original language. |
language | string | Language code of the text. |
date | string | Date of the review, ISO 8601. |
verified | boolean | True when the source marks the review as verified. |
reply | string or null | Reply of the shop. |
product_sku, product_name | string or null | Set for product reviews. |
The document never contains e-mail addresses, order data or other private customer data.
7. Updates and caching
- A change in your account (a setting, a new review, another plan) rewrites the file within seconds.
- Our CDN and browsers may keep a copy for up to 5 minutes, so allow that long before a change is visible everywhere.
- All files are also rewritten once a night.
- If you read the file on your server, cache it for a few minutes. There is no need to fetch it on every page view.
8. Rules for your own display
- Show the "Powered by Shopreviews" label with its link when
brandingis true. - Do not change ratings, texts or names.
- Show the source of each review (
provider_label). - When
domainsis present, use the data on those sites only.
9. Versioning
The field v is the version of the format. We may add fields without raising it, so ignore fields you do not know. If we ever remove or rename a field, v goes up and this page says so beforehand.
Questions
Mail [email protected] and include your widget key.