Version 5.2.0

October 10, 2026

If your Schema Item Type is LocalBusiness, Organization or Restaurant and the entries being reviewed are other businesses (a directory or guide), turn on Reviews Are About Other Businesses after updating, or the JSON-LD stops being printed.

Added

  • A Stars Rating field type. Each entry's average rating and review count are now stored, and kept up to date as reviews are approved, rejected, edited, moved, deleted or restored. Add the field to a layout and entries can be sorted by rating (orderBy('rating DESC'), or 'rating.count'), filtered by it (.rating('>= 4'), .rating({average: '>= 4', count: '>= 3'})), shown and sorted in element indexes, and used in condition rules. The summary never re-saves the entry, so moderation doesn't create entry revisions. Existing reviews are summarised by the update migration.
  • craft.stars.reviews.summary(entry) returns the stored summary without the field.
  • php craft stars/ratings/rebuild [--entry-id=…] recomputes the stored summaries.
  • Read-only GraphQL: starsReviews, starsReviewCount, starsComments and starsCommentCount, behind new "Query for approved reviews" and "Query for approved comments" schema components, and starsRating { average count maxRating } on entries. Only approved items on live entries in sections the schema can read are returned. Emails, IPs, user agents and referrers are never exposed.
  • Add to Entry Pages Automatically (injectSchemaOrg, off by default) adds the JSON-LD to the head of each entry page with approved reviews, with no template change, and never twice.
  • schemaOrg(entry, {type, limit}) takes per-call options, and SchemaService::EVENT_DEFINE_SCHEMA lets you change or drop the JSON-LD per entry.
  • Schema Review Limit (schemaReviewLimit, default 10) caps the individual reviews in the JSON-LD.

Changed

  • The JSON-LD now follows Google's review-snippet rules. LocalBusiness, Organization and their subtypes print nothing unless the new Reviews Are About Other Businesses (schemaThirdPartyReviews) setting is on, because Google treats reviews a business hosts about itself as self-serving. Reviews without a reviewer name are left out of the review list (they still count towards the aggregate), and the list holds the newest 10 rather than every review.
  • The JSON-LD's aggregate rating is read from the stored summary.

Version 5.1.2

October 3, 2026

Not released on its own; these changes ship in 5.2.0.

Security

  • The submission URL is the browser's Referer header, which a script can set to anything. It was stored as given and linked in the review or comment sidebar, so a javascript: value ran in a moderator's session when clicked. Only http(s) URLs are stored now, and anything else already stored is shown as plain text.
  • craft.stars.reviews.schemaOrg() now escapes <, >, & and quotes in the JSON-LD, so review text can't close the <script> tag and run its own.
  • Reviews and comments can only be posted against a live entry. Before, any element id was accepted: an unpublished entry, a user, an asset.
  • A reply has to go under an approved comment on the same entry. Before, it could hang off a comment on another entry, or one still in moderation, and that comment's author was emailed.
  • A new hourly budget per address (maxSubmissionsPerHour, default 10) covers reviews and comments across every entry. The per-entry limit allowed one post per entry, so a script could work through the whole site. It also read the stored IP, so it did nothing with IP capture off. The budget lives in the cache, and X-Forwarded-For is only believed once trustedHosts is set.

    Upgrading behind a proxy or CDN? Set Craft's trustedHosts to the proxy's addresses. Otherwise every visitor is charged to the proxy, and the whole site shares one budget. Raise maxSubmissionsPerHour, or set it to 0, if you can't.

Fixed

  • A review posted without a rating was saved with the top mark. It's now refused with "Please choose a rating."

Changed

  • schemaOrg() returns markup, so |raw is no longer needed. Templates that still use it keep working.

Version 5.1.1

September 24, 2026

Fixed

  • The rate limiter compared a cutoff built in the site's timezone against dateCreated values Craft stores in UTC, so the window was off by the site's UTC offset. West of UTC it stretched (a 2-minute limit in New York lasted about four hours, blocking readers from replying twice in a conversation); east of UTC the cutoff landed in the future and nothing was ever limited. The cutoff is now built in UTC.
  • A rate-limited submission was rejected with "Your submission was flagged as spam." It now says "You posted here recently. Please wait a little while and try again.", so a real person isn't told they look like a bot.
  • Admin responses saved their date as site-timezone time in a UTC column, so the "Response Date" shown in the CP was off by the site's UTC offset. New responses are stored in UTC; dates saved before this release keep the offset.

Added

  • SpamService::check() returns which spam check failed (one of the FAILURE_* constants) or null. isSpam() still works and now wraps it.

Version 5.1.0

September 17, 2026

Added

  • All Twig variables now live under a single namespaced root: craft.stars. Reviews are at craft.stars.reviews.* and comments at craft.stars.comments.*.

