=== Grades Reviews ===
Contributors: smartsites
Tags: reviews, testimonials, ratings, woocommerce, review requests
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.6.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Show your Grades.com reviews with a shortcode, widget or block. With WooCommerce, send your Grades.com review request after each completed order.

== Description ==

Grades Reviews reads the public reviews API of [Grades.com](https://www.grades.com/) and prints your customer reviews in your own theme's design. Everything happens on your server: the plugin fetches the reviews, caches them, and writes plain HTML. There is no JavaScript, no iframe and no third-party request from your visitors' browsers.

* `[grades_reviews]` shows a grid or list of reviews, filtered by rating and review site.
* `[grades_rating]` prints "4.8 out of 5 from 1,353 reviews".
* `[grades_showcase showcase="..."]` shows your Review Showcase: a selection of your reviews, picked by rules you set on Grades.com (or `count`, `min_rating`, `topic`, `sites`, `max_age_days`, `language` attributes). Reviews are never shortened, and the block links to all your reviews.
* A classic widget for sidebars (no block editor needed).
* A server-rendered block for block themes (see the FAQ for the editor caveat).
* Optional JSON-LD `aggregateRating` for your LocalBusiness or Organization, printed once in the page head.
* Responses are cached with transients; a failing API never slows the page down for more than 5 seconds and is not retried for 2 minutes.
* Review text and names are escaped, stars carry a text alternative, and a theme can replace the review markup with `grades-reviews/review.php`.

You need a Grades.com account and a publishable key (`gk_pub_...`). Create one in the Grades dashboard under your location's keys.

= WooCommerce review requests (1.6.0) =

With WooCommerce active, **WooCommerce > Grades.com reviews** sends your Grades.com review request to the customer after an order is completed. Off until you switch it on.

* Ask when an order is **Completed** (default) or **Processing**, after a delay you choose (default 7 days), through WooCommerce's Action Scheduler.
* One request per order, and at most one per customer every 90 days by default (Grades.com applies its own limit too and never asks again someone who already left a review after a request).
* At send time, refunded, cancelled or failed orders are skipped; optionally free orders too.
* Customers who opted out with Grades.com are never asked. If your checkout or newsletter plugin stores marketing consent in an order or customer field, name it and the plugin respects it.
* Every customer gets the same request: the plugin never looks at products, order value (beyond the optional free-order switch) or how happy a customer seems, asks for no rating first and offers no reward. That keeps you within Google's review policy and the FTC rule on consumer reviews (16 CFR 465).
* A note on each order (queued, sent, skipped and why), a log of the last 50 events with masked emails, and an optional "Send review request now" order action (off by default).
* Needs a Grades.com Premium plan and a **secret** API key (`gk_live_...`, scopes `reviews:read`, `reviews:write`, `companies:read`), created at https://my.grades.com/connect?connect=woocommerce. The key is stored with autoload off, sent only from your server and never shown again.
* HPOS (custom order tables) compatible; orders are read and written through the WooCommerce order API.

= Shortcode: reviews =

`[grades_reviews limit="6" min_rating="4" sources="google,yelp" sort="best" layout="grid" show_source="1" show_date="1"]`

* `limit` 1-50, default 6
* `min_rating` 1-5, default from Settings
* `sources` comma separated, default from Settings (empty = all)
* `sort` `newest` (default) or `best`
* `layout` `grid` (default) or `list`
* `show_source`, `show_date` `1` or `0`
* `max_chars` characters shown before "Read more", default 280

= Shortcode: rating =

`[grades_rating]` or `[grades_rating sources="google" stars="0"]`

= Theme override =

Create `grades-reviews/review.php` in your theme. It receives `$review` (author, rating, site (the review platform: google, yelp, facebook...), source (the same), source_label, text, excerpt, truncated, date, url, response_text, response_date; all text is plain, escape it when printing) and `$args`.

== Installation ==

1. Upload the `grades-reviews` folder to `/wp-content/plugins/`, or upload the zip under Plugins > Add New > Upload Plugin.
2. Activate the plugin.
3. Go to Settings > Grades Reviews, paste your publishable key and save. The page shows "Connected to ..." when the key works.
4. Add `[grades_reviews]` to a page, or add the "Grades Reviews" widget to a sidebar.
5. Optional, with WooCommerce: open WooCommerce > Grades.com reviews, paste a secret key, pick the business, press Test connection, then switch on review requests.

== Frequently Asked Questions ==

= Which customers get a WooCommerce review request? =

Every customer whose order reaches the status you chose, unless the order was refunded, cancelled or failed by the time the request is due, the customer opted out, your store's consent field says no, or the customer was asked within the cooldown. Nothing depends on what they bought, what they paid or what they might think of you.

= Does Action Scheduler need WP-Cron? =

Action Scheduler runs on WP-Cron and on admin page loads. On a store with little traffic, a real cron job calling wp-cron.php makes the requests go out on time.

= Can I test the WooCommerce connection? =

Yes: Test connection on WooCommerce > Grades.com reviews calls the Grades.com API with your key and shows the user, the business and whether review requests can be sent (plan, postal address, paused).

= Is my key visible on the site? =

No. The plugin sends it in an `X-Grades-Key` request header from your server and never prints it. A publishable key can only read your visible reviews anyway.

= How often are reviews refreshed? =

Every 10 minutes by default (Settings > Grades Reviews > Cache time). "Clear cached reviews" forces a refresh. The Grades API itself updates when your review sources sync.

= Nothing shows up. =

Visitors see nothing when the key is missing or the API is unreachable; administrators see a notice, and the page source contains an HTML comment such as `<!-- grades-reviews: unavailable (http_401) -->`. `http_401` and `http_403` mean a wrong or revoked key, `http_429` means rate limiting, `request_failed` means your server could not reach the API.

= Does the block appear in the editor? =

The block is server-rendered and ships without editor JavaScript. On WordPress versions that support PHP-only blocks it appears in the inserter. On older versions use the core "Shortcode" block with `[grades_reviews]`; the block still renders if it is already in your content or templates.

= Will Google show stars in search for my own reviews? =

Google decides that. Its guidelines treat reviews a business collects about itself as self-serving, and it often ignores them for LocalBusiness and Organization markup. The JSON-LD is valid and harmless, but do not expect rich result stars.

= Can I turn the JSON-LD off? =

Yes, it is off by default. Leave it off if your SEO plugin already outputs a rating for the same business.

== External services ==

This plugin calls the Grades.com public reviews API (`https://app.grades.com/api/v1/public/reviews`, `/public/summary` and `/public/showcase`; the base URL is configurable) from your web server to fetch your reviews and rating summary. It sends your publishable key (header `X-Grades-Key`), the filter values of the shortcode (limit, sort, minimum rating, sources, and the showcase rules: showcase id, count, topic, text length, age, language) and a User-Agent containing the plugin version and your site URL. Nothing about your visitors is sent.

With WooCommerce and the review requests switched on (WooCommerce > Grades.com reviews), the plugin also calls the authenticated Grades.com API v1 (`https://app.grades.com/api/v1`, same configurable base URL) from your web server with your secret key (header `Authorization: Bearer`): `/me`, `/companies` and `/companies/{business}/review-requests/settings` when you save the settings, press Test connection, or open that settings screen more than 10 minutes after the last check, and `POST /companies/{business}/review-requests` once per eligible order, when the request is due. For each order it sends the customer's billing name and billing email, an order reference made of a hash of your site address and the order id, the consent source "woocommerce_order", and the plugin version and site URL in the User-Agent. Grades.com then emails the customer your review request with an unsubscribe link. Nothing is sent for orders while the feature is off. Service: Grades.com, https://www.grades.com/integrations/wordpress. Terms of use: https://www.grades.com/terms. Privacy policy: https://www.grades.com/privacy-policy.

== Changelog ==

= 1.6.2 =
* Fix: when Grades.com cannot be reached, a page no longer waits for every shortcode in turn (a page with four of them took over 20 seconds). The first call waits at most 3 seconds, the others are skipped for 2 minutes, and visitors keep seeing the reviews loaded last time (up to 7 days old). A revoked key still stops the reviews at once. Settings > Grades Reviews says when the saved copy is shown.
* Fix: the "Grades Review Widget" block now shows the widget in the block editor (it was an empty block until you published). Floating widgets (badge, pop-ups, side tab) show a note saying they appear in a corner of the published page.
* Fix: the block settings have plain names ("Lowest rating shown", "Show dates") instead of "MINRATING" and "showDates". The widget block also takes review tags, like the shortcode.
* Fix: the rating pill (`[grades_widget preset="pill"]`) stays inside the sentence it is placed in instead of breaking the paragraph.
* Fix: star ratings read right where the stylesheet does not apply (feeds, reader views, strict security headers): a 3-star review shows three filled and two outline stars.
* Fix: an admin who places a shortcode or block that matches no review now sees why (only admins, never visitors).
* Change: Settings > Grades Reviews links to the page that creates a publishable key, lists every shortcode and block, and says plainly that the widgets carry the publishable key in the page. Pasting a secret key (gk_live_) is refused with a warning that it must never go into a website.

= 1.6.1 =
* Fix: when your review request campaign on Grades.com is paused, WooCommerce > Grades.com reviews now says "Review requests for orders are on, but the campaign on Grades.com is paused: nothing is emailed until you resume it at my.grades.com/review-requests." and each order note says "Grades.com review request created; the campaign is paused, so nothing is emailed until it is resumed." instead of "sent". The screen reads the state from Grades.com again when you open it (at most every 10 minutes) and after every save, and it says "on" only when Grades.com actually emails the requests: when review requests are paused in Grades.com, the plan does not include them, Grades.com cannot email yet or the state cannot be read, it says so instead, and the order note says nothing is emailed until that changes.
* Fix: Yelp reviews no longer show as an empty "Anonymous" card in `[grades_reviews]`, `[grades_showcase]`, the classic widget and the blocks. Grades.com never sends Yelp review text to websites (rating and link only), so these reviews are left out of the cards, as are reviews without any text; they still count in `[grades_rating]` and the JSON-LD rating. The list asks for a few more reviews so it still fills up to your `limit`.
* Fix: `[grades_widget]` with a publishable key limited to other websites no longer shows an empty box. Admins see why ("Grades.com refused this publishable key for this website...") and visitors get nothing visible, like the other shortcodes.
* Fix: `[grades_reviews]` shows reviewer names and review ages the same way as `[grades_showcase]` and the Grades.com widgets ("Jane D.", ages counted in whole days).
* Fix: `[grades_rating]` on its own line stays inside the content column of block themes such as Twenty Twenty-Five.

= 1.6.0 =
* New: WooCommerce review requests. A completed (or processing) order queues your Grades.com review request for the billing email after a delay (default 7 days), with a per-customer cooldown (default 90 days), skips refunded and cancelled orders at send time, respects Grades.com opt-outs and an optional store consent field, and never filters customers by product, order value or sentiment. Order notes, a masked event log, Test connection, a business picker and an optional "send now" action. HPOS compatible.
* New: suggested privacy policy text and a personal data exporter and eraser for the review request data.
* Improved: when reviews can't be loaded, the settings page says why in plain English (revoked key, plan, rate limit, Grades.com outage, connection blocked by the host) and what to do; admins also see the reason under the shortcode, widget or block (visitors never do).
* Fix: the review site label comes from the review platform (Yelp, Google, Facebook...) instead of the internal collector name, so a Yelp review no longer says "Yelp Apify", and Google reviews from every collector get the same `grades-source-google` class. Works with older Grades.com API answers too. Templates get `$review['site']` (the platform; `source` now holds the same value).

= 1.5.0 =
* New: `tags` on `[grades_widget]`, `[grades_reviews]` and `[grades_showcase]`: show only reviews with one of your review tags, e.g. `[grades_widget preset="carousel" tags="service:roofing"]` on a Roofing page. A tag with no reviews shows the widget's empty message.

= 1.4.0 =
* New: `preset="pill"`, a one-line rating pill for a hero or next to a button (`variant="plain"` without a border, `panel="on"` opens a small panel of reviews). Free on a claimed Grades.com listing, with the rating strip.
* New: display options on every widget: `show_grade`, `show_count`, `show_rating`, `show_stars`, `show_rating_word` (Excellent, Great, Good), `show_source_mark`, `rating_decimals` (1 or 2) and `label` (a short caption).

= 1.3.0 =
* New: nine more widget layouts for `[grades_widget]` and the block: `list`, `masonry`, `spotlight`, `summary` (your rating with a bar per review site), `wall` (large reviews that scroll by themselves, for a lobby screen), `video` (video reviews left on Grades.com), and the floating `badge`, `popup` and `tab`, which sit over your page.
* New: `lang="es"` (Spanish), `columns`, `autoplay`, `interval`, `show_dates`, `show_site`, `position` (left, right), `mobile` (pop-ups on phones) and `height` (the wall).

= 1.2.0 =
* New: `[grades_widget preset="strip|carousel|grid"]` and the block "Grades Review Widget": the Grades.com review widgets (a rating strip with your grade, a review carousel or a review grid), light or dark, in your accent colour. They keep themselves up to date. `iframe="1"` for themes that strip scripts.

= 1.1.0 =
* New: `[grades_showcase]` and the block "Grades Review Showcase": a selection of your reviews by rules (a saved showcase from your Grades.com dashboard, or count, minimum rating, topic, sites, text length, age, language). Never shortened, with a link to all your reviews.
* New: the showcase rules on `[grades_reviews]` (`topic`, `showcase`, `min_length`, `max_length`, `max_age_days`, `language`, `seed`) switch it to the showcase.

= 1.0.1 =
* Fix: settings notices (bad key, missing business name) were shown twice.
* Fix: `show_date="0"` now also hides the date of the owner's response.
* Fix: the block preview in the editor is styled (the screen-reader-only "Read more" text was visible).
* Fix: uninstalling also removes the widget settings.

= 1.0.0 =
* First release: settings page, `[grades_reviews]`, `[grades_rating]`, classic widget, server-rendered block, JSON-LD aggregateRating, transient caching.

== Upgrade Notice ==

= 1.6.2 =
Pages no longer slow down when Grades.com cannot be reached (visitors keep the last reviews); the widget block shows in the editor; plain names for the block settings.

= 1.6.1 =
WooCommerce shows whether Grades.com really emails your review requests (paused campaign or paused requests), Yelp reviews no longer appear as empty "Anonymous" cards, and small display fixes.

= 1.6.0 =
Adds WooCommerce review requests (off until you switch them on).

= 1.3.0 =
Adds nine widget layouts, floating widgets and Spanish.

= 1.2.0 =
Adds the review widgets: rating strip, carousel and grid.

= 1.1.0 =
Adds Review Showcase: reviews picked by rules, linked to all your reviews.

= 1.0.1 =
Small fixes found in a manual test on WordPress 7.1.

= 1.0.0 =
First release.
