Analytics · 11 min read · 2026-08-08
Identity Resolution: Anonymous-to-Known User Stitching
A prospect reads your pricing page, comes back twice over a week, then signs up and activates. In your analytics that single person can appear as three different users — and the exact moment you care about most, the jump from anonymous visitor to paying account, is where the timeline snaps in two. Identity resolution is the plumbing that keeps that one person as one person. Get it right and your funnel from first touch to first value is continuous; get it wrong and every metric downstream of signup is quietly inflated or corrupted.
This is a foundational concept in product analytics, and it is the difference between a tool that can answer "which marketing source produced this paying customer" and one that cannot. This guide explains what identity resolution is, how anonymous-to-known stitching actually works under the hood, the three places it silently breaks, and how to instrument it so your SaaS journey stays whole from the first pageview to the tenth renewal.
The core problem: one human, many identifiers
Identity resolution exists because a single person accumulates a pile of different identifiers over their relationship with you, and none of them is the same as the others. Before they sign up they are an anonymous device or cookie ID. After they sign up they are a user ID in your database. They also have an email, possibly a CRM lead record, maybe a second device, and in B2B a company they belong to. As one identity-resolution primer puts it, stitching "connects multiple identifiers — device IDs, email addresses, cookies, CRM records, user IDs — belonging to the same individual into a unified profile" (Saber). The job of identity resolution is to collapse that pile back into one continuous person.
The reason this matters more in SaaS than in a content site is that the most valuable events happen on both sides of the identity boundary. Acquisition, landing-page behavior, and signup intent are anonymous; activation, retention, and expansion are known. If those two halves never join, you can measure each in isolation but never connect them — you cannot say which acquisition channel drives activation, which pre-signup behavior predicts retention, or what a real end-to-end funnel conversion rate is. The join is the whole point, and it is precisely the join that is fragile.
How the identify call actually works
Anonymous-to-known stitching hinges on a single mechanism: the identify call. When a new visitor arrives, your analytics SDK mints a random anonymous ID and stamps it on every event they fire while logged out. The moment they reveal their identity — logging in, completing signup, or clicking a tracked link — your code calls identify(userId) with a stable internal ID. The analytics backend then merges the anonymous ID into that user ID and retroactively reassigns the prior anonymous events to the now-known user. Heap describes the trigger plainly: resolution happens "when the user takes an action that reveals their identity — logging in, submitting a form" and the platform executes an identify call linking the user ID to the previously assigned anonymous ID (Heap).
The subtlety is that the identify call must fire on every authenticated session, not just at the moment of signup. A user who signs up on their laptop and later logs in on their phone starts with a fresh anonymous ID on the phone; only a phone-side identify call with the same user ID stitches that device into their existing profile. This is why "identify on signup only" is a classic under-instrumentation: it stitches the very first session and orphans every subsequent device and cleared-cookie return. The rule is to call identify on every page load where you know who the user is, idempotently, with the same durable ID each time. Get this into your tracking plan as a hard requirement, not an afterthought.
The three ways stitching silently breaks
Identity resolution fails quietly — there is no error, just two profiles where there should be one — and it almost always fails at one of three points. First, the identify call never fires: this is endemic in server-rendered apps and SSO flows where the login round-trips through a provider and the client SDK never observes the authenticated moment, so the anonymous ID is never linked. Second, it fires with an unstable ID: teams pass a session token, a hashed email, or a username, all of which change over time, so the same human keeps minting new "known" identities. Third, the anonymous ID is destroyed before the merge — the user clears cookies, switches browsers, or uses incognito — and the pre-signup events are lost because there was no anonymous ID left to alias.
The diagnostic is simple and worth running today: compare your analytics tool's total user count against the real number of users in your production database. If analytics shows meaningfully more, you have orphan profiles from broken stitching. The downstream damage is systematic, not random — returning users get logged as new ones, which inflates acquisition, deflates retention, and makes your activation rate look worse than it is because the denominator is padded with duplicate "new users." It is the same class of measurement error as metric definition drift: the number looks precise while being quietly wrong.
Why the ID you choose decides everything
The single most important instrumentation decision is which identifier you pass to identify, and the answer is always your internal, immutable user primary key — the integer or UUID your database assigns that never changes for the life of the account. This ID is what lets the same person be recognized across devices, browsers, and years, because it is the one thing about them that is stable and controlled by you. Everything else fails: emails change and drag PII into your analytics, session tokens rotate on every login, and usernames are editable. A stable internal ID is the anchor the entire identity graph hangs from.
In B2B SaaS there is a second identifier to pass alongside the user ID: a group or account ID that ties the user to their company. Do not overload the user ID to carry account meaning — keep them separate so you can roll individual behavior up to the account without losing per-user granularity. That separation is what makes true account-level analysis possible, a distinction worth its own treatment in the account-level vs user-level analytics guide. Passing a clean user ID and a clean account ID on every identified event is the foundation both personal and company-level reporting are built on.
Identity resolution without third-party cookies
A common worry is that privacy regulation and the death of third-party cookies have made identity resolution harder, but for first-party SaaS analytics the opposite is true: none of this ever depended on third-party cookies. The anonymous ID lives in first-party storage scoped to your own domain, and the identify call links it to your own server-side user ID. The entire join happens on data you already own about your own users on your own product. Third-party cookies only ever mattered for tracking people acrossother companies' sites — something product analytics has no need to do.
This is why cookieless, privacy-friendly analytics can still stitch a full anonymous-to-known-to-paying journey with high accuracy: the stitch is a first-party join, not a surveillance graph. The practical implication is that you do not have to trade measurement quality for privacy compliance here. A user who consents to first-party product analytics can be resolved cleanly from their first anonymous pageview to their current session without a single third-party identifier, which is exactly the model regulators are pushing everyone toward anyway.
The payoff: an unbroken journey from first touch to revenue
When identity resolution works, the anonymous and known halves of the journey fuse into one timeline, and that unlocks the questions SaaS teams actually care about. You can trace a paying customer back to the acquisition source of their very first anonymous visit — closing the loop between marketing spend and revenue that stays open when stitching is broken. This is the missing prerequisite behind most channel-to-revenue traceability work: attribution is only as good as the identity join underneath it.
It also makes your activation funnel honest, because pre-signup behavior and post-signup activation now sit on the same user record, so you can measure which landing experiences and acquisition sources produce users who actually reach first value rather than just users who sign up. And for product-led-growth teams trying to attribute expansion revenue without a clean CRM handoff, resolved identity is what connects a self-serve signup to the account it eventually grows into — the backbone of self-serve revenue attribution. Fix the stitch first; every funnel, cohort, and attribution model downstream inherits its correctness from that one join.
FAQ
What is identity resolution in product analytics?
Identity resolution is the process of connecting the multiple identifiers a single person accumulates — an anonymous device or cookie ID before signup, a user ID after login, an email, a CRM record — into one continuous profile. In SaaS product analytics it specifically means linking the anonymous visitor who browsed your pricing page to the same human once they sign up and log in, so their pre-signup and post-signup events belong to one timeline. Without it, the same person shows up as two or more unrelated users and their journey is severed exactly at the conversion point you most want to measure.
How does anonymous-to-known user stitching work?
Every analytics SDK assigns a random anonymous ID to a new visitor and attaches it to events. When the visitor reveals who they are — logging in, submitting a form, or clicking a tracked email link — your code fires an 'identify' call passing a stable user ID (usually your database primary key). The analytics tool then aliases or merges the anonymous ID into that user ID, so all prior anonymous events are retroactively attributed to the now-known user. The critical requirement is that the identify call runs on every authenticated session with the same durable ID, not a per-session or email-derived one.
Why does the same user show up twice in my analytics?
Almost always because identity stitching failed at one of three points: the identify call never fired (common on server-rendered or SSO flows where the client SDK never sees the login), it fired with an unstable ID (a session token or an email that later changes), or the anonymous ID was reset before the merge (the user cleared cookies, switched devices, or hit the site in a fresh browser). Each break creates a new orphan profile. The tell is a user count meaningfully higher than your database's real user count, and activation or retention curves that look worse than reality because returning users are logged as brand-new ones.
What ID should I pass to the identify call?
Pass your internal, immutable user primary key — the integer or UUID your database uses that never changes for the life of the account. Do not use email addresses (people change them, and they leak PII into your analytics), session tokens (they rotate), or usernames (editable). A stable internal ID is what lets the same human be recognized across devices, browsers, and years. If you need to tie users to their company for B2B rollups, pass a separate group or account ID alongside the user ID rather than overloading the user identifier.
Does identity resolution work without third-party cookies?
Yes — first-party identity resolution does not depend on third-party cookies at all. Anonymous IDs live in first-party storage (a first-party cookie or localStorage) scoped to your own domain, and the identify call links them to your server-side user ID. Third-party cookies only mattered for cross-site tracking, which SaaS product analytics does not need. This is why privacy-friendly, cookieless-by-design analytics can still stitch anonymous-to-known journeys accurately: the join happens on your own first-party data, not on a shared advertising identifier.