Skip to content

Time ranges & timezones

range is the one parameter every screen understands. Nine values:

range Label Starts Bucket
today Today midnight, site time hour
yesterday Yesterday midnight, site time, minus a day; ends at today’s midnight hour
24h Last 24 hours exactly 24 hours ago hour
7d Last 7 days midnight 6 days ago day
30d Last 30 days midnight 29 days ago day
90d Last 90 days midnight 89 days ago day
12m Last 12 months first of the month, 11 months ago month
week This week most recent Monday, site time day
month This month first of the current month, site time day

30d is the default. Anything unrecognised silently becomes 30d, so ?range=lastyear is not an error — it is thirty days.

Every range except yesterday ends now. 7d therefore covers six full days plus today so far, which is why today’s bar in a 7-day chart is usually short.

Set per site in Settings → General. It decides exactly one thing: where a day, a week and a month begin.

  • today and yesterday start at midnight in the site’s zone.
  • Chart buckets are cut in the site’s zone, then labelled as-is.
  • week starts on Monday (ISO weeks).
  • DST is handled by re-measuring the offset after the day shift, so a range that crosses a clock change does not gain or lose an hour.

Two things the site timezone does not affect:

Thing Zone
The visitor id rotation UTC, always
The billing month and the usage counter UTC, always

So a site in Australia/Sydney sees its dashboard days start at Sydney midnight, while its visitor hashes roll over at 10:00 or 11:00 local. On a 7-day chart that is invisible; on the “Returning” flag in Sessions — which means “earlier the same UTC day” — it is not.

Buckets come back from the database as naive local timestamps that are already in the site’s zone, and are formatted as UTC so the viewer’s own zone cannot shift every label:

Bucket Format Example
hour 24-hour clock 14:00
day short month + day Sep 16
month short month + 2-digit year Sep 26

Empty buckets are zero-filled by a generate_series, so a quiet Sunday is a zero and not a gap in the line.

Every range carries a comparison window of exactly the same length, ending where the current one starts:

previous.start = start − (end − start)
previous.end = start

That is what powers:

  • the delta percentages on the Overview tiles and in the API’s delta object;
  • the Compare toggle on the traffic chart;
  • the previous-period columns on Goals, Events, Funnels and Revenue.

A delta is a percentage change, (now − before) / before × 100, with one sensible exception: a funnel’s completion rate is compared in percentage points, because 4% → 5% is +1pt, not +25%.

When before is zero and now is not, the delta is reported as +100%.

Screen Range picker Notes
Overview, Sessions, Events, Journeys, Goals, Funnels, Retention, Revenue yes
Realtime no Fixed windows: 5 min (online now), 1 min (per-minute rate), 30 min (feed and chart), 1 hour (events tile)
Ask no Uses the range in the URL, unless the question itself names one
Session detail no Shows one visit
Shared dashboard no Reads ?range= but shows no picker
Terminal window
curl -s -H "Authorization: Bearer tk_live_…" \
"https://tracing.tools/api/v1/sites/pk_live_xxxxxxxx/stats?range=7d"

The response echoes the resolved window, so you never have to reconstruct it:

{
"range": {
"key": "7d",
"start": "2026-09-10T00:00:00.000Z",
"end": "2026-09-16T17:41:12.913Z",
"timezone": "Europe/Berlin"
}
}

/series returns unit and timezone alongside the data, so a client knows whether it is holding hours, days or months.