Live Pulse
A real-time WordPress plugin that shows live viewer counts and emoji reactions on any post — built entirely on the native WordPress Interactivity API, with zero jQuery, no external services, and no build step.
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/hafez121/live-pulse/archive/refs/heads/main.zipReadme
Live Pulse
Real-time viewer presence and instant emoji reactions for WordPress — built entirely on the native Interactivity API. No React, no build step, no third-party real-time service.
Live Pulse adds two small, live-feeling features to any post or page:
- 🟢 "X people are viewing this now" — a real-time viewer counter
- ⚡ An instant emoji reaction bar — tap a reaction, see it (and everyone else's) update immediately, no refresh
Why this is different
Most "who's viewing" or "reactions" plugins reach for a full JS framework or a third-party real-time service (Pusher, Firebase, a custom WebSocket server). Live Pulse doesn't use any of that.
It's built on the WordPress Interactivity API, introduced in WordPress 6.5 — a native reactivity runtime that ships with WordPress core itself. Combine that with polling against the standard REST API, and you get live-feeling UI with zero extra infrastructure.
Features
- Live viewer count, powered by self-expiring transients — no custom database table, no cron job
- Emoji reaction bar with one-reaction-per-visitor (tap again to remove, tap another to switch)
- Ships as a Gutenberg block, a
[live_pulse]shortcode, or auto-inserted before/after content - Fully configurable: post types, emoji set, poll interval, presence timeout, minimum viewers before the counter shows
- No visitor accounts — anonymous sessions use a random ID stored only in the browser
- Graceful no-JS fallback — the server-rendered count and totals are visible before JavaScript even loads
- Translation-ready, and cleans up after itself on uninstall if you opt in
How it works
Presence: each visitor's browser pings the server every few seconds (configurable) to say "I'm still here." The server keeps a short-lived list of active sessions per post in a transient and automatically forgets anyone who stops pinging — no cleanup job required.
Reactions: counts are stored in post meta as a simple emoji → count map. Each anonymous session can hold exactly one active reaction per post, remembered for a day, so switching or removing a reaction never inflates the numbers.
Installation
- Download the latest release ZIP (or clone this repo into
wp-content/plugins/live-pulse). - Activate Live Pulse from the Plugins screen.
- Go to Settings → Live Pulse to choose post types, emoji, and display options.
- Place it with the block, the
[live_pulse]shortcode, or leave auto-insert on.
Requires WordPress 6.5+ (for the Interactivity API) and PHP 7.4+.
File structure
live-pulse/
├── live-pulse.php Plugin bootstrap
├── uninstall.php Opt-in data cleanup
├── includes/
│ ├── class-live-pulse-settings.php Options + admin settings page
│ ├── class-live-pulse-presence.php Transient-based viewer tracking
│ ├── class-live-pulse-reactions.php Post-meta based reaction counts
│ ├── class-live-pulse-rest.php REST API routes
│ ├── class-live-pulse-display.php Shared render markup, shortcode, auto-insert
│ └── class-live-pulse-block.php Gutenberg block registration
├── blocks/live-pulse/
│ ├── block.json
│ ├── render.php Dynamic block render (reuses shared markup)
│ └── index.js Editor script (plain JS, no build step)
└── assets/
├── js/view.js Interactivity API store (presence + reactions)
└── css/ Frontend + admin styles
Why no build step?
Everything here is written to run as-is: no npm install, no webpack, no @wordpress/scripts. That's a deliberate choice — it keeps the codebase approachable to read end-to-end, and it means the Interactivity API's own runtime (already loaded by WordPress core for other blocks) is the only "framework" involved.
Known issues
- Reactions can intermittently fail to save on some shared hosts. During testing on a free host (InfinityFree), reaction clicks sometimes don't reach the REST endpoint at all, with no console error. Presence tracking (the viewer counter) works reliably in the same environment. Suspected causes: aggressive edge caching/proxying of
POSTrequests to/wp-json/on some free hosts, or a stale service worker/browser cache. Not yet reproduced on standard hosting — issue reports and PRs welcome. - Presence "leaves" are timeout-based, not instant. Closing a tab doesn't immediately decrement the viewer count — it expires naturally after the configured presence timeout (default 30s). This is a deliberate trade-off: an instant leave via
navigator.sendBeaconcan't reliably carry the REST nonce needed to authenticate the request.
Contributing
Issues and pull requests are welcome. A few ideas for a v2, if you'd like to help:
- Poll-based reactions on comments, not just posts
- A lightweight admin dashboard showing historical peak viewers
- An opt-in "who reacted" avatar stack for logged-in users
License
GPLv2 or later — see LICENSE.
Author
Built by Hafez Fandy — LinkedIn.