ReviewSnippet

Docs

Everything you need to add reviews to your site.

InstallCollect + displayStrict CSPDisplay onlyPer-productJSON formatWhat you controlBrandingWhere your reviews live

Install

Sign in, create a site, and register the domain(s) it runs on. Then paste one line where reviews should appear:

<script src="https://reviewsnippet.us/embed.js" async></script>
<div data-reviews-widget></div>

No key or id goes in the page -- the widget is matched to your site by its domain. A domain belongs to one site, and the widget only renders on (and accepts reviews from) a registered domain. You can put the snippet on more than one page; add a <div data-reviews-widget> for each place you want it to render.

The script also serves from reviews.whitneys.co/embed.js -- identical widget, same reviews. Use that host instead if a strict corporate network blocks newer domains.

Collect + display (API mode)

The default. Visitors submit reviews (star rating + text), protected by an invisible proof-of-work and a honeypot. Each one publishes on arrival, unedited -- there is no approval queue. The widget shows an average, a star breakdown, and every live review.

Add a "Write a review" button anywhere on the page by calling the widget's API from your own button:

<button onclick="ReviewSnippet.write()">Write a review</button>

Only offer the form to your own users

Add data-write="off" and the widget shows the reviews but not its own button -- then render your own, for whoever you like. Logged-in customers, people with an order, members only; your app already knows, and we don't need to.

<script src="https://reviewsnippet.us/embed.js" data-write="off" async></script>
<div data-reviews-widget></div>

<!-- your template decides who ever sees this -->
{% if user.is_authenticated %}
  <button onclick="ReviewSnippet.write()">Write a review</button>
{% endif %}

Be clear-eyed about what this is: it changes who is offered the form, not who is able to post. The endpoint still accepts reviews from your domain, gated by proof-of-work and rate limits, so treat it as a nicer front door rather than a lock. It's a good fit when you'd simply rather not invite the whole internet to write -- not a way to prove a reviewer is a customer.

Strict Content-Security-Policy

The widget is built to run under a hard CSP: no eval, no new Function, no inline event handlers, and no inline styles (it styles itself with adopted stylesheets, so you don't need style-src 'unsafe-inline'). If your site sends a script-src/connect-src without 'unsafe-inline' or 'unsafe-eval', it still works -- you just allow our origin:

script-src  'self' https://reviewsnippet.us https://reviews.whitneys.co ;
connect-src 'self' https://reviews.whitneys.co ;
img-src     'self' https://reviews.whitneys.co ;
worker-src  blob: ;   /* optional -- see below */

script-src is the host you load embed.js from; connect-src and img-src are always reviews.whitneys.co (the widget talks to that API and shows a small logo). worker-src blob: is optional. The spam proof-of-work runs in a Web Worker so it never freezes your page; if your CSP blocks blob workers, the widget quietly does the same work on the main thread instead -- it still submits, you just get one harmless CSP report. Allow worker-src blob: to take the faster path and silence that report.

Per-product / per-page reviews

By default a site has one set of reviews -- about the business overall. To give a single product or page its own reviews and its own average, add data-item:

<!-- one product, one key -->
<script src="https://reviewsnippet.us/embed.js" data-item="sku-4471" async></script>
<div data-reviews-widget></div>

<!-- or scope automatically to the page's URL, on a shared template -->
<script src="https://reviewsnippet.us/embed.js" data-item="auto" async></script>
<div data-reviews-widget></div>

Each item is its own namespace: its reviews, average, and takedown count are shown only on that item, and never pool into the site-level average. "4.6 for the shop" and "4.6 for one product" are different claims; mixing them would make the number meaningless. Leaving off data-item keeps the site-level widget you already had.

Honest limit: this scopes reviews; it does not put star ratings into Google search results. Those need Product structured data rendered in your page's HTML, which ReviewSnippet doesn't emit yet -- and Google penalises sites that get it wrong, so we won't ship that promise until it's safe. Per-item reviews are useful on their own; don't add them expecting SEO stars.

Testimonials (static mode)

Want a wall of quotes you pick yourself? That's a legitimate thing to want, and this is it. Point the same script at a JSON file you host -- no backend, no submissions.

<script src="https://reviewsnippet.us/embed.js"
        data-reviews="/my-reviews.json" async></script>
<div data-reviews-widget></div>

Because the file is yours to edit, the widget calls these testimonials, not reviews, and tells readers they were chosen by you. That label isn't optional -- it's the only thing separating a curated wall from reviews you can't touch, and passing one off as the other would make both worthless. To collect real reviews, use the default (API) mode.

Hide the small "Testimonials via ReviewSnippet" attribution footer with data-branding="off". The testimonials label stays either way.

JSON format (static mode)

Either a bare array of reviews, or an object with a name, theme, and reviews:

{
  "name": "Acme Coffee",
  "theme": { "primary": "#f5a524" },
  "reviews": [
    { "author": "Jane D.", "rating": 5, "body": "Great!", "date": "2026-06-01" }
  ]
}
FieldNotes
authorDisplay name (required)
rating1–5 (required)
bodyReview text (optional)
dateISO date, e.g. 2026-06-01 (optional)
replyYour public response (optional)

What you can and can't do

Sign in at /login -- passwordless, via a one-time email link. Reviews are already live by the time you see them; there is no approval step and no way to add one.

You can: reply publicly to any review, set your accent color and domains, and take a review down by recording one of the stated reasons (spam, personal information, abusive, illegal, provably not a customer). Takedowns are shown to visitors as a count on your widget, and the review is kept as a record rather than deleted.

You can't: delete a review, edit one, hide one you disagree with, or hide the fact that you removed one. Only the review's author can erase it, using the private link they got when they wrote it -- that erases the text, their name, their email, and the stored IP. We can't do it for them, and we can't do it for you.

Branding

Set an accent color per site in Settings to theme the stars and buttons. The small "Reviews by ReviewSnippet" footer is a per-site toggle in the dashboard (and data-branding="off" in static mode).

Where your reviews live

On our servers, not yours -- and that's deliberate. "The site owner can't delete a review" is only worth saying if it's true, and it's true because the database isn't yours to reach. If you ran this yourself you could edit any review with a one-line shell command, and the promise would be worth nothing. The constraint is the product.

What that costs you is a dependency on us; what it buys you is stars a stranger has reason to believe. If you'd rather hold your own data, that's a legitimate call -- use testimonials mode, where the JSON file is yours and the widget says so.

Get your snippet Questions? Contact us