Event ID: the value that lets two systems agree a conversion happened once
In short
An event ID is a correlation key: one string attached to both the browser copy and the server copy of a single conversion, so the receiving platform counts it once. It does not have to be globally unique. It has to be identical across both transports, stable if either is retried, and different for two genuine conversions inside the platform's deduplication window.
Key takeaways
- The guarantee is 4 properties: same value on both transports, stable across retries, distinct per real conversion, present before either send.
- Minting the value randomly in the browser is the strategy that breaks — a refresh produces a new one and the conversion is counted twice.
- An order identifier makes a good event ID for purchases; it needs care for refunds and for multiple events attached to one order.
- Each platform applies its own window and its own matching field. Read the current rules from the platform's documentation before relying on them.
An event ID is the value two systems use to agree they are describing the same conversion. The browser sends one copy of a purchase, your server sends another, and the platform matches them on that value and counts one. How you generate it follows entirely from the guarantee it has to keep, so state the guarantee first.
- Identical on both transports. Not similar, not derived by 2 different routines — the same string of characters.
- Stable across retries. A refresh, a retry or a queued send hours later must reproduce the same value, or 1 conversion becomes 2.
- Distinct per genuine conversion. Two orders in the same second must not collide, and a returning customer must not reuse the first value.
- Present before either send. If the server mints it after the browser fired, there is nothing to match on.
Four places the value can come from
| Generated by | Both transports see it? | Stable on retry or refresh? | How it fails |
|---|---|---|---|
| Server, rendered into the page | Yes — one value, two readers | Yes, if derived from the order rather than the request | Needs a server render or an API call; awkward for a purely static checkout |
| Random value in the browser | Only if the browser passes it back to your server | No — a reload mints a new one | The classic double count after a customer refreshes the confirmation page |
| The order identifier | Yes — both systems already hold it | Yes; it is the order | Collides when 1 order raises several events; exposes an internal id unless hashed |
| Hash of the payload | Yes, if both sides hash byte-identical inputs | Only if every input matches, including number formatting | Silent mismatches that read as a platform bug rather than a formatting bug |
For purchases the order identifier is usually right: it satisfies 3 of the 4 properties and is reproducible from your own records. For non-order conversions — a lead form, a call, a signup — mint the value server-side when the conversion becomes true. The browser-random strategy produces double counts in week 1; the payload hash produces them in month 6, when an amount field starts serialising as 49.00 instead of 49.
A correlation key, not a primary key
The distinction saves a lot of argument. A primary key identifies a row in a system you control, for as long as that row exists. A correlation key only has to let two independent systems recognise the same occurrence inside a bounded window, and may be discarded afterwards. A primary key you own makes a good event ID; a good event ID is not automatically safe as a primary key, because nothing guarantees it is unique outside the window.
Advertising systems make this distinction constantly, and getting it wrong is how counts drift apart: an occurrence and the record of it are separate things with separate rules, the point in win notice and billable event are not the same.
Wiring it so both copies agree
- Mint or read the value when the conversion becomes true — the order commits — not when a tag happens to fire.
- Write it to your record of the order and to the page's data layer in the same operation, as a declared field rather than an ad-hoc variable: see the data layer as a versioned contract.
- Have both senders read it from that 1 place. A browser tag constructing its own value and a server job constructing another agree until the day they do not.
- Log it on both sides with the send timestamp and the response, so a mismatch is a query rather than an investigation.
- Reconcile daily: browser sends, server sends, distinct identifiers. Three numbers with an obvious relationship, and a small internal tools and ops job to raise it when they diverge.
Two systems do not agree that a conversion happened once because they are both correct. They agree because someone gave them the same string to compare.
Where the value shows up afterwards
In a raw analytics export the identifier is a parameter rather than a column, which matters to anyone writing SQL against it — the shape is in what one row of the event export holds. In a platform interface it is invisible: you see the deduplicated count, not the matching, so a divergence is diagnosed from your own logs first. That investigation is its own subject, in the ad platform counts more conversions than you do.
The identifier is one field in a larger payload contract, and the rest of that contract sits under tracking, consent and event pipelines in the marketing and advertising practice.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
Can I use the transaction ID as the event ID?
Usually yes, and for purchases it is often the best choice: both sides hold it and it survives retries. Two cautions. If more than 1 event can be raised against a single order, the value needs a suffix per event type. And if the identifier is meaningful inside your business, hash it with SHA-256 rather than publishing an internal sequence to a vendor.
What happens if the browser and server send different event IDs?
The platform treats them as 2 separate conversions and counts both. Nothing errors, which is why this is normally found in a reporting discrepancy weeks later rather than in a test. The 2 usual causes: a value minted independently on each side, and a browser value regenerated when the confirmation page reloads.
Does the event ID need to be globally unique?
No — only unique within the platform's deduplication window, which is measured in days rather than years. A UUID is fine but unnecessary; an order identifier unique inside your own system is sufficient. Reproducibility matters far more than uniqueness: the same conversion must yield the same value every time it is sent.
Should the event ID be sent for every event or only conversions?
Send it wherever the same occurrence can reach a platform by 2 routes — conversions, and any event you mirror server-side. For events that only travel one way there is nothing to deduplicate against, so the identifier adds no matching value, though a stable one still helps when reconciling your logs.
- deduplication
- conversion tracking
- event pipelines
- identifiers
The work behind this page
Builds from our portfolio that this page draws on.
PipelineIQ
An AI SDR platform that scores every lead for fit, runs multichannel sequences across email, LinkedIn and call, drafts the replies, and books the meeting.
Sales AIQuoteForge
An AI CPQ and proposal platform that builds enterprise quotes from your catalog, guards every discount against the margin floor, routes approvals, and generates the proposal.
Sales AIRead next
- The tagging server: a first-party endpoint that owns the payloadA tagging server is not a proxy. It parses one first-party event, adds and strips fields, and emits a vendor-shaped request per destination from your infrastructure.definition
- Consent state: a typed field on each event, not a switch on the pageThe pageview before the banner answer and the purchase after it are both correct, and they carry different consent values. That only works if consent travels per event.definition
- The exported event row: nested parameters and no session columnOne row per event, a repeated parameter struct with four typed slots, and a pseudonymous identifier that can be missing. Every figure a report shows is derived from this.definition
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