v1.6.4 Latest
New
- Weekly cap is now settable per action in Settings > Points. The limit was already enforced, but there was no field to set it.
- A badge can now require more than one condition. Build a rule from any of eight condition types (points, points in a period, action count, level reached, badge earned, streak, tenure, admin awarded) and require all of them or any of them.
- The four tenure badges and the three site-first badges are now ordinary editable rules. They were awarded by hardcoded engines and the library told you they were manual, so the only way to change what "2-Year Member" meant was to edit PHP.
- When you save a badge rule you can choose to award it to members who already qualify. It is off by default: leave it off and the badge is earned from now on.
- Kudos Moderation can be filtered by giver, by receiver, and by date range, and kudo-trading pairs are now detected across the whole table rather than only the page you are looking at.
- Members decide which of their badges are public. Every earned badge on your own badge board has a Share button, and a badge you have not shared is not visible to anyone else.
- Settings > Modules has a Background features section: the weekly recap email, leaderboard nudges, status retention, community challenges, tenure badges, site-first badges, badge sharing and cohort leagues can each be switched off. Seven of the eight were already enforced in code and had no screen to set them.
- Webhooks can subscribe to the redemption event. The engine fired it and the API accepted it, but the page never rendered a checkbox for it.
- `wp wb-gamification share grandfather` publishes every existing badge in one pass, for owners who deliberately ran an open community, and `wp wb-gamification share reset` makes them private again.
Improve
- Points, badges, levels, and the Hub follow the active theme's colours in both light and dark mode on BuddyX, BuddyX Pro, and Reign.
- Awarding points costs fewer database queries. A badge is only evaluated when something that could actually change its answer has happened, so a "publish 10 posts" badge no longer runs a count every time a member reacts to a comment.
- The Daily Points Trend chart on Analytics has an axis, labels and a baseline, and a quiet day is now visible instead of rounding away to nothing.
- Empty blocks tell a logged-out visitor how to log in instead of only telling them to.
- A member who leaves a page open overnight can still give kudos, redeem a reward or submit an achievement. The security token in the page expires after about a day; it is now refreshed and the action retried once, instead of failing with an error that retrying could not fix.
- Awarding points costs fewer queries on sites with tiered badges. Bronze at 5 comments, Silver at 25 and Gold at 100 each asked the database the same question about the same member on every award; they now ask once.
- Point decay no longer aggregates every member on the site in order to decay a few hundred of them.
- Kudos Moderation's abuse detection is indexed. It scanned every kudos ever given on the site each time a moderator opened the page.
- Community challenges and webhook subscriptions are no longer re-read from the database on every single points award.
Fix
- Deleting a member left all of their gamification data behind for ever: their points, streaks, badges, cohort rows and queued notifications stayed in the database. Those rows also broke the Analytics dashboard, which could report figures such as "6822% streak health" because it counted rows belonging to members who no longer existed. Deleting a member now removes their data, the dashboard is correct on sites that already have orphaned rows, and `wp wb-gamification member purge-orphans` cleans up the rows an earlier version left behind.
- Failed webhook deliveries were never retried. The retry looked up a column that does not exist, the database refused the query, and the job quietly did nothing. Retries now fire, and a subscription you have switched off is still respected.
- The leaderboard could show two different point totals for the same member on the same page: the board row and the "your standing" strip below it read from different places. They now agree.
- Challenges opened and closed on the site's clock on the page but on the database's clock in the engine that awards progress. On a site ahead of UTC a challenge could appear open and award nothing for hours; on a site behind UTC it kept awarding after it had visibly closed.
- The Daily Points Trend chart drew an empty column for days that had points on any site not set to UTC.
- The user status bar rendered on top of the theme's header. It now measures whatever is actually at the top of the page, at any screen size.
- Revoking kudos took back the points but still congratulated the receiver with a "you got kudos" notification for a kudos that no longer existed.
- The welcome notice could not be dismissed. Clicking its X hid it for one page view and it returned on the next, on every plugin page, until you ran the setup wizard. There is now a "No thanks" that means it.
- The redemption confirmation was announced to screen readers as a modal while trapping nothing, and pressing Redeem never moved keyboard focus into it. It is a real dialog now: focus moves in, Escape closes it, and focus returns to the button you pressed.
- Level-up and streak celebrations were announced as modal dialogs a member could not escape. They are announcements, and they are announced as such.
- Granting a staff role the "manage rules" or "view analytics" capability had no effect on the actions and recap endpoints, which still demanded full administrator rights.
- Importing from GamiPress reported success and imported nothing on sites running a version older than 6.9.4, where its points are stored differently. The import now reads whichever shape the site actually has.
- A reward with limited stock became unlimited the moment it sold out, and could then be redeemed without limit. Stock now has three distinct states: empty means unlimited, 0 means sold out, and any positive number is the quantity remaining. Rewards you currently run with a stock of 0 stay unlimited; they are migrated on upgrade.
- The per-member kudos cooldown was never applied on sites in a timezone behind UTC, so members could send kudos to the same person repeatedly. The cooldown is now enforced in every timezone.
- The weekly digest's "this week" window was offset by the site's timezone, so the email could omit recent activity or include activity from the previous week. It now covers the correct seven days on any site.
- The weekly digest was also sent to the wrong people for the same reason: the query that selects recipients used the database clock instead of the site's, so members active near the edge of the window were dropped from the send.
- Challenges opened and closed on the database's clock rather than the site's. On a site ahead of UTC, a challenge scheduled to start at 09:00 stayed shut for hours and members could not join one that was already running; one due to close at midnight kept accepting entries. Start and end times now mean what the clock on the wall says, on the page and in the engine that awards the progress.
- The community-challenge countdown showed the wrong time remaining, and could read "ended" hours before the challenge actually closed.
- Two kudos sent to the same member at the same instant could both bypass the cooldown and record twice. Only one is now recorded.
- Toasts set to a top position rendered behind the theme's header. They now sit below it, and below any other bar pinned to the top of the page.
- Leaderboards now serve from their snapshot table instead of aggregating the full points ledger on every view. The snapshot was disabled by every points award, and a timezone mismatch emptied it at the end of each rebuild on sites ahead of UTC, so leaderboard views fell back to a full-table query.
- The all-time leaderboard reads the materialised member totals rather than summing the whole ledger.
- Members no longer receive duplicate weekly emails. An overdue cron re-fire could start a second send while the first was still queued.
- Notification queue is bounded per member and no longer replays a backlog of stale toasts on every page load.
- Weekly digest, cohort assignment, and status-retention jobs now process members in batches instead of attempting the whole site in a single run.
- Personal-data export is paginated, so an export for a member with a long history no longer exhausts memory.
- Award Points now uses a searchable member picker instead of rendering every member on the site into a dropdown.
- Added database indexes for badge, kudos, submission, redemption, and member-intelligence queries that previously scanned the full table.
- Badge rarity is cached, so public badge pages no longer aggregate the badge table on every request.
- Setup wizard's Coaching Platform and Nonprofit templates no longer seed actions that cannot fire; the wizard now refuses to save an action it does not recognise.
- Licence assets no longer 404 on hosts where the plugin directory is a symlink or the document root does not prefix-match the plugin path.
- Blocks stopped working on themes that navigate without a full page reload. It was worse than nothing on the two forms: pressing Give kudos or Submit achievement made the browser submit the old way and navigate the member off the page, with what they wrote in the address bar.
- A member's own profile visibility toggle, the control that decides whether strangers can see their profile, did nothing at all on those themes.
- A leaderboard that arrived through a client-side navigation showed its figures once and then never updated again.
- The redemption confirmation panel sat on top of the Redeem button and swallowed the click, so the button could not be pressed.
- Deactivating the plugin left a recurring badge job and a half-finished retention job scheduled for ever, firing on a site where the plugin was switched off.
- Uninstalling now removes everything the plugin created: roughly fifty options including the stored licence key, scheduled jobs in all seven of the plugin's job groups rather than only one, and every one of its user meta keys.
- Scheduling the plugin's background jobs no longer trips WordPress's "translation loading was triggered too early" notice.
- Confirm and Cancel in the admin's confirmation dialogs were always in English on a translated site, including the dialog that permanently deletes all member progress.
- Save, Confirm reset and Cancel on the Streaks page were always in English on a translated site.
- `wp wb-gamification scale teardown` deleted real members whose user ID happened to be 1,000,000 or above. It now removes only the members it created, and reports any real accounts it found in that range instead of touching them.
Security
- Anyone could read any member's challenge progress. The public challenges endpoint took a member id and returned that member's progress for it, with nothing checked, so a visitor with no account could walk through the ids and collect it, including for members who had switched their public profile off.
- Anyone could read any member's badges. The badge share card, the OpenBadges credential and the public badge page were each addressed by a badge id and a member id, both of which are guessable, so a visitor could enumerate them and, for a credential badge, have the site issue a signed verifiable credential about a person who had never shared it. Badges are now private until the member shares them.
- Unpublished community challenges could be fetched by id, so the titles of drafts and retired challenges were readable by anyone, even though the list they belong to already hid them.
- A member exercising their right to erasure was not fully erased. The eraser removed data from the tables it knew about, and it did not know about six of them, including queued notifications, cohort membership and redemptions. The personal-data export omitted a member's kudos, cohort history, redemptions and challenge log. Both now cover every table that holds a member's data, and cannot fall behind when a new one is added.
- The Action Scheduler cleanup no longer deletes other plugins' queued work. It previously removed every pending Action Scheduler job older than the retention window, with no ownership check, which could destroy WooCommerce orders and subscription renewals on any site. Cleanup is now fenced to this plugin's own jobs, and queued work is never aged out as routine housekeeping.
- Six of a member's stored settings survived a GDPR erasure, were missing from the data export, and were left behind by uninstall. One of them is a staff member's written note about that person.
Dev
- Staff permissions can be read and set over REST at `GET|PUT /wb-gamification/v1/settings/capabilities` (administrator only).
- New filter `wb_gam_empty_state_{block}` to change what a block says when it has nothing to show.
- `wp wb-gamification scale benchmark` now covers the badge, notification, and streak read paths, and a green run against a seeded dataset is required before a release can be packaged.
- A member publishes or withdraws their own badge over REST at `POST|DELETE /wb-gamification/v1/badges/{badge_id}/share`. There is deliberately no member id in that route: nobody can publish somebody else's badge.
- New actions `wb_gam_badge_shared` and `wb_gam_badge_unshared` fire when a member publishes or withdraws a badge.
- `wb_gam_user_badges` gains a `shared_at` column, added on upgrade.
- `wp wb-gamification scale benchmark` also counts the database queries one points award costs and fails if that number climbs. Every other budget it checks is a timing budget, and a badge asking the same question twenty times is twenty fast queries that no timing budget can see.