Every ad platform has one: a token stuck on the end of your landing page URL that says which click this was. Google has gclid. Meta has fbclid. Microsoft has msclkid. ChatGPT ads have oppref, and if you lose it, everything downstream still works except the one thing you are paying for.
oppref is small and boring, which is exactly why it gets dropped. Here is what it is and the four ways builds lose it.
What it looks like
Click an ad inside ChatGPT and you land on the advertiser’s URL with parameters appended:
https://example.com/pricing?oppref=gAAAAAb123...&olref=gAAAAA...
That gAAAA prefix is not decorative. It is the signature of a Fernet token, a standard encrypted-and-signed string format. The value carries an embedded creation timestamp, and the rest is encrypted with a key you do not have.
So you cannot parse it, cannot shorten it, and cannot regenerate it. Pass it through byte for byte and do not try to normalise it.
Which parameter you actually need
Two tokens arrive together on an ad click, and only one of them is yours to use.
oppref is documented, is what the pixel reads, and is the field the Conversions API expects back on a conversion event.
olref shows up on every observed ad click, is not in OpenAI’s public documentation, and the pixel does not store it. The prevailing read from independent analysis is that it is impression or conversation-side logging on OpenAI’s side, identifying the placement rather than the advertiser’s visit. There is no documented use for it in your setup.
Ignore olref. Capture oppref.
One more distinction worth building into your reporting: OpenAI does not add UTM parameters of its own on paid clicks. Any UTMs you see there are ones you set. Meanwhile organic citations from ChatGPT arrive with utm_source=chatgpt.com. If you tag paid traffic as chatgpt, you keep paid and organic cleanly apart. If you tag it as chatgpt.com, you have just merged your two most interesting traffic sources into one bucket.
Where it gets stored
The pixel reads oppref off the landing URL and writes it into a first-party cookie called __oppref. Observed lifetime is around 30 days, which is behaviour rather than a published guarantee.
It also sets __obref, which is a different thing and worth not confusing. __oppref identifies the click. __obref is a browser reference for the visitor, and it goes into the Conversions API as user.obref, unchanged.
That round trip is the entire job. The identifier arrives on one page view, often days before the purchase, and something has to hold it until the conversion happens.
The four ways it goes missing
A redirect eats it. This is the big one. The ad click goes straight to your landing URL with the parameters appended. There is no intermediate tracking hop that reconstructs anything. Send the ad to a URL that redirects, and if the redirect drops the query string, the click ID is gone before a single tag runs. Point ads at final URLs. If you genuinely need a hop, carry the full query string through every one.
The server side never asks for it. The pixel captures oppref for you. The Conversions API does not, and this catches almost everyone. OpenAI’s own docs put it plainly: capture the value yourself and pass it with the server event when it is available. Skip that and conversions still count, they just stop belonging to any particular ad.
The visit outlives the page. Someone clicks the ad, reads, leaves, comes back two days later through a bookmark, and buys. The purchase page URL has no oppref on it. Only the cookie does, or your own store does. If your conversion tag reads the URL and nothing else, that sale is unattributed.
The value never reaches conversion time. Server-side setups that fire on a payment webhook are the sharpest version of this. The webhook comes from the payment provider, not the browser, so there is no cookie and no URL. The click ID has to have been written somewhere durable at checkout time and read back when the webhook arrives, keyed on something both sides know.
What a resilient capture looks like
The pattern is the same one that works for gclid and fbclid, so if you already do this you are most of the way there.
Read oppref from the URL on the landing page and write it to first-party storage under your control, not only the pixel’s cookie. Prefer a chain that checks the URL first, then the cookie, then whatever you persisted, and takes the first value it finds.
Persist it against the identifier your conversion will actually carry. For an ecommerce checkout that is an order ID. For a subscription that is a customer ID. The point is that when the conversion event fires from a server, you can look the click ID back up without a browser being involved.
Then send it on the event. Not in a custom parameter, in the event-level oppref field, which is where OpenAI reads it.
Why bother
Without oppref, ChatGPT Ads can still count that a conversion happened. What it cannot do is tell you which ad, ad group or campaign earned it, and conversion-optimised bidding gets nothing useful to learn from.
That is the trade. A conversion with a click ID teaches the auction. A conversion without one is a number on a dashboard.
It is a single query parameter, it arrives once, and it is trivially easy to lose to a redirect nobody remembers adding.