Changed

  • The plugin no longer takes over the top-level craft.comments (or craft.reviews) variable when another plugin has already registered it. comments is a name verbb/comments has used for years, and because both plugins registered it on CraftVariable::EVENT_INIT, whichever ran last won — installing Stars alongside it silently replaced Verbb's API, 500ing its settings screen and any site template calling craft.comments.*. Stars now only claims those names if they're still free. (#4)

Deprecated

  • craft.reviews and craft.comments as top-level variables. They still work where they aren't contested, but will be removed in 6.0.0 — move templates to craft.stars.reviews / craft.stars.comments.

Version 5.0.3

September 7, 2026

Fixed

  • Adding an admin response (or making any other edit) to an existing review or comment in the CP could silently clear its entryId, orphaning it from its entry and dropping it from the frontend. The entry-select field's hidden input round-trips through setAttributes() on every CP save, and an empty submission there was written straight through as null with no validation error. Frontend submission and the bulk moderation actions were never affected — they don't go through this method — which is why only CP edits showed the problem. An empty submission for an existing, already-linked review or comment is now treated as the field being untouched rather than an explicit removal, so its entry link survives. (#3)

Version 5.0.2

August 4, 2026

Fixed

  • Every setting on the settings page rendered a bare warning icon with no text next to it. The "overridden by config" macro returned the whitespace between its own tags when a setting wasn't overridden, and Twig treats that non-empty string as a real warning. Only genuinely overridden settings show a warning now.

Changed

  • Reworked the Review and Comment editor screens. Every field used to be packed into the sidebar, leaving the main body empty. The submission's own content — rating, name, email, review/comment text, pros, cons, and admin response — now renders in the body via an in-code field layout, laid out two-up where it reads better. The sidebar keeps just what's about the submission: its moderation status and the entry it belongs to, above the existing metadata.
  • Validation errors now appear inline on the field that caused them, instead of only in the error banner.
  • A reply's parent comment is now shown in the Comment sidebar as a "Reply To" link.

Version 5.0.1

August 4, 2026

Fixed

  • The Reviews and Comments CP sections rendered their element index as escaped HTML instead of a working index. Both templates now extend Craft's _layouts/elementindex rather than echoing the deprecated _elements/indexcontainer partial through renderTemplate().
  • Frontend review and comment submissions returned a 500 error whenever notifications were enabled. The element saved, but rendering the notification email threw, because the plugin's email templates live in a control-panel-only template root and were being rendered in site template mode. They're now rendered in CP template mode, and a template failure is logged instead of breaking the submission.
  • Review and Comment index columns showed raw values — the entry ID instead of the entry, the rating number instead of stars, and the lowercase status key instead of a labelled status. The custom column rendering was declared as tableAttributeHtml(), which Craft 5 renamed to attributeHtml(), so it was never called.
  • Fixed the frontend form and review display examples in the README, which used a repeat filter that doesn't exist in Twig or Craft.

Known issues

  • Reply notifications only fire when a reply is created with approved status, so with the default defaultStatus of pending they never send. Approving a reply later does not trigger them.

Version 5.0.0

July 19, 2026

First public release on the Craft Plugin Store, for Craft CMS 5. Builds on the initial review system with a full comments system, a submitter blocklist, pluggable captcha, privacy controls, and an automated test suite.

Added

  • Comments — a threaded comment system for entries, as a first-class element alongside reviews:
    • Four-state moderation, CP element index, and bulk actions (shared with reviews via a ModeratedElement base).
    • Threaded replies with a configurable maximum depth (maxCommentDepth); over-deep replies attach at the deepest allowed level.
    • Frontend submission (actions/stars/comments/save), optional login gating (commentsRequireLogin / commentsAllowAnonymous), and auto-filled author details for logged-in users.
    • craft.comments Twig API (tree, forEntry, topLevel, replies, count) and a bundled recursive stars/_comments/thread.twig macro.
    • Email notifications to moderators, plus reply notifications to the parent comment's author.
    • Comment permissions: view / manage / moderate / reply / delete.
  • Blocklist — block submitters by email, IP, or user id. Enforced on both review and comment submission, with a CP management section, a "Block Author" bulk action, and a stars:manageBlocklist permission.
  • Pluggable captcha — reCAPTCHA v3, reCAPTCHA v2, hCaptcha, and Cloudflare Turnstile, selectable per site. Applies to reviews and comments alike. craft.reviews.captcha() / craft.comments.captcha() expose the provider and site key for the frontend widget.
  • Privacy controls — captureIpAddress, captureUserAgent, and captureReferrer settings to independently disable storing each piece of submission metadata (GDPR-style data minimization). All default to on.
  • Reviewer/commenter email addresses are masked in error logs (e.g. a***@example.com).
  • Automated test suite (Codeception + Craft's test framework), runnable via DDEV.

Fixed

  • craft.reviews.averageRating() — and the ratingValue in the schema.org JSON-LD output — returned an incorrect value instead of the true average.
  • The per-IP rate limiter flagged legitimate first-time submissions as spam, rejecting valid reviews whenever rate limiting was enabled (on by default).

Changed

  • Spam rate limiting is context-aware (reviews vs. comments count against their own tables).
  • The legacy enableRecaptcha / recaptcha* settings are superseded by captchaProvider / captcha* but are still honored (mapped to reCAPTCHA v3).
  • New plugin icon.
  • Licensed under the standard Craft License.

Version 1.0.0

February 15, 2026

Added

  • Initial release
  • Review element type with star ratings (1-5 configurable up to 10)
  • Four-state moderation: pending, approved, rejected, spam
  • Pros/cons fields
  • Admin response support
  • Spam protection: honeypot, reCAPTCHA v3, rate limiting, submission time check
  • Schema.org JSON-LD output (Review + AggregateRating)
  • Email notifications on new submissions
  • Twig variable craft.reviews for frontend queries
  • User permissions for view, manage, moderate, respond, delete
  • CP element index with bulk actions (approve, reject, mark as spam)