Tracking & Attribution

What Is an Identity Graph for Marketing Attribution?

An identity graph maps which identifiers belong to the same person. What it stores, which identifiers earn a place in it, and why attribution needs one.

Quick answer

An identity graph is a stored map of which identifiers belong to the same person — a first-party visitor ID, a normalised email, a phone number, an ad click ID, a payment customer ID — held together with the evidence that linked them and a confidence score for each link. Attribution needs one because conversions and clicks almost never arrive under the same identifier. Without a graph, a report can only describe browsers; with one, it can describe people.

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

An identity graph is a stored map of which identifiers belong to the same person. A first-party visitor ID, a normalised email, a phone number, an ad click ID, a payment customer ID — the graph records that these were observed together, keeps the evidence, and treats them as one record.

Attribution needs one because the click and the conversion almost never arrive under the same identifier. Without a graph, a report can only describe browsers. With one, it describes people.

What does an identity graph actually store?

Two things: identifiers, and the evidence that connects them.

Each identifier is a node — one email, one phone number, one cookie ID. Each connection is an edge, and an edge exists only where something was observed: a form submission carrying both an email and the visitor ID of the browser it was typed in, an order carrying both an email and a payment customer ID.

What it does not store is a person. There is no master record of a human in the middle — only a cluster of identifiers the evidence says belong together, with sessions hanging off each one. “Ava Chen” is a label your dashboard prints on a cluster.

That matters when the graph gets something wrong. A system that stores observations can revisit them; one that stores conclusions cannot.

Which identifiers go into a marketing identity graph?

Only identifiers your own systems observed: what a visitor typed into your form, what your server wrote, what arrived in your own landing page URL or your own payment processor. That restriction is what makes the graph a piece of first-party attribution rather than a third-party data purchase.

What each one is worth:

Identifier Where it comes from What it proves Durability
First-party visitor ID A cookie your server sets on your domain Two sessions, same browser Months if the server sets it, days if a script does
Email address A form, or an order Strong — people reuse one email across devices Until they use a second address
Phone number A form, or an order Strong, and normalises cleanly to E.164 Permanent, rarely shared
Ad click ID The landing page URL — fbclid, gclid, msclkid, ttclid, epik This session came from one specific ad click One page load, unless you store it
Payment customer ID Stripe, or your billing system Every future invoice belongs to this person Permanent within that processor
IP address + user agent The request itself Weak — same network, same browser build Minutes to hours
Device fingerprint hash Browser characteristics Weak — a last resort Weeks, and degrading

The pattern: strong identifiers are things a person gave you, weak ones things you inferred.

The click ID is the only row with real urgency. An email is still an email tomorrow; a gclid exists for one page load and is gone, which is why which click ID each ad platform uses is worth knowing before you need it. Unwritten at first touch, the connection between that person and that campaign exists nowhere else.

PartialLeads lead detail: an Identity Cluster panel listing six identifier tiers, each with a match-strength bar and the sessions it joined

What makes a join deterministic instead of probabilistic?

A deterministic join is one where the same value appeared in two places. The person typed ava@example.com into a form on her phone in March and onto a checkout on her laptop in April. Nothing is guessed: two records carry a matching key, and the key came from the person both times.

A probabilistic join is an inference. Same IP, same browser version, same city, similar behaviour, therefore probably the same human. Often right, never proof.

The difference shows when you are wrong. A wrong deterministic join is rare and usually traceable — a shared family email, a receptionist’s number on twenty lead forms. A wrong probabilistic join is silent, and merges two strangers into one customer who appears to have taken a journey neither took.

Which is why the honest design is a ladder, not a switch: deterministic keys first, inference only for what they cannot reach, inferred edges marked as such.

Why does every edge need a confidence score?

Because the two ways a graph fails are not symmetrical, and a score is how you choose which one to risk.

Under-merging leaves one person split across three records. Your lead count inflates, your cost per lead looks better than it is, and your journeys are truncated — exactly why one customer shows up as three leads. Embarrassing, but recoverable: the evidence is still there to join later.

Over-merging is worse. Two people become one, and every conclusion downstream inherits the error — the journey is fiction, the revenue lands on the wrong campaign, a conversion event goes back to an ad platform with somebody else’s email attached. No report shows you this happened.

