Current as of August 21, 2026.This article reflects the public Poolstatis contracts available on its publication date.

Product analytics should link an anonymous visitor to an authenticated user only after the product has explicit evidence that both identifiers belong to the same actor. The link should be scoped, auditable, reversible, and applied when queries run. Historical events should retain the identifier originally sent.

This design preserves pre-signup journeys without pretending that every browser, session, account, or email belongs to the same person. It also lets a team correct a bad identity link without rewriting an event archive.

The practical sequence is:

  1. Assign a persistent, opaque first-party identifier before authentication.
  2. Use the product’s stable internal user ID after authentication.
  3. Create an explicit anonymous-to-identified link at a trusted transition.
  4. Resolve the canonical actor when calculating users, funnels, retention, or experiments.
  5. Preserve the original identifiers for audit, deletion, and debugging.
  6. Return unknown or ambiguous when the available evidence cannot support a stronger identity claim.

What is anonymous-to-identified identity resolution?

Anonymous-to-identified identity resolution connects activity collected before login with the stable product actor created or recovered during authentication.

Suppose a visitor receives anon_7f2a when opening a product. They view documentation, start setup, and then sign in as internal user usr_1842. The product can record this directed relationship:

anon_7f2a -> usr_1842

The anonymous identifier remains on the events that originally contained it. Queries may resolve both raw identifiers to usr_1842 when counting unique actors or reconstructing the journey.

This is different from replacing anon_7f2a in every stored row. A link is an interpretation supported by provenance. Rewriting makes the interpretation look like an original fact.

The distinction becomes important when the link is wrong, the environment changes, a shared browser switches accounts, or a deletion request targets one raw identifier.

Why does identity quality change product metrics?

Unique-user metrics are identity calculations. Funnels, retention, lifecycle analysis, frequency, and experiments also depend on knowing whether two events belong to the same actor.

Identity failureData symptomLikely product mistake
New random ID for every eventUser counts inflate sharplyEngagement appears broader than it is
Session ID used as the user IDReturning users appear newRetention looks lower
One placeholder ID shared by everyoneUsers collapse into one actorFunnels and frequency become meaningless
Anonymous and authenticated IDs never linkedOne journey becomes two usersPre-signup conversion is understated
Two real users linked togetherSeparate histories mergeSegments, retention, and experiments are corrupted
Link crosses environmentsTest and production identities mixProduction decisions use non-production evidence

Google’s current User-ID guidance similarly requires a unique, persistent identifier for each user and warns that assigning the same ID to multiple people skews reporting. It also advises against identifiers containing information that lets a third party determine the user’s identity. Google Analytics User-ID documentation

A chart cannot repair identity after aggregation. The identity contract must exist below the metric.

What identifier should be used before sign-in?

Use an opaque, first-party identifier that persists for the intended anonymous measurement period. It should contain no email address, phone number, account name, route, campaign value, or device fingerprint.

For a browser product, the identifier may be stored in an origin-scoped first-party storage mechanism. The current WHATWG HTML standard states that each site has a separate storage area and that localStorage spans beyond the current session. It also notes that storage can fail or be unavailable when browser policy prevents persistence. WHATWG HTML Living Standard

That gives the identifier useful but limited meaning:

  • It represents one observable browser storage context.
  • It does not prove that one human owns the device.
  • It does not automatically work across browsers or devices.
  • It can disappear when storage is cleared or restricted.
  • It must not be described as permanent.
  • It must not be reconstructed through fingerprinting when unavailable.

A new identifier after storage deletion is a new observable actor until another trusted event links it. Quietly guessing that two anonymous IDs belong to the same person upgrades probability into identity.

For apps or server-side flows, the persistence mechanism will differ. The same rule remains: the identifier must have a documented scope and lifecycle.

What identifier should be used after authentication?

Use the product’s stable internal actor ID.

Good identifiers are:

  • Unique within the declared product scope.
  • Stable across sessions.
  • Independent of editable profile fields.
  • Opaque outside the product.
  • Available consistently to the code that emits events.
  • Different between production and development when environments are isolated.

