Skip to content

How visitors are counted

Every number on every screen rests on one definition. This page is that definition.

When a hit arrives, the collector computes:

sha256( UTC-day | rotating-salt | client-IP | user-agent | site-public-key )

and keeps the first 16 bytes, hex-encoded — a 32-character string. That string is written to the event and the session. The IP address is never stored.

Four consequences follow directly from the inputs:

Input Consequence
UTC day The id changes at midnight UTC. The same person tomorrow is a different visitor.
Rotating salt Even with the same day, IP and user agent, yesterday’s hash cannot be recomputed.
Client IP A person on Wi-Fi and then on mobile data is two visitors. A shared office NAT can make many people one visitor.
User agent A browser update, or switching from Safari to Chrome, produces a new visitor.
Site key The same person on two of your sites is two unrelated ids.

Unique visitors on any screen is count(distinct visitor_id) over the events in the current slice. Read it as distinct browser-days, and it is accurate. Read it as people, and it drifts:

  • Over- counts anyone who changed network or browser mid-period.
  • Over- counts one person across two days as two.
  • Under- counts several people behind one office NAT with the same browser.

Over a single day, it is a close approximation of distinct devices. Over thirty days, it is much nearer to “browser-days” than to “people” — a visitor who comes back every day for a month contributes thirty.

A visit is a run of activity by one visitor with no gap longer than 30 minutes. When a hit arrives, the collector looks for a session for the same site and visitor whose last activity was inside 30 minutes; if it finds one it extends it, otherwise it opens a new one.

A visit carries a rollup:

Field How it moves
pageviews +1 per pageview hit
events +1 per hit of any type
duration_ms += the d on each hit, and each flushed duration
entry_path the path of the first hit, never changed
exit_path rewritten on every hit
is_bounce true while pageviews <= 1
revenue_cents += the amount of each revenue event in the site currency

Because the visitor id rotates at midnight UTC, a visit that starts at 23:50 and continues at 00:10 becomes two visits by two visitors. Everything else — bounce rate, time on page — is computed per visit and is unaffected.

bounce rate = visits with pageviews <= 1 / visits

Custom events, outbound clicks and revenue events do not clear the bounce flag. A one-page visit where somebody signed up is still a one-page visit. If what you want is “visits that did nothing”, filter Sessions with Bounced and not Converted.

When a filter is applied, bounce rate is computed over the sessions the filtered events belong to — which is what makes “bounce rate for /pricing” mean “visits that touched /pricing”, not “visits whose only page was /pricing”.

Two numbers, from the same source.

Time on page is attached to a pageview. It arrives either as the gap measured when the next pageview is sent, or as a duration hit flushed when the tab is hidden. A duration hit is bookkeeping, not an event: the collector adds the milliseconds to the pageview they belong to and to the open session, and never writes a row.

Average visit is sum(session.duration_ms) / visits.

Neither can see time after the last signal. A visitor who reads one page for ten minutes and closes the tab contributes ten minutes only if the visibility flush arrived — which it does in every current browser, but not if the device was killed, the tab crashed, or sendBeacon was blocked by CSP.

A flushed duration is clamped to 0–30 minutes, because a longer gap is a new visit by definition.

views per visit = pageviews / visits

Counted over the filtered slice, so it answers “how many pages did the visits that touched this filter see in total”, not “how many of these pages”.

On the Revenue screen:

Per visitor = revenue / unique visitors in range
Customers = distinct visitor ids that reported an amount in range

Per visitor uses the same filtered visitor count the rest of the screen shows, so a country filter narrows numerator and denominator together. A customer is a visitor id, which in the default mode is a browser-day: the same person buying on two days is two customers.

Screen Effect
Overview Visitors over a long range are browser-days. A 30-day total is not 30-day uniques.
Sessions “Returning” means earlier the same day. The visitor profile only ever shows today’s visits.
Journeys A flow is drawn inside visits, so it is unaffected.
Funnels Steps must happen on the same UTC day. The “Same day” window is the widest one offered, and it is honest.
Retention Visitor-mode retention is near zero past D0 by construction. Use identified mode.
Revenue Customers are visitor ids, so over a long range they are paying browser-days. A revenue event is credited to the visit it fired in, never to an earlier day.