The whole problem in one line
Cookieless analytics works by deriving a temporary identifier server-side instead of storing one on the device, and rotating it — usually daily — so it cannot be used to follow anyone over time. That rotation is the privacy guarantee. It is also, from the perspective of every metric that counts people, a catastrophe:
A daily-rotating identifier is a new person every midnight. Any metric that counts people, or divides by them, is reading a fresh stranger each day and cannot tell you otherwise.
This is the reason cookieless has historically been the domain of web analytics — pageviews, sessions, referrers — and not product analytics. It is not that product analytics is less privacy-conscious. It is that funnels, cohorts and flows are all built on the one thing rotation is designed to destroy. What follows is what actually happens, metric by metric.
What breaks
Unique users inflate, and the error grows with your window
A visitor who comes back on five separate days produces five different identifiers, and a unique-user count reads that as five people. The distortion is not a fixed percentage — it scales with how many distinct days the average visitor appears on. A daily unique count is fine. A weekly one is modestly wrong. A 30-day one can be wrong by a multiple, and a loyal audience makes it worse, because the more someone comes back the more people they appear to be. The number moves in the direction that looks like growth, which is the worst possible failure mode for a metric nobody is checking.
Per-user averages deflate by the same factor
“Events per user”, “sessions per user”, anything with people in the denominator: the numerator is right and the denominator is inflated, so the average drifts steadily toward one. A tool reporting healthy event volume alongside an engagement average that keeps sagging is often not describing a disengaging audience — it is dividing by a headcount that grows every night.
Funnels leak at every day boundary
A funnel tracks one person across ordered steps. Any funnel whose steps can span a night — signup with an email confirmation, a trial that converts later, a checkout someone sleeps on — sees the returning person as a stranger. They vanish from step two as a drop-off, then reappear at step three as somebody who skipped the beginning. You get an understated conversion rate and a phantom cohort entering mid-funnel, and neither is labelled as an artifact.
Retention collapses to approximately zero
This is the sharpest one. A retention cohort asks whether the people who first appeared on day 0 came back on day 1, day 7, day 30. With rotating identifiers, none of day 0’s identifiers exist on day 1 — so the answer is no, always, by construction. The curve does not degrade or get noisy. It goes flat at zero and stays there no matter what you ship. A metric that returns a confident, precise, always-wrong number is considerably more dangerous than one that returns nothing.
User flows fragment nightly
Path analysis reconstructs the sequence of screens one person moved through. Rotating identifiers cut every journey at midnight, so long or multi-session paths — exactly the ones worth studying — are chopped into disconnected fragments that each look like a short visit.
Top-K by user counts the same person repeatedly
Any “top N” ranked by distinct users — most-visited pages by user, most-triggered events by user — inherits the same inflation, and unevenly. Pages that returning visitors hit repeatedly get over-credited relative to pages people see once, so the ranking itself distorts, not just the magnitudes.
What does not break
It would be easy to conclude that cookieless traffic should be dropped from reporting altogether. That is its own silent wrong answer, and a worse one in some ways, because it under-counts your real traffic while looking authoritative.
- Event totals are exact. A consent-declining visitor’s pageview is still a pageview. Counting events never requires knowing who produced them, so totals, sums, averages, minimums and maximums over event properties are all fully correct on cookieless traffic — and excluding it would make them wrong.
- Session metrics are exact. A session is stitched from activity inside a short inactivity window — 30 minutes is the usual convention — which only ever needs to know that two events arrived close together from the same visitor on the same day. Rotation happens at a boundary sessions do not cross, so session counts, duration and pages-per-session are unaffected.
- Same-day uniques are exact. The identifier is stable for the day it was minted, so a daily active count over cookieless traffic is sound. It is only the multi-day window that inflates.
The rule: split by what the metric counts
Put those together and the correct handling is not a global filter in either direction. It is a split, applied per metric, on a single question — does this number count people, or divide by them?
- Counts or divides by people — unique users, per-user averages, funnels, retention, user flows, user-dimension top-K. Exclude cookieless identifiers. Including them corrupts the answer invisibly.
- Counts events or properties — totals, sums, averages, minimums, maximums. Include cookieless identifiers. Excluding them under-counts real traffic.
- Counts sessions — include, unconditionally. Session metrics never read a person identifier at all, so the question does not arise.
The asymmetry in the failure modes is what makes the default matter. Wrongly excluding a volume metric under-counts visibly — the number is lower than you expected and someone asks why. Wrongly including a people metric over-counts invisibly — the number is higher than reality, which nobody questions. So when a new metric is added and nobody has decided which bucket it belongs in, excluding is the safer wrong answer.
How Pug enforces it
Pug mints cookieless identifiers with a reserved cookieless- prefix, so any part of the system can
recognise one from the value alone without a lookup. That turns the rule above from a convention into something the
query layer can apply directly, and it is applied by default — you do not opt in to correct counting.
The classification is written as an exhaustive switch over every aggregation type rather than a list of the two that exclude. That distinction is not stylistic. The list form fails open: an aggregation added later and not considered would default to “include”, quietly admitting rotating identifiers into a metric that may well count people, with no error raised at any layer. The exhaustive form fails the build instead, so adding a metric without deciding which bucket it belongs in is a compile error rather than a number that is wrong for a quarter before anyone notices. Session metrics are exempt by construction — they never read the identifier column.
The query API carries an include_cookieless flag for the cases where you deliberately want these
identifiers back in — auditing raw volume, say, or reconciling against a web-analytics tool. It defaults to off. In
the events table and live feed, cookieless identifiers render without a profile link, because there is no profile to
open: an ephemeral identifier is not a person and the interface should not suggest it is.
What to do about it
- Read volume from totals and sessions. These are correct across 100% of your traffic — better coverage than any consent-gated tool gives you, with nothing stored on the device.
- Treat people-metrics as consented-only. Your funnel and retention numbers describe the population that opted in. That is a real limitation, but a known one, which beats a number that silently blends two incompatible populations.
- Never compare uniques across window lengths. If a tool blends cookieless identifiers into uniques, a 30-day count is inflated relative to a 7-day count by an amount that depends on your own return behaviour, so the ratio between them is meaningless.
- Ask any vendor which bucket they use. “Cookieless” tells you nothing about whether rotating identifiers reach the unique-user number. If the answer is vague, assume they are counted, and treat the headline figure as an upper bound.
- Design your consent prompt for the metrics you actually need. If retention drives your roadmap, that is the argument for asking — and for asking well. See GDPR compliance for analytics for what a valid ask requires.
Cookieless is not a lesser form of measurement. It is an honest one with a specific, knowable boundary: it tells you what happened, reliably and completely, and it cannot tell you who kept coming back. Tools that appear to do both are usually not rotating their identifiers, which is a different trade-off entirely and one worth making deliberately.