An internal immutable user UUID usually fits better than an email address. Emails can change, be reassigned, reveal personal information, or represent a shared mailbox. A hashed email is still derived from an email and should not be treated as automatically anonymous or safe.

The GDPR explicitly includes online identifiers among the information that may be associated with a person. An opaque analytics ID should therefore be treated as potentially personal data, with an appropriate purpose, notice, retention policy, access boundary, and deletion process. This article is an engineering design guide, not jurisdiction-specific legal advice. Regulation (EU) 2016/679

Do not use "anonymous", "guest", zero, an empty string, or another shared placeholder as a real actor ID. Shared placeholders merge unrelated activity.

Create the link at a trusted product transition where the application possesses both identifiers.

Typical moments include:

  • Successful account creation.
  • Successful login.
  • Completion of a verified magic-link flow.
  • A server-confirmed session exchange.
  • An authenticated migration from an old internal ID to a new stable ID.

The direction should move from temporary or superseded identity toward the stable actor:

temporary_or_old_id -> stable_actor_id

Do not create a link merely because two events share an IP address, user-agent string, campaign parameter, or similar timestamp. Those values can support diagnostics, but they do not prove identity.

The server is usually the strongest place to authorize the link because it can verify the authenticated account and receive the current anonymous identifier from the trusted product flow. The browser may carry the anonymous value, but it should not have permission to merge arbitrary users.

The link operation should be idempotent. Retrying the same confirmed relationship must not create several competing links.

Why should historical events keep their original identifier?

The identifier sent with an event is part of the original evidence. Replacing it destroys information about what the product knew when the event occurred.

Keeping raw identity provides four advantages.

First, a mistaken link can be revoked. Future queries can separate the actors again without reconstructing old rows from backups.

Second, reviewers can distinguish received evidence from later interpretation. An event containing anon_7f2a remains visibly anonymous at capture time even if later analysis resolves it to usr_1842.

Third, privacy operations can target an exact raw identifier. Expanding every request through the current identity graph may delete more data than requested, especially after an incorrect merge.

Fourth, identity rules can improve without running destructive backfills. The query layer can apply the current reviewed graph while the immutable event layer remains stable.

The cost is that queries must resolve identity consistently. A system that resolves links in funnels but not retention will produce contradictory user counts. Identity resolution belongs in a shared storage or query boundary, not in individual dashboard formulas.

How should query-time identity resolution work?

Query-time resolution follows active directed links until it reaches the canonical actor.

Given:

anon_browser_1 -> temporary_account_9
temporary_account_9 -> user_42

all three raw identifiers can resolve to user_42. The stored events retain their respective raw values.

A safe resolver needs several constraints:

ConstraintWhy it matters
Project scopePrevents identity from leaking between tenants
Environment scopeKeeps development and production separate
One active destination per sourcePrevents contradictory canonical actors
Cycle rejectionPrevents A -> B -> A from having no truthful endpoint
Bounded outputPrevents person views from returning unlimited identifiers or links
Audit historyShows who created or revoked the relationship
Shared query implementationKeeps user counts consistent across analysis types

The resolved actor should be used by unique-actor trends, funnels, retention, lifecycle, stickiness, experiment outcomes, and actor summaries. Raw-event inspection should continue exposing the original identifier.

Revoking a link changes subsequent query results. That is expected: the interpretation has changed. The audit should preserve the previous link and the operator responsible for the correction.

What happens on logout or account switching?

Logout ends the use of the authenticated actor for subsequent anonymous activity. It does not mean that every later browser event should remain attached to the previous account.

A safe client transition is:

  1. Send authenticated events with the stable actor while the authenticated session is valid.
  2. Clear the authenticated identity when logout succeeds.
  3. Rotate or restore an anonymous browser identifier according to the product’s documented policy.
  4. Do not automatically link post-logout anonymous activity back to the former user.
  5. Create a new explicit link only after another trusted login.

Shared devices make this boundary essential. If Alice signs out and Bob uses the same browser, continuing to emit Alice’s stable ID merges two people.

