The Problem With a Match Score
Most identity vendors hand you a number. This profile is an "87% match." What does that mean? Which identifiers linked? Were they declared by the person, or inferred from a device pattern? Could the link be a household artifact — two roommates on the same Wi-Fi? Could you defend it to your data-protection officer, or explain it in the post-mortem after your lifecycle campaign emailed the wrong person?
A match score compresses everything you would want to know into a single opaque float. You can't audit it, you can't write policy against it, and when it's wrong you can't say why.
ClickStream's identity graph takes a different position: instead of scoring the merge, label the evidence. Every resolved person carries one of three confidence bands — deterministic, probabilistic, or observed — and the band is a first-class field in the product, not a footnote in a methodology PDF.
Three Bands, Not a Black Box
| Band | What it means | What puts a person there |
|---|---|---|
deterministic |
An authenticated or declared identifier anchors this person | Hashed email, hashed phone, CRM customer ID, or a social-login OAuth subject |
probabilistic |
Devices were linked by inference, not declaration | Mobile advertising ID or device-fingerprint device-graph inference |
observed |
A single device, consistently seen — no person-level anchor yet | First-party cookie identity only (server-set, persists up to 400 days) |
The band is the filter you act on. Syncing to your CRM? Restrict to deterministic. Estimating reach or deduplicating traffic reports? Include probabilistic. Personalizing anonymously? observed is exactly what it says: this device keeps coming back, and we won't pretend to know more than that.
Underneath the bands, the matching engine weights each signal type by how trustworthy it is. A hashed email carries a 0.30 weight, a social-login OAuth subject 0.25, a hashed phone or CRM customer ID 0.20, a mobile ad ID 0.10, a device fingerprint 0.08, a bare visitor cookie 0.05. Those weights drive matching internally — but what surfaces to you is the band, because "deterministic" is a claim you can defend and "0.63" is not.
The Merges We Refuse to Make
The most important property of an identity graph is not how many profiles it merges. It's which merges it declines. A false merge is worse than a missed one: it corrupts two customer histories at once, poisons attribution in both directions, and — if it triggers an email to the wrong person — becomes a privacy incident. Four guardrails are built into ClickStream's resolution pipeline.
1. Conflicting identifiers block the merge — permanently
When two profiles share one deterministic signal but conflict on another — different CRM customer IDs, different hashed emails — the merge-eligibility check refuses to combine them, and the refusal is recorded as a persistent merge block so the pair is never silently retried later. Every merge that does happen is written to a merge history, and canonical identity chains are followed with cycle-safe traversal. The graph keeps receipts in both directions: what it joined, and what it declined to join.
2. The shared-mailbox cap
An info@ or sales@ mailbox looks, to a naive matcher, like one very busy person on many devices. It isn't — it's a whole team. ClickStream's rule: an email seen on more than 5 visitors is treated as a shared mailbox and never auto-merged. The signal is retained, but it stops acting as a fuse-everything key. B2B sites hit this constantly; most identity tools happily collapse an entire sales department into one "person."
3. Households are not people
Two people in one apartment share an IP address, a geography, and often overlapping browsing hours. Environmental signals like these are explicitly excluded as merge justification: shared network and location context alone can never fuse two profiles. The probabilistic cross-device matcher runs inside a 30-day window with a confidence gate of at least 0.60 — and even a candidate that clears the gate only auto-merges when a person-distinguishing signal is present, not just an environmental overlap.
Households still exist in the graph — as households. Household clustering groups profiles by hashed IP (excluding hosting, VPN, proxy, and Tor networks), and workplace clustering groups by location and network with business-hours weighting. A household is a structure you can query, never a person created by accident.
4. Mobile ad IDs need corroboration
Mobile advertising IDs are user-resettable — the person who owned that IDFA last quarter may not own it today. So a merge candidate supported by nothing but a MAID match is held until an independent signal corroborates it. One resettable identifier is a hint, not an identity.
Probabilistic Links Expire. Deterministic Ones Don't.
Inference has a shelf life. A fingerprint match from four months ago says very little about who is holding the device today, so every probabilistic edge in the graph carries a TTL and decays out if it isn't re-observed:
| Edge type | Expires after |
|---|---|
| Session link | 7 days |
| Visitor-cookie link | 14 days |
| Device fingerprint | 14 days |
| Location (geohash) | 14 days |
| Household | 30 days |
| Mobile ad ID | 30 days |
| Workplace | 60 days |
| Ad-click ID (13 types captured) | 90 days |
| Hashed email / hashed phone | Never — deterministic signals don't decay |
This is the confidence-band philosophy applied over time: evidence that was inferred fades unless it is refreshed; evidence that was declared endures. A graph whose probabilistic edges never expired would drift steadily toward false merges — the decay is a feature, not a limitation.
Social Logins Are Deterministic Keys
Here's an identity source most analytics tools throw away: the OAuth subject. When a visitor signs in with Google, Apple, Facebook, or LinkedIn, the identity provider returns a stable subject identifier for that account. ClickStream treats these as deterministic, authenticated cross-device keys — the same signed-in account on a phone and a laptop resolves to the same person, without the visitor ever typing an email into one of your forms.
Each OAuth subject is HMAC-hashed with your tenant key before it enters the graph, like every other identifier. In the weighting scheme it sits at 0.25 — just below a hashed email — because an authenticated login is among the strongest person-level claims available. If your site offers social login, you are already generating deterministic identity; the graph just refuses to waste it.
One Tenant, One Keyspace
Identity resolution raises an uncomfortable question most vendors prefer not to answer: if the same person visits two of your vendor's customers, does the vendor connect those profiles behind the scenes?
In ClickStream, the answer is enforced by cryptography rather than policy. Identity signals are HMAC-hashed with tenant-specific keys before graph insertion. The same raw email arriving from two different customers' sites produces two different hash values — so the resulting nodes cannot link, even inside our own infrastructure. Cross-tenant querying exists only behind explicit opt-in. Your identity graph does not quietly enrich anyone else's, and nobody else's enriches yours.
The same posture extends to third-party enrichment data: partner-derived signals are trust-capped below first-party signals and are never used as deterministic merge keys. Data you observed on your own site always outranks data somebody sold you.
Bots Never Become People
An identity graph that resolves bots is doing precision damage to itself. ClickStream's bot detection — a registry of 158 named bots including 38 named AI agents, plus an 11-category classification taxonomy — feeds directly into identity eligibility. Every profile passes through an eligibility pipeline with four lanes: human_eligible, review_required, bot_quarantined, and suppressed_non_person. Quarantined traffic is classified and countable, but it can never merge into a person, never inflates your audience counts, and never receives a confidence band as if it were a customer.
That's also why the dashboard's "People" metric is defined the way it is: unique identity-resolved persons, after merging, bots excluded. When ClickStream says people, it means people.
Reading Identity in Your Code
The Signals SDK exposes identity and bot state on the live visitor object. (The @clickstreamhq/signals package is a developer preview — 0.1.0-alpha — while the core @clickstreamhq/sdk tracker is stable.)
import { configure, getVisitor, isBot, isIdentified } from '@clickstreamhq/signals';
// configure() must run before any getVisitor() call
configure({ apiKey: 'cs_live_...' });
const visitor = await getVisitor();
if (isBot(visitor)) {
// Quarantined: this visitor will never count as a person.
// visitor.bot.category and visitor.bot.name say exactly what it is.
}
if (isIdentified(visitor)) {
// A deterministic identifier has been observed for this visitor.
}
For the graph itself, the read API (GET /v1/graph/:id, available on Scale and above) returns a person's canonical record — including its confidence band and household and workplace cluster context. The graph API is read-only today. Identity resolution unlocks on the Growth plan.
Defensible by Construction
Imagine the audit meeting every data team eventually sits through: "You merged these two profiles. Prove it was the same person." With an opaque match score, the honest answer is a shrug at a decimal. With confidence bands, the answer is structural:
- The band names the evidence class — deterministic, probabilistic, or observed — so every downstream activation can be scoped to the certainty it actually requires.
- Merge blocks are permanent records — conflicting identifiers don't just fail to merge once, they're prevented from merging again.
- Shared mailboxes, households, and resettable ad IDs are refused as merge keys — the three classic sources of false merges are handled as explicit guardrails, not statistical hope.
- Probabilistic edges decay on schedule — inference expires in 7 to 90 days unless re-observed; declared identity doesn't.
- Tenant HMAC isolation is cryptographic — cross-customer linkage is impossible without opt-in, not merely disallowed.
- Bots are quarantined out of personhood entirely — your People metric counts humans.
An identity graph earns trust with the merges it refuses. The confidence band is just that refusal, made visible.