So confidence is what keeps weak evidence from doing strong things. A mature graph ranks its tiers so the strongest available key wins, and bounds the weak ones with time windows and row caps so a shared office IP cannot absorb an entire company.

What does an identity graph fix that a cookie cannot?

Four things, no matter how well the cookie is implemented.

The device switch. A click on a phone and a purchase on a laptop are two browsers with two cookies and no relationship. Only a shared identifier — the email on the order — joins them.

The long gap. Someone clicks in March and buys in June. The click ID is long gone and its session has ended. If the first touch was written against the person rather than the session, it survives.

The payment processor. Stripe knows a card, a customer and an amount. It does not know a campaign. Joining the payment back to the campaign runs through the customer ID and the email — graph work by definition.

The re-identified anonymous. Someone browses anonymously for two weeks, then fills a form. A cookie-only system has two weeks of unattributed sessions and one lead. A graph attaches those sessions to the person retroactively, because the visitor ID they carried now links to an email.

Each is the same operation: a later identifier claiming earlier evidence. That is all identity resolution is, and how visitor identity resolution works is the step-by-step version.

What breaks an identity graph?

Predictable things, and better known in advance.

Shared identifiers. A family laptop, an office NAT with two hundred people behind one IP, info@company.com on forty enquiry forms. Genuine edges, useless ones — hence the caps.

Unstable IPs. iCloud Private Relay, corporate VPNs and carrier networks replace the IP entirely, so anything built on it degrades. Weight it low rather than fight it, which is what attribution for Private Relay and VPN visitors comes down to.

Two addresses for one person. A work email on the demo request, a personal one on the invoice. Unless a phone number or visitor ID overlaps, those clusters stay separate.

Normalisation drift. Ava.Chen@Gmail.com, ava.chen@gmail.com and ava.chen+newsletter@gmail.com are one mailbox and three strings. Normalise them differently in two places and the join silently fails. Meta’s customer information parameters documentation gives the rules for conversion payloads — lowercase, trim, strip formatting from phone numbers — and the same discipline belongs in your own graph.

Consent. If a visitor declines tracking there is no identifier to store, and there should not be one. A graph that respects consent has gaps, and those gaps are correct.

Is an identity graph the same as a CDP or a CRM?

No, and conflating them leads teams to buy the wrong thing.

A CRM stores records you created deliberately — contacts, deals, notes — and assumes you know who someone is. A CDP unifies customer data for activation: audiences, segments, syncs. An identity graph sits underneath both and answers one question, which identifiers belong to the same person; it is what a CDP relies on when it claims to have unified a profile.

The attribution version is narrower still: identifiers carrying campaign evidence, resolved fast enough to send a conversion back to an ad platform while it still matters.

How does PartialLeads build an identity graph?

PartialLeads maintains an identity graph per account: normalised email, phone, Stripe customer ID and IP mapped to sessions, each with a confidence score. A cluster resolver unions a person’s sessions across six tiers — durable visitor ID, email, phone, IP plus user agent, device fingerprint hash, and a click ID seen on more than one session — with the weak tiers deliberately bounded. The fingerprint tier runs on a 90-day window and is capped at 200 rows, specifically to stop a false merge from spreading.

Three details matter, because they are where graphs usually leak.

The visitor ID is set by the server, not by a script. Browser restrictions cap script-written storage aggressively; a cookie set in the HTTP response is not subject to that cap, so the graph’s most durable node stays durable.

Normalisation happens before anything is stored or hashed. Phone numbers go to E.164, using the session’s geo for a missing country code; Gmail dot and plus variants are collapsed before hashing. Joins fail on formatting far more often than on logic.

Purchases match on a ranked ladder. An inbound order matches a session by visitor ID echo first, then email, then phone, then IP, and an unmatched order is stored as unmatched rather than guessed at — recoverable when identity arrives. For sessions broken mid-visit, visit-sibling inheritance lets a sourceless session take campaign data from a sibling in the same visit.

Where you see it: the Journey column in the Leads list draws each session as a badge, and the ring on each badge encodes how that session was stitched into the person — visitor ID, email, phone, IP plus user agent, fingerprint or click ID.