Whether to rotate the anonymous identifier at logout is a product and privacy decision. Rotation reduces accidental account association but creates a new anonymous journey. Reusing the pre-login identifier preserves continuity but can join activity across different users on a shared device. The chosen behavior should be explicit and tested.

How should ambiguous or unknown identity be reported?

Return uncertainty as data.

An unlinked identifier is not necessarily anonymous. It could be a stable authenticated ID, an anonymous browser ID, an imported legacy ID, or incorrect instrumentation. Inferring its class from a prefix such as anon_ is convenient but weak unless the server owns and validates that provenance.

Useful states include:

  • linked: active server-owned links or multiple observed raw IDs establish a canonical population.
  • unknown: no supported evidence establishes a more specific identity state.
  • ambiguous: the graph or imported data contains a contradiction that prevents a reliable conclusion.

A product interface should not relabel unknown as “anonymous user.” That would claim knowledge the system does not have.

Queries should also expose identity coverage: the share of relevant evidence carrying a usable actor identifier. Coverage does not prove that every identifier is correct, but low coverage is a direct blocker for unique-user analysis.

Identity resolution and deletion should not silently use the same expansion rule.

Analytics queries commonly need canonical resolution: several raw IDs may represent one analytical actor. An administrative deletion request may identify only one exact raw ID. Automatically expanding that request through every current and historical link increases the deletion scope.

A safer contract states which operation is occurring:

OperationRecommended identity behavior
Unique-user queryResolve active links
Funnel or retention queryResolve active links consistently
Raw-event debuggingShow original identifier
Link correctionRevoke or replace reviewed link
Exact raw-ID deletionDelete evidence for that raw identifier only
Full person erasureUse a separate, explicitly authorized canonical expansion workflow

The product must document which deletion semantics it supports. A label such as identity_scope: exact_raw_distinct_id makes the boundary reviewable.

What does Poolstatis implement today?

As of August 21, 2026, current Poolstatis Core source implements explicit actor links with these properties:

  • Directed source_distinct_id -> target_distinct_id links.
  • Isolation by project and environment.
  • Active-source conflict detection.
  • Cycle rejection.
  • Revocation instead of destructive removal.
  • Append-only creation and revocation audit.
  • Query-time canonical resolution without rewriting events.
  • Resolved identity in actor-based analytical queries.
  • Bounded canonical people and activity reads.
  • linked, unknown, and ambiguous identity states.
  • Exact raw-identifier event deletion without automatic canonical expansion.
  • MCP tools for creating, listing, and revoking links, plus bounded actor and person reads.

The implementation and limitations are inspectable in the current Poolstatis data-model documentation and identity service.

This review verifies the source tree at that commit. It does not claim that every capability has been independently exercised against the hosted Cloud deployment.

What should an identity implementation checklist include?

Identifier design

  • Authenticated actors use stable internal IDs.
  • Anonymous IDs are opaque and first-party.
  • No shared placeholder represents multiple users.
  • Emails, phone numbers, raw URLs, and fingerprints are not actor IDs.
  • Browser-storage limitations are documented.
  • Project and environment scopes are explicit.
  • The application possesses both identifiers at a trusted transition.
  • The link moves toward the stable actor.
  • The server authorizes the relationship.
  • Repeated requests are idempotent.
  • Conflicting active destinations are rejected.
  • Cycles are rejected.
  • Creation records the responsible operator or credential.

Query correctness

  • Raw events retain their original IDs.
  • Unique users, funnels, retention, lifecycle, and experiments share one resolver.
  • Identity coverage travels with analytical results.
  • Unknown identity remains unknown.
  • Ambiguity blocks confident person-level conclusions.
  • Link changes are visible in the audit trail.

Lifecycle and privacy

  • Logout behavior is defined and tested.
  • Shared-device account switching is tested.
  • Links can be revoked without rewriting events.
  • Retention applies to identity and audit data deliberately.
  • Exact raw-ID deletion and full-person erasure are separate contracts.
  • Public notices accurately describe identifier use.

Identity resolution is not a cosmetic people-page feature. It determines the population behind nearly every actor-based product metric. Preserve raw facts, require explicit links, resolve them consistently, and make uncertainty visible.