Media, Publishing & Streaming// diagnostic

The meter resets for anyone who opens a private window

In short

A metered paywall that resets in a private window is behaving exactly as a client-side counter must. The count lives where the reader can delete it, so the only durable fix is to bind counting to a signed-in identity — and that is worth doing when you already need identity for other reasons, not as a response to evasion on its own.

Key takeaways

  • A count stored in the browser is deletable by the browser. Private windows are the visible case, not the whole leak.
  • Bracket the leak before spending on it — a floor and a ceiling are available, an exact number is not.
  • Storage partitioning resets counts for readers doing nothing evasive, whenever the meter script runs in a third-party context.
  • Move counting server-side when identity is already required, not to punish evasion — otherwise you are funding a registration wall out of an anti-fraud budget.

It is not broken. A meter that resets in a private window is device storage behaving the way device storage behaves, and every implementation keeping its count in a cookie or local storage has this property by construction. The useful question is not how to stop it, but how much of your metered traffic actually starts from zero, and whether the fix costs less than the leak.

The instinct — detect the private window, block it, escalate — loses. The evader's next move costs them 4 seconds; the innocent reader you challenge has a next move that costs you a subscriber. Below: the measurement, the 4 mechanisms that produce a fresh count, and the threshold at which identity-bound counting pays.

What share of your metered sessions start from zero

You cannot measure this exactly, and a team insisting on an exact number will spend a quarter not getting one. Anonymous readers with no prior state are indistinguishable from cleared ones, so the honest output is a floor and a ceiling — which is enough to decide.

  1. Log 2 things per metered session: the count at session start, and whether the browser presented first-party state older than the session — a consent choice, a dark-mode preference, a newsletter dismissal.
  2. Classify. Zero count with a consent choice recorded 4 months ago is a returning reader whose meter cookie specifically is gone. Zero count with no prior state at all is unclassifiable — new reader, cleared browser or private window.
  3. The floor is the first group as a share of all metered sessions; the ceiling adds the unclassifiable ones. The gap between them measures how blind your first-party data is.
  4. Split both by browser and by acquisition source. A gap concentrated on 1 browser is usually a partitioning fault; a gap spread evenly is usually behaviour.

The count is somewhere the reader can reach, which was the trade

The largest cause is the design itself. A cookie or a local-storage key costs nothing to run, keeps every article render cacheable at the edge, and works for readers who have never given you an email address. Those are real properties, and the storage decision sets everything else — the full comparison is in where the meter count lives and what it counts.

The cost is that the count is deletable, per device, by anyone who wants it gone. Private browsing is the visible version; the invisible ones are larger — a second device, a work laptop, a browser clearing storage on quit, privacy tooling clearing cookies on a schedule.

The browser partitioned your storage and nobody shipped anything

This leak has nothing to do with evasion, and it is the one most often missed because it looks like reader behaviour. If your meter is a vendor script running in an iframe on a domain that is not yours, its storage is third-party storage — and browsers key third-party state to the top-level site as well as to the resource origin.

Mozilla documents this as state partitioning: localStorage, sessionStorage, IndexedDB, DOM Cache, service workers and shared workers partitioned by top-level site, with cookies dynamically partitioned and unpartitioned access granted only through the Storage Access API. Firefox enabled network partitioning by default from version 85 and dynamic partitioning from version 103. Other engines have equivalents on their own timelines, so confirm each vendor's current documentation rather than assuming parity.

  • Symptom. Counts reset for readers doing nothing unusual, correlated with 1 browser rather than spread evenly.
  • Test. Read the meter's storage key from the top-level document. If your own origin cannot see it, the count lives in a partition you do not control.
  • Fix. Write the count as first-party state from your own domain and let the vendor read it rather than own it. A cookie set by a server response survives more of this than one written by a third-party script.
  • Consequence. Moving the write to your origin puts the meter into your cache story — the tension behind subscribers hitting the wall on popular stories.

Nothing asks who the reader is, so there is nothing to count against

A meter that never requires identity can only count devices. That is a coherent position, and it is where most publishers start, but it means the count is a property of a browser profile rather than of a person — and a person has 3 or 4 browser profiles without trying. Storage hardening does not touch this, because the identifier itself is scoped to the device.

So the honest name for the durable fix is not anti-evasion. It is identity acquisition, with its own success metric and its own owner — the registration wall is not a cheap paywall. Once identity exists the meter is 1 input to a decision rather than the decision, and that decision belongs in one access check every surface can call.

Somebody found the exemption list and posted the recipe

Every meter carries exemptions: search referrals, newsletter clicks, campaign parameters, section fronts, breaking-news overrides. Each is defensible alone. Together they are a documented set of ways to read without being counted, and any of them keyed to a signal a reader can forge — a referrer header, a query parameter — will eventually be forged at scale.

