Reports & breakdowns
The aggregate endpoints — headline numbers, traffic over time, per-page performance, and any dimension you want to group by. Every one of them takes the same window parameters.
The window
| Name | Type | Required | Description |
|---|---|---|---|
| site | string | No | Site id or site key. Optional when the key is scoped to one site. |
| days | integer | No | Window length ending now. 1–400, default 30. |
| from / to | ISO instant | No | An explicit window, instead of days. Capped at 400 days — an unbounded window is a table scan. |
| include_bots | 0 | 1 | No | Include sessions flagged as automated. Excluded by default. |
| limit | integer | No | Page size on list endpoints. Each endpoint names its own maximum. |
List your sites
GET /v1/analytics/sitesThe first call an integration makes: it turns a key into the site ids everything else takes. A key issued for one site returns that one site.
{
"data": [
{
"id": "8f2b…",
"name": "Marketing site",
"domain": "example.com.au",
"status": "active",
"site_key": "hlda_site_xxxx",
"created_at": "2026-08-01T04:12:00.000Z"
}
],
"scopes": ["analytics:read", "analytics:heatmaps"]
}Overview
GET /v1/analytics/overview?days=30{
"data": {
"sessions": 4821,
"visitors": 3907,
"pageviews": 12044,
"bounced_sessions": 1902,
"converted_sessions": 118,
"conversion_value": 284000,
"identified_sessions": 63,
"hot_sessions": 210,
"total_clicks": 9331,
"rage_clicks": 47,
"dead_clicks": 212,
"form_starts": 340,
"form_submits": 118,
"errors": 9,
"total_active_ms": 214880000,
"avg_active_ms": 44572,
"avg_scroll_pct": 61.4,
"avg_intent_score": 28.9,
"p75_lcp_ms": 2140,
"p75_inp_ms": 132,
"p75_cls_x1000": 41,
"first_seen_at": "2026-08-06T…",
"last_seen_at": "2026-09-05T…"
},
"site": { "id": "8f2b…", "name": "Marketing site", "domain": "example.com.au" },
"window": { "from": "…", "to": "…", "includeBots": false }
}cls_x1000 is CLS multiplied by 1000 so it stays an integer; divide by 1000 to compare against the 0.1 threshold.Reading the bounce number
A bounce here is not "one pageview". That definition marks someone who read one long article for four minutes as a failure. A visit counts as bounced only if it stayed on one page, spent under fifteen seconds engaged, scrolled less than halfway, and did nothing — no click, download, search or form.
Timeseries
GET /v1/analytics/timeseries?days=30&bucket=daybucket is day or hour. Buckets are UTC calendar boundaries rather than rolling windows, so two calls a minute apart return the same buckets — which is what makes the result comparable between runs.
{
"data": [
{ "bucket": "2026-09-01T00:00:00.000Z", "sessions": 161, "visitors": 140,
"pageviews": 402, "conversions": 4, "active_ms": 7120000 }
],
"bucket": "day"
}Pages
GET /v1/analytics/pages?days=30&limit=50| Name | Type | Required | Description |
|---|---|---|---|
| path | string | No | Normalised: query stripped, trailing slash gone, lowercased, and long numeric or uuid segments collapsed to :id. |
| pageviews / unique_sessions | integer | No | Views, and how many distinct visits produced them. |
| entries / exits | integer | No | Sessions that started, and ended, on this page. |
| clicks / rage_clicks | integer | No | All click types, and the frustrated subset. |
| avg_dwell_ms / avg_scroll_pct | number | No | Averaged over page exits, so a page still open does not drag them down. |
/product/:id with ten thousand views rather than ten thousand pages with one view each. Pass the normalised form back to the heatmap endpoint.Breakdown
GET /v1/analytics/breakdown?dimension=channel&days=30One endpoint rather than a dozen, because the answer has the same shape for every dimension and only the key changes.
| Name | Type | Required | Description |
|---|---|---|---|
| channel | dimension | No | Acquisition channel. See Marketing inference for how it is decided. |
| source / medium / campaign | dimension | No | UTM parameters, falling back to the referring host for source. |
| referrer | dimension | No | Referring hostname, www stripped. |
| landing_path | dimension | No | Where visits started. |
| country / region / city | dimension | No | Resolved at the edge from the connection. |
| device / browser / os / language | dimension | No | Audience shape. device is the viewport bucket: mobile, tablet or desktop. |
| company | dimension | No | The organisation behind the address, from reverse DNS. The B2B one: how an anonymous visit becomes an account name. |
| intent_band | dimension | No | cold, warm or hot. |
{
"data": [
{ "key": "organic_search", "sessions": 1840, "visitors": 1602, "pageviews": 4210,
"conversions": 44, "conversion_value": 96000, "bounced": 690,
"avg_active_ms": 51200, "avg_intent_score": 31.2 }
],
"dimension": "channel"
}