Reviews

Collect reviews and star ratings on your own site, moderate them in the Control Panel, and show averages and review schema. Verified purchases with Cargo.

1.2.3

October 19th, 2026

Fixed

  • With reCAPTCHA v3, the form still wrote a script inline, which a strict Content-Security-Policy blocks: it's now in /!/reviews/reviews.js with the time check. Needs 1994/reviews-core 1.0.1, installed with it.

1.2.2

October 19th, 2026

Fixed

  • Deleting an entry left its reviews, and their photos, behind. They're now deleted with it (with separate sites, a deleted localisation takes its own site's reviews). Reviews of entries deleted before 1.2.2 are untouched.
  • The "no more emails like this" link in review requests had the customer's email address in it, so it ended up in access logs and analytics. The address is now encrypted; links in emails already sent still work.
  • Every "helpful" vote cleared the entry's statically cached pages. With a queue worker, they're now cleared once for every vote in five minutes. Someone who drops cookies no longer counts as a new voter each time.
  • A photo that passed the upload checks but couldn't be decoded was dropped without a word: the reviewer is now told.
  • Dates in the ready-made list follow the site's locale ("19. listopada 2026." on a Croatian site), with PHP's intl extension. Also as date_long in the tags.
  • A deleted user's reviews show "A customer" in the visitor's language, not the one active when they were deleted (from now on: reviews anonymised before keep the words they were given).
  • Review request and reviewer emails are sent in the language of their site, whatever runs the scheduler or the queue.
  • The form's time check is a script file (/!/reviews/reviews.js), not inline, so it runs under a strict Content-Security-Policy.

1.2.1

October 18th, 2026

Fixed

  • An export previewed under Reviews → Import is kept in storage/framework/reviews-import until it's imported, or for a day. That folder now has its own .gitignore, so the file (people's names and email addresses) can't be committed to your site's repository in the meantime.

1.2.0

October 18th, 2026

Upgrading

  • With the database driver, run php artisan migrate: 1.2 adds four columns to reviews (where a review came from, and whether it counts) and a review_sources table. Existing reviews are your site's own, and count, as before.

Added

  • Import reviews from another platform's export: Yotpo, Judge.me, REVIEWS.io, Shopify Product Reviews, Trustpilot, WooCommerce, Reviews' own, or any CSV or JSON with a rating column. Reviews → Import shows what would be added first; php please reviews:import does the same from the command line. Import and sync.
  • Sync reviews from Feefo, REVIEWS.io, Judge.me, Yotpo and Trustpilot on a schedule: Reviews → Sync, and php please reviews:sync, run hourly by the scheduler. Keys are kept encrypted, beside the reviews.
  • Imported and synced reviews show where they came from, get no helpful votes, and don't count towards the average or schema unless you say so (only Feefo allows it for synced reviews), as Google's guidelines ask.
  • php please reviews:export-all: every review as a CSV that Reviews for Statamic or Craft imports.
  • A new permission, Import and sync reviews.
  • Reviews across sites. On a multi-site install, reviews can be shared (the default, as before: an entry has the same reviews on every site) or separate: each site has its own reviews, average and schema, and someone can review the same entry on each. Under Settings, or sites in config/reviews.php.

Changed

  • Reviews now shares its core with Reviews for Craft: the numbers, stars, names, spam checks, captchas, review schema and the default stylesheet come from the 1994/reviews-core package, installed with it. Nothing changes on your site; the stylesheet is now at vendor/1994/reviews-core/resources/css/reviews.css. Forms drawn before the update (on cached pages, say) still work.
  • A review's site is now the site of the entry it's of. Before, the form recorded every review against the default site, so site="current" only worked there. Reviews written before 1.2 keep the default site: see Moving to separate sites before switching an existing install to Separate.
  • The Reviews field and the Control Panel list can show one site's reviews (?site= on the list); with separate sites, the field shows its own site's.

Deprecated

  • The captcha classes in NineteenNinetyFour\Reviews\Captcha (Turnstile, HCaptcha, Recaptcha, RecaptchaV3, SiteverifyCaptcha): the form uses reviews-core's now. They're kept, working as before, for code that extends them. Custom captchas implementing Contracts\Captcha are unchanged.

1.1.2

October 18th, 2026

Fixed

  • A review's page in the Control Panel shows its photos again: they were left out.

1.1.1

October 16th, 2026