PartialLeads Leads list: a lead row whose Journey column shows stitched session badges under a 4 SESSIONS label

The honest constraints. A graph joins only the evidence it was given: someone using two email addresses, two devices and no phone number stays two clusters until something overlaps. Weak-tier joins are bounded on purpose, so some real merges are declined rather than risked. And resolving identity on your side is not the same as an ad platform resolving it on theirs — we control what gets sent; whether Meta or Google ties that event to a user depends on their graph.

What breaks The mechanism Where you see it in the dashboard
One person counted as three leads across devices Six-tier cluster resolver: visitor ID, email, phone, IP + user agent, fingerprint, click ID Leads list, Journey column with a sessions count
Purchases landing with no campaign attached Orders matched to a session on a ranked ladder; unmatched orders kept and re-matchable Purchases ledger, matched vs unmatched
Safari and cookie clearing dropping returning visitors Durable visitor ID written by the server, not by a script Journey ribbon, sessions joined across weeks
Joins failing on formatting rather than logic Email and phone normalised before storage and hashing Lead detail, normalised contact fields
Attribution lost between two sessions in one visit Visit-sibling inheritance passes campaign data to the sourceless session Attribution report, resolved model

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

Sources

  1. Meta for Developers — Conversions API: https://developers.facebook.com/docs/marketing-api/conversions-api
  2. Meta for Developers — Customer information parameters (normalisation and hashing rules): https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters
  3. Meta for Developers — fbp and fbc parameters: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc

Frequently asked questions

QWhat is an identity graph in simple terms?
It is a record of which identifiers belong to the same person, plus the evidence for each connection. If an email address and a browser cookie ID appeared together on one form submission, the graph stores that they are linked. Later, when a purchase arrives carrying only the email, the graph can point back to every session that cookie ID was seen on.
QWhat is the difference between an identity graph and identity resolution?
The graph is the data structure; resolution is the process that reads and writes it. Resolution is the act of deciding that two sessions belong to one person; the graph is where that decision and its supporting evidence are stored. In practice the terms get used interchangeably, but the distinction is useful when comparing vendors — some have a resolution step and no durable graph behind it.
QDo I need an identity graph if I only run one channel?
Probably yes, because the problem is not channel count. Even single-channel advertisers have visitors who click on a phone and buy on a laptop, or who return three weeks later in a new session. Those are identity problems, not attribution-model problems, and no amount of tuning a report fixes them.
QIs an identity graph legal under GDPR?
It processes personal data, so it needs a lawful basis, consent where consent is required, a retention policy and a way to honour deletion requests — the same obligations as any customer database. What matters is that it is built on first-party data you collected with permission, that you can delete a person's cluster on request, and that you do not buy third-party identity data to enrich it.
QCan an identity graph merge two people by mistake?
Yes, and this is the failure worth designing against. It happens on shared signals — a family laptop, an office IP, a generic company email on many forms. Good graphs weight those signals low, bound them with time windows and row caps, and prefer to leave one person split across two records rather than merge two strangers into one.
QWhat happens to my identity graph when third-party cookies go away?
Very little, if it was built on first-party data. Third-party cookies were never a good identity source for a single advertiser; the durable nodes are the email and phone a person typed into your own form, the cookie your own server set, the click ID that arrived in your own URL and the customer ID in your own payment processor. None of those depend on a third-party cookie.
QHow is an identity graph different from device fingerprinting?
A fingerprint is one weak, inferred signal that can live inside a graph — it is not the graph itself. Fingerprints degrade as browsers change, they are probabilistic, and they are increasingly restricted. A graph built primarily on fingerprints is a guess with a database attached; a graph built on identifiers people supplied uses the fingerprint only as a last resort, if at all.
QHow do I tell whether an attribution tool really has an identity graph?
Ask it to show its working. A tool with a real graph can tell you how many sessions a given person has, which identifier joined each one, and how confident it is in that join. A tool without one will show you a journey with no explanation of how the steps were connected — which usually means they were connected by the session, not the person.

Find the qualified leads your forms are currently throwing away.

Install PartialLeads on one landing page, send traffic, and compare what your CRM captured against what PartialLeads recovered and qualified.