Get traffic geography
Returns where the store’s visitors were for a named reporting period.
The payload carries the resolved period window, the days of it geography could answer, the country breakdown ranked by visitors (capped at ten with a trailing “(other)” row folding the tail), the nested city breakdown, and the visitor totals the shares divide by.
Unlike the channel split on traffic/sources, the country breakdown is a partition: each visitor resolves to exactly one country, and visitors with no placed visit in the window are reported as unplaced_visitors rather than dropped, so the parts provably sum to the whole. Shares are not renormalised — their gap is the unplaced traffic.
Authorizations
Bearer token authentication
Query Parameters
Named reporting period (default last_30_days). Supported names: today, last_7_days, last_30_days, last_90_days, last_12_months, this_month, last_month. An unsupported name returns 422.
Response
Success
Store-traffic geography for a period — the resolved window, the days of it geography could answer, the ranked country breakdown, and a nested city breakdown carrying its own capture window, wrapped in the standard API response envelope.
The days of the requested period that geography could answer — the requested window intersected with the days this store has carried placed visits. Every count in the payload is taken over this window rather than the requested one.
Null when the two do not meet, which means the period lies entirely before this store began carrying placed visits. Null arrives with an empty countries list and zeroed totals, and is deliberately distinct from an answerable window whose counts are all zero — that means nobody came. Do not coerce one into the other.
The day this store first carried a placed visit (YYYY-MM-DD, UTC), or null when it never has. Reported whether or not the requested period overlaps it, so a client can say when geography began rather than presenting an empty period as an absence of traffic.
Countries ranked by resolved visitors, capped at ten and optionally ending in a single "(other)" row folding the tail.
This is a partition, not an attribution split: each visitor resolves to exactly one country — the country of their most recent placed visit in the window — so the rows are disjoint and Σ(visitors) + unplaced_visitors == total_visitors holds exactly.
The city breakdown, nested rather than listed beside the countries because it answers a different set of days. City capture began after country capture, so this object carries its own capture_start, its own effective_window, and its own total_visitors.
cities.total_visitors will usually differ from the top-level total_visitors, because each counts the visitors of its own window. Both are correct. Divide city shares by cities.total_visitors and never by the top-level one.
Total distinct bot-free visitors over the effective window, placed and unplaced together. The denominator every share divides by.
Visitors with no placed visit in the effective window — counted, not dropped, so the country breakdown provably sums to the whole.
Shares are against total_visitors and are deliberately not renormalised, so Σ(shares) is the placed fraction rather than 1. The gap is this number, and it is meant to stay visible.
The HTTP status code echoed in the response envelope.