ExemptionWhat the reader has to do to reuse itWorth keeping?
Campaign or newsletter query parameterAppend the parameter to any article URLOnly if exchanged at the edge for a short-lived signed cookie
Search or social referrerSend a referrer headerYes, but expect it to be the main path, not the exception
Section, story age or story typeNothing — it is a property of the articleYes. Not keyed to the reader, so it cannot be harvested
Breaking-news overrideNothing, while it is onYes, if lifting it purges by [surrogate key, not the whole site](/solutions/media-publishing/surrogate-keys-and-purging-one-story-not-the-site)
Exemptions, by how easily a reader reproduces them

The rule in that table: an exemption keyed to a property of the content is safe, and an exemption keyed to a claim the reader makes about themselves is a shared password. If you keep the second kind, do not trust the claim directly — exchange it once at the edge for a signed, short-lived cookie.

Why detecting the private window is a trade you lose

Detection is available. Browsers have historically leaked behavioural differences in private modes, and each technique worked for a while before being closed. That is the problem: the technique has a half-life, the countermeasure does not, and you have signed up to maintain a probe that breaks on a browser release you did not schedule.

Every escalation costs a reader who did nothing and inconveniences an evader for an afternoon. That asymmetry does not improve with better detection. It improves with a reason to sign in.

The second problem is who you catch. A reader who opened a private window has already declined to pay at the current friction. Blocking converts a few, annoys the rest, and hits the wrong group hardest: shared computers, corporate machines with strict privacy policies, students on library terminals. Institutional readers should not be in this conversation at all, because they have a consented grant mechanism — seats, domains and IP ranges for institutional access.

The threshold at which identity-bound counting pays for itself

Server-side metering holds the count against a resolved reader id rather than a device, so it survives private windows, second devices and cleared storage. It also requires a registration step, puts a lookup in the path of every article render, adds a dimension to the cache key, and creates a reader-level behavioural record you now have to govern. 4 costs, none of them a sprint.

What is already trueMove counting server-side?Why
Registration already required to read anythingYes, immediatelyThe expensive part is built; counting against the id is a small addition
An entitlement service already resolves identity per requestYesThe lookup is already in the request path — 1 more field on a call you make anyway
Anonymous reading, measured floor is smallNoYou would fund a registration wall out of an anti-evasion argument, and the wall has a better argument of its own
Anonymous reading, leak concentrated in frequent readersBuild identity first, then count against itFrequent evaders are prospects. The wall is the intervention; the meter follows
A third party pays you against a usage countYes, and audit itAn indefensible count is a commercial problem — see [reporting usage under a machine licensing deal](/solutions/media-publishing/reporting-usage-under-a-machine-licensing-deal)
The decision rule, by what is already true in your estate

The middle rows are where most publishers sit, and the answer there is uncomfortable: the meter is not the project. Identity first, then counting bound to it, then whatever wall model the catalogue justifies — decided on catalogue composition in hard versus metered access for a news archive.

What identity-bound counting still will not stop

It will not stop a second account on a second email address, it will not stop password sharing, and it will not stop a reader consuming the first 3 paragraphs your degraded render serves to search engines. Nor will it tell you whether the reader who stopped at the wall would ever have paid, which is the number the whole argument turns on.

So spend the effort elsewhere. A propensity model ranking readers by likelihood to subscribe beats an evasion detector, because it acts on the population you can convert — ordinary AI agents and automation work. If it will be trained on reader-level behaviour, where it runs is a separate decision, with 4 options in private and on-premises LLM deployment. Whether to own the paywall at all splits by component — build or buy as the estate grows — inside paywalls, subscriptions and entitlements and our media and publishing practice.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

Should we block readers who use private browsing?

No. Detection techniques have a short half-life, break on browser releases you do not control, and catch a group that has already declined to pay at the current friction. The collateral damage lands on shared computers and corporate machines with strict privacy settings. Spend the effort on a reason to sign in instead.

How do we measure how many readers are resetting the meter?

Bracket it rather than counting it. The floor is the share of metered sessions showing a zero count while still presenting older first-party state, such as a consent choice recorded months ago. The ceiling adds sessions with no prior state at all, which could equally be new readers. Measure across 2 full reset cycles, because the days after a reset look identical to a wiped count.

Does server-side metering stop meter evasion completely?

No, it changes what evasion costs. Counting against a signed-in identity survives private windows, cleared storage and second devices, but a second email address creates a second reader. It is worth doing when identity is already required or already resolved per request, and a poor first move when it means building a registration wall purely as an anti-evasion measure.

Why do meter counts reset for readers who are not doing anything unusual?

Usually because the count sits in a third-party context the browser partitions. Browsers key third-party storage to the top-level site as well as the resource origin, so a meter written by a vendor script in an iframe can land in a partition your own code cannot see. Writing the count as first-party state from your own domain removes that class of reset.

  • paywall
  • metering
  • subscriptions
  • diagnostics
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation