REST API
Realtime
The live "right now" feeds for one of the current team's sites: the online visitor count, a rich profile-resolved visitor feed for a live map, an activity ticker, and a lookup of favicon domains per traffic source. A site is addressed by {siteKey} (UUID or domain). All endpoints require Authorization: Bearer {token}.
Unlike the rest of the reporting API, realtime endpoints take no date range (range/from/to do not apply) — each one reads a fixed live window: [now - 5 minutes, now]. This is independent of the product-wide analytics session duration (config('clickbase.session_duration_minutes'), which only controls session continuity at ingest). The upper now bound keeps a future-dated or clock-skewed event from ever counting as online.
Who counts as online (same rules on the count, visitor markers, and activity feed — they stay in lockstep):
- Non-engagement events only (
event_type = engagementis excluded — a beacon marks a visit that already happened, never someone online right now). paymentevents are excluded (Stripe/manual revenue rows must not create phantom visitors or wipe a pin with(0, 0)coords).- Visitors need a real geolocation: the latest event that carried non-zero
latitude/longitudewins. A later custom event with missing geo does not drop them. Exact(0, 0)(ClickHouse's missing-geo sentinel) never counts. - The online count is uncapped; live visitor markers are capped at the 500 most recently active visitors (the live UI shows "showing X of Y" when the set is larger).
Most of these endpoints still accept the shared dashboard filters as query parameters (country, path, source, etc.) — see the exceptions noted per endpoint below.
Online visitor count
GET /api/sites/{siteKey}/stats/online
The distinct number of visitors currently online — the badge count. Accepts filters.
Response
| Field | Type | Description |
|---|---|---|
online |
int | Distinct geolocated visitors (visitor_id) active in the 5-minute live window. |
Status: 200 OK.
curl "https://clickbase.so/api/sites/example.com/stats/online" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
await fetch('https://clickbase.so/api/sites/example.com/stats/online', {
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests
requests.get(
'https://clickbase.so/api/sites/example.com/stats/online',
headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
{ "online": 7 }
Live visitors
GET /api/sites/{siteKey}/stats/live/visitors
One row per geolocated visitor active in the live window, carrying their last-known location (from the latest event that had real coordinates), path, and device context — the feed behind a live map. Identity resolves through the same profile matching as People, so a visitor renders with the same name/avatar there and here. Capped at the 500 most recently active visitors; the online count stays uncapped. Accepts filters.
Response — visitors, a list of:
| Field | Type | Description |
|---|---|---|
visitor_id |
string | The visitor's tracker-generated id. |
user_id |
string | The identify-call identifier; empty string when not identified. |
is_identified |
bool | Whether user_id is set. |
display_name |
string | Nickname derived from their identity. |
avatar_url |
string | Generated (or, once identified, custom) avatar URL. |
latitude |
float | Last known non-zero latitude. |
longitude |
float | Last known non-zero longitude. |
city |
string | City from the same event as the last known coordinates. |
region |
string | Region from the same event as the last known coordinates. |
country |
string | Country from the same event as the last known coordinates. |
path |
string | Last-hit page path. |
device |
string | Device type of their last event. |
browser |
string | Browser of their last event. |
os |
string | OS of their last event. |
source |
string | Last non-empty traffic source. |
channel |
string | Last non-empty acquisition channel. |
referrer_domain |
string | Last non-empty referrer domain. |
last_seen_at |
string (ISO 8601) | Timestamp of their most recent event in the window. |
session_started_at |
string (ISO 8601) | Earliest event of their current session (full history). |
visit_count |
int | Lifetime distinct sessions for this visitor on the site. |
Status: 200 OK.
curl "https://clickbase.so/api/sites/example.com/stats/live/visitors" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
await fetch('https://clickbase.so/api/sites/example.com/stats/live/visitors', {
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests
requests.get(
'https://clickbase.so/api/sites/example.com/stats/live/visitors',
headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
Live activity
GET /api/sites/{siteKey}/stats/live/activity
One row per geolocated online visitor in the live window (their latest non-engagement event), newest first — a lightweight ticker (no profile lookup or Postgres join). Accepts filters.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
int | No | Number of visitors, 1–100. Default 20. |
Response — feed, a list of:
| Field | Type | Description |
|---|---|---|
visitor_id |
string | The visitor's tracker-generated id. |
display_name |
string | Nickname derived from the visitor's identity. |
avatar_url |
string | Generated avatar URL for that identity. |
country |
string | Country from the latest event that had real coordinates. |
path |
string | Latest event's page path. |
event_type |
string | e.g. pageview, event. |
event_name |
string | Custom event name; empty for a plain pageview. |
timestamp |
string (ISO 8601) | When the latest event fired. |
Status: 200 OK.
curl "https://clickbase.so/api/sites/example.com/stats/live/activity?limit=50" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
const params = new URLSearchParams({ limit: '50' });
await fetch(`https://clickbase.so/api/sites/example.com/stats/live/activity?${params}`, {
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests
requests.get(
'https://clickbase.so/api/sites/example.com/stats/live/activity',
params={'limit': 50},
headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
Live source domains
GET /api/sites/{siteKey}/stats/live/source-domains
A map of traffic source → representative favicon domain, for rendering source icons on the live map/ticker. This endpoint takes no filters and no query parameters. Unlike the other realtime endpoints it is deliberately computed over a broad 30-day history rather than the live window (a favicon domain is a stable property of a source, not something that should flicker based on who's online right now), and the result is cached for one hour.
Response — source_domains, an object keyed by source name:
| Field | Type | Description |
|---|---|---|
source_domains.{source} |
string | The representative referrer domain for that source. |
Status: 200 OK.
curl "https://clickbase.so/api/sites/example.com/stats/live/source-domains" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
await fetch('https://clickbase.so/api/sites/example.com/stats/live/source-domains', {
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests
requests.get(
'https://clickbase.so/api/sites/example.com/stats/live/source-domains',
headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
{
"source_domains": {
"X (Twitter)": "x.com",
"Google": "google.com"
}
}