Features · Analyse
A live visitor count in the top bar of every page, a Realtime page with views per minute and the latest events as they arrive, and a dashboard that quietly refreshes itself when the data moves — every number still one click from the query behind it.
The dashboard holds one server-sent-events connection per tab. New events wake it; if the stream drops it falls back to polling with exponential backoff, and it pauses while the tab is hidden. No WebSocket server, no extra service.
The live badge and the Realtime page obey the same filters and strict mode as the report you are reading, compiled into the live SQL on the server — so "6 online" never contradicts the table under it.
The latest events are labelled person, crawler or agent. A crawler reading your pricing page shows up in the feed and never in the online count.
The current view re-queries when data moves, throttled, with no loading flash, keeping your scroll position, and never while a dialog or input has your attention.
The evidence
SELECT COUNT(DISTINCT visitor_id) AS value FROM events WHERE site_id = ? AND ts >= ? AND bot_kind = '' AND agent_trust = 'human' -- params: ["acme-3f9c21", now - 5 * 60 * 1000]
Five minutes is the industry convention; the window is in the parameters, not hidden in code. Views per minute (live.per_minute) and the feed (live.feed) open their own queries the same way.
"Online now" means seen in the last five minutes, not a socket held open to each visitor — we do not keep a connection to your visitors' browsers. The feed covers the last 30 minutes, not history; the Sessions page is for that. Streams are per signed-in user and capped, and rotate every five minutes.