Fixed

  • "Helpful" counts can't go backwards. Saving a review that was loaded before someone voted (a reply, say) no longer puts the old count back, with either driver. The file driver now changes one review at a time, re-reading it from disk, so two requests can't overwrite each other's votes.
  • Averages can't stick at an old value. A page working out an entry's numbers as one of its reviews changed could cache the old numbers for good; each change now starts afresh.
  • Photos move safely on approval. They're copied, the review is saved, and only then are the old copies removed, so a failed save can't leave a photo public or lost, and leaves the review as it was to try again. A photo that can't be written is left where it was.
  • Signed-in reviewers are shown by their account's name, whatever a form sends, as the docs say.
  • The file driver's review-request log is read with a lock, so a request is never sent twice, or to someone who opted out, while the log is being written.

Safety

  • The form no longer reveals who has reviewed what. A guest's second review of an entry from the same email address is thanked as a first would be (and not kept), instead of saying they've already reviewed it. Two arriving at once can't both be kept (with a cache store that supports locks, as Laravel's file, database and Redis stores do).

Docs

  • Guest "helpful" votes are by cookie: one per person as far as that goes without an account.

1.1.0

October 16th, 2026

Added

  • Ready-made reviews ({{ reviews:display }}): a finished section with the average and star breakdown, the reviews (sorting, a rating filter, pages, "helpful" buttons, replies) and the form, in one tag, or in parts (display_summary, display_list, display_form). Works without JavaScript and on statically cached pages; the views can be published and edited.
  • Default styles ({{ reviews:styles }}) that take the site's own font, size and colours, follow a site's dark mode without a setting of their own, with every colour, size and gap a --reviews-* CSS variable. In a cascade layer, so any CSS of the site's own wins. Publish them to edit (--tag=reviews-css), or link to them yourself ({{ reviews:styles_url }}).
  • Review schema in an SEO addon's own schema ({{ reviews:schema_data }}): the rating and reviews as JSON, or as properties that keep the JSON valid with or without reviews, for fields such as SEO Pro's JSON-LD Schema field. Schema::parts() for the same in PHP.
  • The translations can be published (--tag=reviews-translations).

1.0.0

October 16th, 2026

The first release.

Added

  • A review form for any entry ({{ reviews:form }}): an overall rating out of five, optional ratings for criteria you set, a title, the review, and a name and email for guests. Works without JavaScript. Signed-in reviewers can change or delete their review.
  • Who can review: anyone, signed-in users only, and (with Cargo) only customers who bought the product. Only published, live entries in the collections you choose.
  • Moderation in Content → Reviews: pending, approved, rejected and spam, search and filters, bulk actions, editors' notes and a public reply. Publish reviews by signed-in users or verified buyers straight away, if you like. Permissions for viewing, moderating, replying and deleting.
  • The reviews ({{ reviews }}): sorted by newest, oldest, highest, lowest or most helpful; filtered by rating, verified purchases and photos; paginated.
  • The numbers ({{ reviews:summary }}, reviews:average, reviews:count, reviews:stars): the average, count, each star's share and each criterion's average, cached until a review changes.
  • "Was this helpful?" votes, once per person.
  • Review schema ({{ reviews:schema }}): JSON-LD with AggregateRating and the latest reviews, for any schema.org type, and an @id to join your own schema.
  • Photos, off by default: re-saved as JPEGs without their metadata, private until the review is approved, then moved into an asset container.
  • Emails: new reviews to editors; approvals and replies to reviewers. Queued.
  • Cargo: verified purchases, reviews from buyers only, and review request emails a set time after an order, with an opt-out.
  • Storage in flat files (indexed by the Stache) or the database, and reviews:transfer between them.
  • Privacy: reviews:export and reviews:forget; reviews anonymised when their user is deleted.
  • A dashboard widget of reviews waiting, and a Reviews field showing an entry's rating in the Control Panel.
  • Settings in the Control Panel. Every tag works in Antlers and Blade.
  • Events and a PHP API.

Safety

  • Spam: a honeypot, a time trap that works on statically cached pages, a link limit, and rate limits on every form. Optional captchas: Cloudflare Turnstile, hCaptcha, reCAPTCHA v2 and v3, or your own.
  • Everything a reviewer wrote is escaped in templates, the Control Panel and emails, and can't break out of review schema.
  • No IP addresses are kept. Votes and opt-outs are kept as hashes.
  • Redirects stay on your site.
  • Photos are size-checked before they’re opened, so a small file can’t unpack into an image that exhausts memory.
  • Fair reviews: nothing publishes or hides reviews by their rating, and editors can't change a reviewer's words.