Skip to main content

Analytics

Breakdowns

A ranked list for any dimension — pages, countries, referrers, goals.

GET/sites/{siteId}/breakdowns/{dimension}
Breakdown
curl --request GET \
  --url 'https://truestat.io/api/v1/sites/{siteId}/breakdowns/{dimension}' \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "label": "US",
      "views": 412,
      "visitors": 206
    },
    {
      "label": "IN",
      "views": 190,
      "visitors": 136
    }
  ],
  "meta": {
    "page": {
      "limit": 100,
      "offset": 0,
      "has_more": true
    },
    "range": {
      "to": "2026-09-16T13:40:00.000Z",
      "tz": "UTC",
      "from": "2026-08-17T13:40:00.000Z",
      "clamped": false
    },
    "site_id": "6fed8980-a119-4a9c-a4d4-53e448ef9f9e"
  }
}

One endpoint, sixteen dimensions. The dimension is a path segment.

The dimensions

GroupValues
Pagespath · entry_path · exit_link · file_download · hostname
Sourcereferrer · channel · utm_campaign · utm_term
Placecountry · region · city
Systembrowser · os · device
Conversiongoal

An unknown dimension is a 400 that lists the valid ones, rather than an empty result that reads like "no data".

goal covers both kinds of goal

A conversion reaches TrueStat two ways, and this dimension returns them in one ranked list — the same list the dashboard's card shows:

  • Sent goals, recorded as events by the script or POST /goals

  • Rule-based goals, defined by a URL and evaluated when you read the report

You cannot tell them apart from a row, and for ranking purposes you do not need to. What matters is that adding a rule changes this breakdown for past windows too, because the rule is applied at read time rather than recorded at visit time.

Every row has the same shape

{ "label": "US", "visitors": 206, "views": 412 }

label is the value grouped by, whatever the dimension. It is deliberately not named after the dimension — a caller looping over several of them writes one loop rather than a switch.

Fields that mean nothing for a dimension are absent, not null: a country has no click count, an exit link has no revenue. Absent keys disappear from JSON; nulls have to be filtered by every caller.

FieldAppears on
visitorsevery dimension
viewsdimensions that count page views
clicksexit_link, file_download
country_coderegion, city — for the flag
goals, revenue_centsdimensions that carry them

Paging

limit and offset, with meta.page.has_more telling you whether to ask again.

There is no total. Counting every matching row costs as much as the query itself on a wide window, and on live data the number is stale before you read it. has_more is what a pager actually needs.

Filters compose with the dimension

Any filter_* narrows the rows before they are ranked. Breaking down by path with filter_country=DE gives the top pages among German visitors — the same drill-down the dashboard does when you click a row.

Authorizations

Authorizationstringheaderrequired

An API key from Settings → API keys. Scopes available: analytics:read, sites:read, sites:write, settings:read, settings:write, goals:read, goals:write, funnels:read, funnels:write, notes:read, notes:write, alerts:read, alerts:write, team:read, team:write, revenue:read, revenue:write.

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path parameters

siteIdstring (uuid)pathrequired
The site's id, from `GET /sites`. A site that is not yours and a site that does not exist both answer 403, so this cannot be used to discover other people's ids.
dimensionenum<string>pathrequired
What to group by: `path`, `entry_path`, `exit_link`, `file_download`, `hostname`, `referrer`, `channel`, `country`, `region`, `city`, `browser`, `os`, `device`, `utm_campaign`, `utm_term`, `goal`.
options:pathentry_pathexit_linkfile_downloadhostnamereferrerchannelcountryregioncitybrowserosdeviceutm_campaignutm_termgoal

Query parameters

periodenum<string>query
A named window, resolved in `tz`. Cannot be combined with `from`/`to` — a request carrying both is refused rather than guessed at.
options:todayyesterdaylast24hlast7dlast30dlast12mmonthyearall
fromstring (date-time)query
Start of the window, ISO 8601 with an offset. Must be given together with `to`.
tostring (date-time)query
End of the window. Must be given together with `from`.
tzstringquerydefault: UTC
IANA timezone for day boundaries. `period=today&tz=Europe/Istanbul` means the reader's today, not the server's. Defaults to UTC.
botsenum<string>querydefault: excluded
Whether crawler traffic is counted. Excluded by default — the `/ai/*` endpoints report it separately and always include it.
options:excludedincluded
limitintegerquerydefault: 100
Rows per page, 1 to 1000.
offsetintegerquerydefault: 0
Rows to skip.
filter_pathstringquery
Narrow the result to one `path`.
filter_path_patternstringquery
Narrow the result to one `path_pattern`.
filter_hostnamestringquery
Narrow the result to one `hostname`.
filter_entry_pathstringquery
Narrow the result to one `entry_path`.
filter_exit_linkstringquery
Narrow the result to one `exit_link`.
filter_file_downloadstringquery
Narrow the result to one `file_download`.
filter_goalstringquery
Narrow the result to one `goal`.
filter_browserstringquery
Narrow the result to one `browser`.
filter_osstringquery
Narrow the result to one `os`.
filter_devicestringquery
Narrow the result to one `device`.
filter_countrystringquery
Narrow the result to one `country`.
filter_regionstringquery
Narrow the result to one `region`.
filter_citystringquery
Narrow the result to one `city`.
filter_referrerstringquery
Narrow the result to one `referrer`.
filter_channelstringquery
Narrow the result to one `channel`.
filter_utm_sourcestringquery
Narrow the result to one `utm_source`.
filter_utm_mediumstringquery
Narrow the result to one `utm_medium`.
filter_utm_campaignstringquery
Narrow the result to one `utm_campaign`.
filter_gad_campaign_idstringquery
Narrow the result to one `gad_campaign_id`.
filter_utm_termstringquery
Narrow the result to one `utm_term`.
filter_bot_kindstringquery
Narrow the result to one `bot_kind`.

Response

application/json

The answer.

dataunknown
See the example.
metaobject