=== Testimonials Block – Customer Reviews, Ratings, Badges & Video Testimonials ===
Contributors: bplugins, abuhayat, himur98
Donate link: https://www.buymeacoffee.com/abuhayat
Tags: testimonials, reviews, rating, social proof, video testimonials
Requires at least: 6.5
Tested up to: 7.1
Stable tag: 1.0.5
Requires PHP: 7.4
License: GPLv3 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html

Testimonials Block makes it easy to display customer testimonials and reviews in a professional, responsive layout using the WordPress block editor.

== Description ==

Build beautiful customer testimonials, reviews, ratings, and social proof sections with 40+ modern layouts directly in the WordPress Gutenberg block editor. No coding required.

Testimonials Block is a flexible testimonial plugin for WordPress that helps you showcase customer reviews and build trust with your visitors. Create testimonial grids, sliders, carousels, masonry layouts, review cards, video testimonials, audio testimonials, rating summaries, social proof badges, and more.

Choose from 40+ testimonial and review layouts, customize the design to match your website, and manage your testimonials from one place with the built-in Testimonials Custom Post Type.

[Testimonials](https://bplugins.com/products/b-testimonials-block/) | [Support](https://bplugins.com/support/) | [Demo](https://bblockswp.com/demo/testimonials-all-demos/)

=== Key Features – Free Version ===
- **40+ Testimonial Layouts**: Create testimonial grids, sliders, carousels, masonry layouts, card stacks, speech bubbles, timelines, marquees, quote boxes, and more.

- **Customer Reviews & Ratings**: Showcase customer feedback with reviewer names, photos, designations, review text, and star ratings.

- **Video & Audio Testimonials**: Display video reviews from YouTube, Vimeo, or MP4 files and add audio testimonials with waveform-style players.

- **Social Proof Badges**: Display rating and review badges for Google, Trustpilot, G2, Facebook, Capterra, and verified buyers.

- **Testimonial Form**: Collect customer testimonials directly from your website and review submissions before publishing.

- **Testimonials Custom Post Type**: Manage testimonials from a central dashboard and reuse them across different testimonial layouts.

- **Responsive Design**: Control columns, gaps, and layouts independently for desktop, tablet, and mobile devices.

- **Flexible Styling**: Customize colors, typography, spacing, borders, shadows, images, avatars, and star ratings.

- **Read More Controls**: Limit long reviews with customizable excerpts and expandable Read More / Show Less buttons.

- **Social Proof & Feedback**: Add rating summaries, NPS polls, customer case studies, review accordions, comparison tables, and other trust-building elements.

- **SEO Rich Results**: Automatic Schema.org Review and AggregateRating JSON-LD markup, so Google can show star ratings for your pages. No add-on, no configuration.

- **Ready-made Patterns**: Seven full sections — Wall of Love, SaaS hero, e-commerce social proof, agency results, review trust bar, scrolling marquee and a review collection page — insert complete and ready to rewrite.

- **One-Click Migration**: Bring your testimonials across from Strong Testimonials, Real Testimonials, Site Reviews or WooCommerce product reviews. Nothing in the other plugin is changed or removed. CSV import and export too.

- **Import Google & Facebook Reviews**: Pull your real Google reviews and Facebook recommendations in as testimonials and show them in any of the 40+ layouts. Uses the same credentials the rating badges already use.

- **Category Filter & Search**: Let visitors filter testimonials by category or search them by keyword, without reloading the page.

- **Accessible**: Star ratings, filters, toggles and dialogs are keyboard-operable and announced correctly by screen readers.

- **Spam-Protected Form**: The submission form is guarded by a honeypot, a timing check, a link cap, a per-visitor rate limit and a duplicate check — no CAPTCHA for your customers to fight.

=== How to Use Testimonials – Quick Start Guide ===

Adding customer testimonials to your WordPress website takes only a few steps.

1. Install and activate Testimonials.

2. Open any post or page in the WordPress Block Editor.

3. Click the + button and search for Testimonials.

4. Choose a testimonial layout such as a grid, slider, carousel, or masonry layout.

5. Add your customer reviews and customize the block settings.

6. Adjust the layout, colors, typography, images, ratings, and spacing.

7. Publish the page and your testimonials are ready to display.

You can also manage testimonials centrally with the Testimonials Custom Post Type and use them across different layouts.

=== Use Cases ===
- **Business Websites**: Build trust by displaying customer feedback and success stories.

- **Agency Websites**: Showcase client testimonials, projects, and customer experiences.

- **Product Pages**: Display reviews and ratings near products or services.

- **SaaS Websites**: Highlight customer stories, ratings, and case studies.

- **Ecommerce Stores**: Show customer reviews, verified buyer feedback, and rating summaries.

- **Service Businesses**: Present client testimonials in attractive grids, sliders, or cards.

- **Landing Pages**: Add social proof to help visitors make confident decisions.

- **Portfolio Websites**: Showcase client feedback alongside completed projects.

=== Enjoying Testimonials? ===

If the plugin saved you an afternoon, a [review on WordPress.org](https://wordpress.org/support/plugin/b-testimonials-block/reviews/#new-post) helps the next person find it. It takes a minute, and for a small team it makes a real difference.

== Installation ==

= From WordPress Admin: =
1. Navigate to **Plugins → Add New**.
2. Search for **Testimonials Block**.
3. Click **Install Now** and then **Activate**.

= Manual Zip Upload: =
1. Download the `testimonials.zip` file.
2. In your WordPress admin, go to **Plugins → Add New → Upload Plugin**.
3. Choose the `.zip` file and click **Install Now**.
4. Activate the plugin through the Plugins menu.

== Frequently Asked Questions ==

= Can I move my testimonials over from another plugin? =

Yes. Go to **Testimonials &rsaquo; Import / Export**. Strong Testimonials, Real Testimonials, Site Reviews and WooCommerce product reviews are detected automatically, including when the other plugin is deactivated. Nothing in the other plugin is changed or deleted, so you can try it and change your mind.

= Will importing twice give me duplicates? =

No. Each imported testimonial remembers where it came from, and rows already imported are skipped. Run it again whenever you like to pick up anything new.

= Do the testimonials show up in Google as star ratings? =

The plugin outputs Schema.org Review and AggregateRating JSON-LD automatically, which is what Google reads for rich results. Whether it chooses to show stars is always Google's decision. If another plugin on your site already outputs review markup, turn this one off with `add_filter( 'bpbtb_schema_enabled', '__return_false' );`.

= Is Testimonials Block free to use? =

Yes. Testimonials Block is a free WordPress testimonial plugin with 40+ layouts and blocks for displaying customer testimonials, reviews, ratings, and social proof.

= Can I add testimonials with Gutenberg? =

Yes. Testimonials Block is built for the WordPress Gutenberg block editor. You can add testimonial layouts directly to posts and pages without writing code.

= Can I create a testimonial slider? =

Yes. You can create testimonial sliders, carousels, grids, masonry layouts, and several other testimonial layouts.

= Can I collect testimonials from visitors? =

Yes. The Testimonial Form block allows visitors to submit their feedback from your website. You can review submissions before publishing them.

= Can I manage testimonials from one place? =

Yes. The built-in Testimonials Custom Post Type lets you create and manage testimonials centrally and reuse them across different layouts.

= Can I display video testimonials? =

Yes. You can showcase video testimonials using YouTube, Vimeo, or MP4 videos.

= Can I display customer ratings and review badges? =

Yes. The plugin includes rating summaries and social proof badge blocks for platforms such as Google, Trustpilot, G2, Facebook, and Capterra.

= Does Testimonials Block work with WordPress themes? =

Yes. The plugin is designed to work with standard WordPress themes and block-based site editors.

= Where can I get support? =

You can ask questions through the WordPress.org support forum or visit bPlugins Support.

== Screenshots ==

1. Activate Testimonials from the Plugins screen.
2. Go to Pages -> Add New to start a new page.
3. Search "Testimonials" in the block inserter and add the block.
4. Pick one of the 40+ layouts from the placeholder.
5. Type your reviews and open the sidebar to customise.
6. Open the Testimonial Block Switcher to browse every layout.
7. Switching layouts replaces the block with that layout's own default content.
8. Keep editing your content, then Publish.
9. Centered Cards Grid — Layout panel (arrangement, columns, gaps) and Elements panel (toggle image, name, designation, review text, rating).
10. Centered Cards Grid — Card style (background, corner wash, padding, border, shadow) and Name typography & colour.
11. Video Testimonials — Videos panel (add, reorder, manage entries) and Width & height.
12. Google Reviews Badge — Width, height & alignment, and Badge logo sizing.
13. Default testimonial cards with the Excerpt & Expand feature.
14. Testimonials Slider — interactive carousel with navigation dots.
15. Testimonials List — clean vertical list of reviews.
16. Testimonials Masonry — staggered grid for variable-height cards.
17. Testimonials Marquee — smooth infinite scrolling ticker.
18. Rating Summary — overall score and star rating distribution.
19. Testimonial Stats — key statistics and satisfaction percentages.
20. Trust Badges — security, guarantee and award badges.
21. Client Logos — brand and client logos in a grid or carousel.
22. Video Testimonials — video reviews with lightbox popup playback.
23. Before & After — comparison showcase for results and transformation.
24. Testimonial Form — front-end form for collecting customer reviews.
25. Centered Cards Grid — sleek centered profile and testimonial card grid.
26. Gradient Border Grid — testimonial grid with a gradient card border.
27. Coverflow Carousel — 3D coverflow-style testimonial carousel.
28. Compact Reviews List — space-saving list of short reviews.
29. Avatar Reviews List — reviewer avatars paired with short quotes.
30. Quote Box Showcase — large pull-quote style testimonial display.
31. Speech Bubble Cards — reviews styled as chat speech bubbles.
32. Customer Journey Timeline — reviews laid out along a timeline.
33. Stacked Review Cards — overlapping stacked review cards.
34. Customer Case Study — in-depth case study style testimonial.
35. Google Reviews Badge — official-style Google Business score badge.
36. Trustpilot Score Badge — official-style Trustpilot score badge.
37. G2 Review Badge — official-style G2 review score badge.
38. Floating Review Badge — a floating, fixed-position review badge widget.
39. Star Rating Progress Bars — rating breakdown shown as progress bars.
40. Social Proof Toast — recent-activity popup notifications.
41. Audio Testimonials — voice reviews with a waveform audio player.
42. Feedback & NPS Poll — Net Promoter Score survey widget.
43. Comparison Review Table — side-by-side comparison of reviews.
44. FAQ Review Accordion — reviews presented as an FAQ-style accordion.
45. Hero Testimonial Spotlight — a single large, featured testimonial.
46. Minimalist Reviews Grid — clean, minimal grid of reviews.
47. 3D Flip Perspective Carousel — carousel with a 3D flip transition.
48. Floating Avatar Bubbles — animated floating reviewer avatar bubbles.
49. Facebook Recommendation Badge — official-style Facebook recommendation badge.
50. Capterra Score Badge — official-style Capterra score badge.
51. Verified Buyer Trust Seal — a verified-purchase trust seal badge.
52. Popup Modal Review Trigger — a review shown inside a popup modal.

== External services ==

This plugin's admin screens load two webfonts, Roboto and Lato, from Google Fonts, and the plugin icon shown in its admin header from WordPress.org's own asset host. Both are requested inside wp-admin only, on this plugin's own pages. Neither is used on your public site.

* **bPlugins authorisation service** (`api.bplugins.com`) — contacted **only** when you press "Connect with Facebook" on the Review Sources screen, and never otherwise. It performs the Facebook login on your behalf and returns your Page access token to your server. What is sent is a random single-use key generated by your site; what comes back is stored in your own database. No request is made unless you press the button, and removing the connection stops it entirely. [Privacy Policy](https://bplugins.com/privacy-policy/)
* **Google Fonts** (`fonts.googleapis.com`, `fonts.gstatic.com`) — serves the Roboto and Lato webfonts used by the plugin dashboard, Submissions and Poll screens. The request sends what any web request sends: your IP address, browser and operating system. Nothing about your site, your content or your visitors is sent. [Terms](https://policies.google.com/terms) | [Privacy Policy](https://policies.google.com/privacy)
* **WordPress.org plugin API** (`api.wordpress.org`) — the **Our Plugins** tab of the plugin dashboard asks WordPress.org for the list of plugins published by bPlugins, so it can show their icons, versions and ratings. The request names bPlugins as the author and sends nothing about your site. [Privacy Policy](https://wordpress.org/about/privacy/)
* **WordPress.org plugin assets** (`ps.w.org`) — serves this plugin's own icon image, shown beside the plugin name in its admin header. [Privacy Policy](https://wordpress.org/about/privacy/)
* **Live demo previews** (`bblockswp.com`) — the **Demo & Help** page's Live Demo cards load each layout's preview inside an iframe from bPlugins' own demo hosting, only when you open that page and click a demo. No data about your site is sent. [Privacy Policy](https://bplugins.com/privacy-policy/)

On your public site, the **Video Testimonials** block embeds YouTube or Vimeo only if you enter a YouTube or Vimeo URL yourself, and only after a visitor clicks play. A self-hosted MP4 makes no external request at all. [YouTube Privacy Policy](https://policies.google.com/privacy) | [Vimeo Privacy Policy](https://vimeo.com/privacy)

== Source Code ==

The non-minified source code for this plugin is available on our public repository:
[GitHub Repository](https://github.com/bPlugins/b-testimonials-block)

== Third-Party Libraries ==

This plugin uses the following third-party libraries:

* [Swiper](https://github.com/nolimits4web/Swiper) - MIT License (powers the Testimonials Slider, Coverflow Carousel and 3D Flip Perspective Carousel layouts).
* [react-responsive-masonry](https://github.com/cedricdelpoux/react-responsive-masonry) - MIT License (powers the Testimonials Masonry layout).
* [immer](https://github.com/immerjs/immer) - MIT License (used internally by the block editor sidebar and admin dashboard to update settings state).
* [react-router-dom](https://github.com/remix-run/react-router) - MIT License (routes the plugin's admin dashboard screens: Demo & Help, Submissions, Feedback & NPS Poll).

= bpl-tools =
* Source / GitHub: https://github.com/bPlugins/bpl-tools
* License: GPL-2.0-or-later – https://www.gnu.org/licenses/gpl-2.0.html
* Purpose: Shared utility library providing this plugin's admin dashboard components (Demo & Help, Submissions, Feedback & NPS Poll, Our Plugins) and common Gutenberg editor controls.
* External Services: see the == External services == section above for exactly which requests this plugin makes through it.

== Build Process ==

This plugin uses a build process to generate the production assets (JS/CSS) located in the `build/` directory. The human-readable source code is available in the `src/` directory.

To build the plugin from source:
1. Clone the repository: https://github.com/bPlugins/b-testimonials-block
2. Install dependencies: `npm install`
3. Run the build command: `npm run build`

Build Tools Used: @wordpress/scripts (Webpack, Babel, PostCSS).

== Developers ==

Every testimonial block on a page contributes to one consolidated Schema.org JSON-LD document, printed once in the footer. Placeholder testimonials that have never been edited are excluded, and a testimonial shown twice on the same page is only counted once.

Turn the markup off entirely — for example when an SEO plugin already outputs review markup:

`add_filter( 'bpbtb_schema_enabled', '__return_false' );`

Name the thing being reviewed (defaults to the site name):

`add_filter( 'bpbtb_schema_item_name', function () { return 'My Product'; } );`

Change the schema.org type wrapping the reviews (defaults to `Product`):

`add_filter( 'bpbtb_schema_item_type', function () { return 'Service'; } );`

Cap how many reviews go into the document (defaults to 50):

`add_filter( 'bpbtb_schema_max_reviews', function () { return 20; } );`

Reshape the finished document:

`add_filter( 'bpbtb_schema_data', function ( $data, $reviews ) { return $data; }, 10, 2 );`

Exclude further blocks from contributing reviews:

`add_filter( 'bpbtb_schema_excluded_blocks', function ( $blocks ) { $blocks[] = 'bptmb/testimonials-hero'; return $blocks; } );`

== Changelog ==

= 1.0.5 - 10 September 2026 =
**New**
* **Schema.org structured data.** Every testimonial block now feeds Review and AggregateRating JSON-LD, which is what Google reads to show star ratings in search results. It is on by default and needs no setup.
* One consolidated document per page rather than one per block, so a page carrying a grid and a slider no longer publishes two competing aggregate ratings — which search engines treat as a markup error rather than as two ratings.
* Testimonials read from the Testimonials post type are included, exactly as displayed.
* A testimonial shown by more than one block on the same page is counted once, so repeating a wall of love below the fold does not inflate the review count.
* Blocks whose content is not a review of your own — the Google, Trustpilot, G2, Capterra, Facebook and verified-buyer badges, client logos, trust badges, stat counters, rating bars and the poll — are excluded.
* A block still showing the shipped demo testimonial contributes nothing, so an unfinished page never publishes "John Doe" as a real customer.
* A Rating Summary block carrying a real average and review count declares the page's aggregate rating outright, in preference to averaging whichever testimonials happen to be on screen.
* Six filters for developers — see the Developers section.

**Performance**
* **The editor bundle is 81% smaller — 3.89 MB down to 723 KB.** The icon picker's three icon sets (Font Awesome, Bootstrap and Lucid) come to 3.35 MB of JSON, and they were compiled into the bundle every one of the forty blocks shares. Opening the editor downloaded and parsed all of it before a single block was on the canvas, whether or not anyone went near an icon. They are now fetched on demand, when the Icon panel is actually opened.
* No change to what the picker does or how icons are stored — the same three sets, still saved as inline SVG.

**Block patterns**
* **Seven ready-made sections**, under "Testimonials & Social Proof" in the inserter: Wall of Love, SaaS Hero with Rating, E-commerce Social Proof, Agency Results & Testimonials, Review Platform Trust Bar, Scrolling Testimonial Marquee and Ask for a Review.
* Each arrives as a finished section — heading, layout, spacing and sample testimonials — rather than as a single default block to build out by hand.
* The sample testimonials a pattern brings with it are excluded from the structured data above, so a page inserted and not yet rewritten never publishes an invented customer to Google. They start counting the moment you write your own words over them.

**Every block previews itself in the inserter**
* **Thirty-five of the forty blocks had no preview.** They appeared in the inserter as a name and an icon, which is no way to choose between forty layouts. Hovering a block now shows the layout itself, rendered at a width that suits it.
* Previews carry **three testimonials rather than one**, so a grid reads as a grid, a marquee has something to scroll and a timeline has a sequence. The five blocks that did already preview showed a single card; they show three now as well.
* **The review badges previewed empty.** Their score, review count and description are blank until you fill them in, so Google, Trustpilot, G2, Capterra, Facebook, verified-buyer and the badge widget all previewed as an outline with nothing in it. They now preview with a figure.
* A badge whose rating source is set to Live previews from a typed figure instead, so opening the inserter never depends on a connected account or an outbound request.
* **The Before / After block previewed as a blank box** — both of its images default to an empty URL. It now previews a comparison you can actually drag.
* The star-rating bars previewed at zero on every row, because the per-star counts start empty. They now preview a real distribution.
* Preview avatars and images are **drawn inline rather than fetched**, so the inserter never waits on a network request and never shows a broken image.

**Google & Facebook review import**
* **Your actual Google reviews and Facebook recommendations, imported as testimonials.** The rating badges could already show a live score — "4.8, 312 reviews" — but there was no way to read those reviews. Now there is, and they land in the Testimonials post type so every layout can show them.
* No second set of credentials: it reads whatever was entered on the Review Sources screen for the badges.
* **You choose which Google endpoint to read.** Google has two, and they are not interchangeable. The legacy Place Details endpoint still works for Cloud projects that already had it switched on, but Google froze it on 1 March 2025 and it cannot be enabled on any project created since — so a key made today only gets Places API (New). The import screen offers Automatic (try the old one, fall back to the new one), or either on its own, and tells you in plain words which one actually answered and what the other one said.
* Switching between them re-imports nothing. Both paths produce the same reviews with the same de-duplication keys, so a site that imported under one endpoint and later moves to the other gets no duplicates.

**A broken review platform now says so**
* **A rating badge that cannot reach its platform no longer fails silently.** The badges are built to degrade rather than break — an unreachable platform falls back to the last figure it had, then to the average of your own testimonials, then to placeholder numbers. Good for a visitor; useless for you, because a dead API key looks exactly like a working one from the front of the site.
* An expired Facebook Page token is the case this was built for. The badge carried on showing the Facebook logo, five stars and "Recommended by 1 Customer" — where the 1 was the block's own placeholder item. Nothing was broken and nothing said anything was wrong.
* There is now an admin notice on the plugin's own screens, the Dashboard and the Plugins list, naming the platform and quoting the reason the platform itself gave. Dismissing it is per-error: fix one platform and break another, or have the same platform fail for a new reason, and it comes back.
* And a **Site Health** test, for the screens the notice stays off. Marked "recommended" rather than "critical" — your pages render fine, it is only the accuracy of a number that is affected.
* The wording distinguishes the three cases honestly, because they are not equally bad: showing the platform's own figure from yesterday, showing the rating you typed in as a fallback, and showing a figure worked out from your own site under someone else's logo.
* Neither the notice nor the test ever makes an API call. They read the cached result and nothing else — an admin notice that fetched from Google and Facebook would put two outbound requests on every wp-admin page load.

**Connect Facebook in one click**
* **A Connect with Facebook button on the Review Sources screen.** No Page access token to find, no Graph API Explorer, no Facebook app to register. Log in, choose your Page, done.
* This is the other half of the problem above. Graph API Explorer hands out a **short-lived** token by default, and a long-lived Page token takes three steps nobody should have to know about — a user token with the right permissions, exchanged for a long-lived one, then traded at /me/accounts for the Page's own. A Page token obtained properly does not expire; a pasted one usually dies within hours.
* A connection that has stopped working offers **Reconnect** rather than only Disconnect, so fixing an expired token is one click and not two.
* **Your access token never passes through your browser.** The exchange happens entirely in PHP and the page is told the Page name and nothing else.
* Each login attempt uses a single-use key issued by your own site, tied to the administrator who pressed the button and valid for fifteen minutes. A request carrying anything else is refused before any outbound call is made.
* The plugin ships no Facebook app id and no app secret. The login is handled by the authorisation service bPlugins already runs, at api.bplugins.com — the same one Business Reviews uses. See the Privacy section below.
* Pasting a token by hand still works exactly as before, for anyone who prefers it.
* Google keeps the review in the language the customer wrote it in, rather than the machine translation, when both are returned.
* Facebook recommendations without any written text are skipped — a bare thumbs-up is not a testimonial. Negative recommendations are imported along with the positive ones; quietly keeping only the good ones is how review markup gets penalised.
* Re-importing picks up only what is new, the same as every other source. A "Refresh" button re-reads from the platform rather than the hourly cache.
* **Google returns at most five reviews per listing.** That is a Google limit, not a plugin one — Place Details has no pagination and no API key raises it. The screen says so rather than pretending otherwise.

**Import & export**
* **Testimonials &rsaquo; Import / Export.** One-click migration from **Strong Testimonials**, **Real Testimonials**, **Site Reviews** and **WooCommerce product reviews** — names, job titles, companies, ratings, photos and dates.
* Nothing in the other plugin is changed, removed or deactivated. The import reads; it does not take. If you do not like the result you simply carry on as you were.
* Sources are detected even when the other plugin has been **deactivated**, which is the state most sites are in by the time they come looking for this.
* The screen says how many testimonials each source holds and how many have already come across, so you know whether the button will do anything before you press it.
* Running an import again picks up only what has been added since — nothing is duplicated. The button relabels itself to "Check for new" once a source is fully imported.
* Photos are pointed at rather than re-uploaded, so migrating does not leave two copies of every avatar in the media library.
* **CSV import** matches columns by name: Name, Author, Client or Reviewer all work, as do Review, Text, Testimonial or Feedback, and Rating, Stars or Score. A file with no recognisable name or review column is refused with an explanation rather than half-imported.
* **CSV export** of every testimonial, with a byte-order mark so Excel opens non-Latin names correctly instead of as mojibake.

**Filtering & search**
* **Testimonial categories.** The Testimonials post type now has its own Categories taxonomy, with a column on the admin list.
* **Category filter bar** — a row of buttons above a grid, slider, masonry, list, marquee or timeline that filters the testimonials in place, with no page reload and no request. Switch it on under **Filter & Search** in the block settings.
* **Keyword search** across the name, role, company and review text of the testimonials on the block. HTML in the review body is not searchable, so searching "div" no longer matches everything.
* A block can also be pinned to a single category, in which case the others are never sent to the browser at all.
* Both are off by default, so no existing block changes appearance.
* The filter is a view control, not a content change: structured data still describes every testimonial on the page, not just the ones currently on screen.

**Accessibility**
* **Star ratings are now announced.** The star row was decorative SVG with no text, so a screen reader passed over the most important thing on a testimonial in silence. It is now a single labelled image — "Rated 4.5 out of 5".
* **The Read more / Less toggle** reports whether it is open (`aria-expanded`); it previously announced only a label that changed under the reader.
* **The popup modal is keyboard-operable.** Opening one used to leave the keyboard behind it — Escape did nothing, Tab walked the page underneath, and there was no way out without a mouse. Focus now moves into the dialog, stays inside it, returns where it came from on close, and Escape closes it.
* **The modal's close button has a name.** It was the character "×", which is read as "times" or skipped.
* **Testimonial form labels are tied to their fields.** Each label was a sibling of its input with no `for`, so clicking a label did nothing and every field was announced as unlabelled.
* The NPS poll's score buttons say what they are out of and which is chosen; the card-stack dots say which card is current; the avatar list reports the selected face; the social-proof toast announces itself politely as it rotates rather than appearing in silence.

**Security & privacy**
* **The public submission endpoint is no longer unguarded.** It had only a nonce in front of it — which any visitor can read off the page — so a script could post unlimited testimonials; six in a row were accepted in under a second when this was measured. It is now behind a honeypot, a signed timing check, a link cap, a per-visitor hourly rate limit and a duplicate check. No CAPTCHA: it is the one measure that costs an honest submitter more than a bot.
* **Field lengths are capped.** `post_content` was unbounded, so a single request could write a review of any size. Caps are filterable through `bpbtb_form_field_limits`, and cut on character boundaries so Bangla, Arabic and emoji are not broken in half.
* **Photo uploads are gated on the form that was actually rendered.** The photo field is off by default, but an upload was accepted regardless — meaning any site running the form accepted unauthenticated files into its media library. Uploads now require a form that offered the field, are capped at 2 MB, and are checked to be real images before anything is written to disk.
* **The NPS poll route required no nonce and had no rate limit.** Its vote log is capped at 5,000 entries, which made it worse rather than safer: a flood could push out every genuine vote. It now needs a nonce, is rate-limited, and its log is no longer autoloaded on every page request.
* **The poll no longer records visitors' IP addresses.** One was stored in plain text with every vote and never read by anything — personal data collected for no purpose. Repeat voting is handled by a counter keyed on a salted hash that is never written down.
* Structured data output escapes slashes, so a review containing `</script>` cannot break out of the JSON-LD tag.

**Fixed**
* **Half-star ratings could not be saved.** The rating meta was registered as an integer with `absint()` as its sanitiser, so every fractional rating was silently rounded down on save — 4.5 became 4 — even though the meta box offers 0.1 steps. Ratings are now stored as numbers and clamped to the 0–5 scale, on every path that writes one.

**Housekeeping**
* A one-time notice now asks how the plugin is doing. It waits a week, appears only once a testimonial or a block has actually been saved, shows only on this plugin's own screens and the plugins list, and offers a route to support for anyone who needs help rather than a review. "No thanks" is permanent.
* Uninstalling with "delete all data" enabled now removes that notice's stored state along with everything else.

= 1.0.4 – Controls, Editor Parity & Alignment =
**New controls**
* **Popup:** the Popup Modal Review Trigger's modal was built entirely from inline styles, so no panel could reach it and it always opened white out of a dark card. Overlay colour and blur, panel background, width, padding, radius, the close button, the avatar and every text size are now controls.
* **Poll Style:** typography for the title, description, scale labels and buttons, plus button size, radius, gap, box padding, radius, shadow and the two button text colours — all of which were fixed values in the stylesheet.
* **Badge Score:** score typography and star row size for the six badges that show a rating.
* **FAQ Review Accordion:** corner radius, background, shadow, row gap and the question and answer padding.
* **Trust Badges:** Badge Box, Badge Icon and Badge Text panels — padding, corner radius, shadow, icon size, icon position, gap and typography.
* **Testimonial Form:** field label, placeholder and input styling, plus field name colour and typography. The same input controls were added to the Feedback & NPS Poll.
* **Badge Logo:** a size control for the Google, Capterra, Facebook, Trustpilot and G2 marks. They stay unswappable — they are trademarks — but their size is now yours.
* **Alignment:** the review badges and Social Proof Toast are narrower than their column and always sat against its left edge. They can now be centred or right-aligned.
* **Card:** Corner wash and card hover colour, reaching every card the Card panel paints.
* **Card details:** header strip background, avatar ring and card corner tint.
* **Icon:** Icon Size now applies to a block's built-in artwork, not only to an icon picked from the library.

**Improvements**
* **Gradient Border Grid** now draws the gradient border and star badges its name promises, instead of rendering as the plain grid with an inverted card.
* Trust Badges' Icon panel follows the Badges repeater — one slot per badge, shown one at a time behind a row of chips, with its own Add New Badge button.
* The Speech Bubble tail's colour pickers show the colour actually in use instead of an empty swatch, with a Follow the card again button to hand it back to the Card panel.
* Social Proof Toast ships with three notifications, so the rotation it exists to show is visible the moment it is inserted.
* Evened out control spacing across the inspector panels.

**Fixes**
* Trust Badges' editor preview drew the same blue shield for every badge while the published page drew a shield, a tick and an amber star. Both now draw the same thing.
* Trust Badges' Icon Size reached only one of the block's two rendering paths, and lost to a per-badge value that no longer had a control to clear it.
* Corner wash and card hover opened on the review badges, Social Proof Toast, Star Rating Bars, Avatar Reviews List, Customer Case Study and Comparison Review Table and moved nothing.
* Client Logos restores each logo's colour on hover inside the editor, not only on the published page.
* The Before / After slider now releases from the pointer when the drag ends in the editor.
* Corrected the mislabelled Bars & Tracks control on the Feedback & NPS Poll, which painted the card background.
* Removed the Testimonial Form's duplicate Form Colors panel.

= 1.0.3 – Major Feature Expansion & Security Hardening =
* **New:** Expanded from a single Testimonials block to **40+ modern child block layouts** — including Grids, Sliders, Carousels, Masonry, Marquee Tickers, Speech Bubbles, Timelines, Card Stacks, Floating Avatars, Hero Layouts, Quote Boxes, Popup Modals, Video & Audio Testimonials, and more.
* **New:** Added official-style **Social Proof & Rating Badge** blocks for Google, Trustpilot, G2, Facebook, Capterra, and Verified Buyer seals.
* **New:** Added **Client Logos** grid block to showcase trusted-by brand logos with grayscale hover effects.
* **New:** Added interactive **Before / After** image comparison slider block.
* **New:** Added **Testimonial Form** block for collecting customer reviews directly from the frontend.
* **New:** Added **Customer Submissions Dashboard** (`Testimonials → Submissions`) with approve, reject, and bulk action workflow.
* **New:** Added **Feedback & NPS Poll** admin dashboard for tracking Net Promoter Score responses.
* **New:** Added modern React-based **Demo & Help** admin page under Testimonials menu with first-activation redirect.
* **New:** Added **Block Switcher** — switch between any child block layout instantly from the sidebar without losing content.
* **New:** Added **Star Rating Bars**, **Rating Summary**, **Comparison Table**, **Case Study Card**, **FAQ Accordion**, **Social Proof Toast**, and **Testimonial Stats** blocks.
* **New:** Introduced **Testimonials Custom Post Type (CPT)** for centralized testimonial management with dynamic block sourcing.
* **Improvement:** Full responsive device controls — columns, column gap, and row gap adjustable independently for Desktop, Tablet, and Mobile.
* **Improvement:** Complete card design customization — background, box-shadow, padding, border, and border-radius.
* **Improvement:** Full typography and color controls for reviewer name, designation, review text, and rating icons.
* **Improvement:** Excerpt length control with expandable Read More / Show Less buttons.
* **Fix:** Hardened plugin security — added proper output escaping (`wp_kses_post`), input sanitization (`wp_unslash`, `sanitize_text_field`), and nonce verification across all admin pages and REST API endpoints.
* **Fix:** Resolved WordPress Plugin Check (PCP) compliance — fixed all errors and warnings for internationalization, variable prefixing, and escape output standards.
* **Fix:** Ensured 100% backward compatibility — existing legacy blocks and user data are seamlessly preserved after update.
* **Fix:** Corrected CSS selector scoping in dynamic styles to prevent leaking into parent containers.

= 1.0.0 =
* Initial public release with a single Testimonials block.