GPT Ads
ChatGPT Ads

Browser tracking vs. the Conversions API, in plain English

What each way of reporting a conversion catches, what it misses, and why running both does not double count.

By 5 min read

Two paths to the same target: one dashed and full of gaps, one solid and unbroken

If you've set up ChatGPT Ads tracking, you've probably been told you should also be doing "server-side tracking" or using "the Conversions API" — usually without much explanation of what that means or why you'd bother.

Here's the plain version, what each approach actually catches, and how to decide whether the second one is worth your time.


The two ways a conversion gets reported#

Browser tracking runs in your shopper's web browser. They complete an order, a small piece of JavaScript on the thank-you page fires, and their browser sends a message to ChatGPT saying a purchase happened.

The Conversions API runs on your server. The order completes, your store's backend notices, and your server sends that message to ChatGPT directly. The shopper's browser is not involved at all.

Same information, two different messengers. The difference is entirely in how reliable each messenger is.


What browser tracking misses#

The browser is a hostile environment for measurement, and increasingly so.

Ad blockers and privacy extensions block requests to known measurement endpoints. The block is silent — the page works, the order completes, the message is simply never sent.

Browser privacy features do similar work by default. Safari's tracking protections and Firefox's strict mode restrict or clear the cookies that hold the click reference, so even when the event fires it can arrive with nothing tying it to your ad.

The shopper closes the tab. The purchase event fires on the confirmation page. Someone who completes payment and immediately closes the tab may never load it, or may close it before the request finishes.

Connections drop. Mobile checkout on a bad signal loses requests.

None of these produce anything you can see. The order is in your Shopify admin and the conversion simply doesn't exist as far as your ad reporting goes.

How much you lose depends heavily on who you sell to. A store selling developer tools loses far more than one selling garden furniture — ad blocker use varies enormously by audience. I'd rather you measure your own gap than trust a number I made up, and the next section is how.


What the Conversions API misses#

It isn't a straight upgrade. Server-side has its own blind spots.

It only knows what your server knows. Your server sees completed orders. It does not see someone browsing three products and leaving. Page views and product views still need the browser.

It needs identifiers to match on. A browser event carries cookies that identify the visit. A server event carries whatever you attach — hashed email, hashed phone, the click reference from the original ad click. If you don't capture and carry that click reference through to the order, your server event arrives correctly and matches to nothing.

It has a time limit. Events must carry a timestamp within the last seven days, and no more than ten minutes in the future. You can backfill a few days if something breaks; you can't reconcile last month.

It's more work to set up. An API key, a webhook that fires when orders are paid, and code that assembles and sends the event. That's the real cost, and it's why apps exist to do it for you.


Why the answer is both#

Two identical cards arriving from opposite sides and merging into one

Run browser tracking and server-side tracking together, and each covers the other's gap. Browser gives you the full funnel and the cookie-based matching. Server guarantees the purchase — the event your entire return calculation depends on — arrives regardless of what the shopper's browser did.

The obvious worry is double counting. Every purchase would be reported twice, your conversions would double and your cost per acquisition would halve.

That's solved with an event ID. Both copies of the same purchase carry the same one, and ChatGPT matches on three things together — your pixel ID, the event name, and that ID. It keeps whichever arrives first and discards the duplicate. One purchase, one conversion, whichever messenger got through.

This only works if the IDs genuinely match. If your browser event and your server event generate their IDs independently, they won't, and you'll double count everything. Whatever you use should derive the ID from something stable about the order — the order number, say — so both sides arrive at the same value without needing to talk to each other.


How to measure your own gap#

Before you invest in server-side, find out what it would buy you.

  1. Pick a period where your tracking was running normally — a full week.
  2. Count the orders in your Shopify admin for that period.
  3. Count the conversions your ads dashboard reports for the same period.

The difference is your total gap. Some of it is legitimate: shoppers who never saw your ad, and purchases outside the attribution window. But if the gap is large, some of it is browser events that never arrived.

Then place one test order and confirm your purchase event fires with the correct amount and click reference — if it doesn't, fix that first. Server-side tracking will faithfully deliver the same broken data.


What you need to turn it on#

If you decide to do it, the pieces are:

  • An API key from the conversions section of your ChatGPT Ads account. This is a secret. It must live on your server, never in your storefront code, where anyone viewing the page source could read it.
  • Something that fires when an order is paid. On Shopify that's a webhook.
  • The click reference, carried through to the order. This is the part people skip, and it's what makes the difference between a matched conversion and an anonymous one.
  • Matching event IDs on both sides, as above.

Most platforms also offer a validation mode that checks your events without recording them — it's worth sending your first few through that before you turn it on for real, so a formatting mistake doesn't pollute your reporting.


The short version#

Browser tracking is easy to set up and loses a meaningful share of your purchases to things you cannot control. Server-side tracking is more work and guarantees the purchase arrives.

If you spend enough on ads that a fifth of your conversions going missing would change what you do next, run both. If you're spending a little and mostly want directional signal, browser-only is fine — just know that the number you're looking at is a floor, not a measurement.

And either way, check that your purchase events carry the right amount and the click reference. Neither approach helps if what you're sending is wrong.


I build LLM Pixels, a Shopify app that runs both the browser pixel and server-side purchases with deduplication handled for you.