Browse the help center

Why a conversion did not count

Read the XD-reason header (or the pixel's debug=1 JSON) to see why a pixel or server-to-server conversion was not counted, what each reason code means, and why repeated test conversions vanish.

Troubleshooting network manager Account → Advertisers → campaign → Conversion actions → Conversion tracking code

A conversion pixel or postback that “did nothing” almost always says why on its response. This page lists the reason codes the ad server returns, how to read them, and why repeated test conversions can vanish. To set up the tracking in the first place, see Get the pixel and S2S tracking code; to run a test conversion, see Test a conversion.

Who this is for

Anyone integrating or testing conversion tracking — network managers and the advertiser’s own developers. Reading the response needs no permission in Epom: it is whatever your browser, your server or curl receives from the ad server.

Read why a conversion did not count

The pixel always answers 200 OK with a 1×1 GIF, so nothing in the picture tells you whether the conversion landed. The outcome is on the response instead, in an XD-reason header — present on every conversion response, success included, from the cookie pixels (/action.gif, /action.js) and from the server-to-server endpoint (/at) alike. On the image pixel you can also add debug=1 to the URL and get the outcome as a small JSON body instead of the image (any non-empty value works; the JS pixel and the S2S endpoints do not serve it):

curl -s 'https://ads.example.com/action.gif?key=<key>&debug=1'
{"reason":"no-cookie","counted":false,"description":"No click or view cookie reached the ad server - the browser dropped it, or this user never saw the ad."}

counted is true only when the conversion was added to the advertiser’s totals — which is ok and nothing else. The codes you meet while integrating:

XD-reasonWhat happened
okCounted.
expiredA click or view matched but fell outside the action’s attribution window. Recorded as a diagnostic, not counted.
no-cookieNo click or view cookie arrived — wrong browser, cookies cleared, or a consent tool dropped it.
no-matchCookies arrived, but none of them belongs to a creative of this campaign — or of any campaign sharing its conversion-tracking alias. Usually the tag sits on a page reached without seeing the ad.
already-trackedThe same click or view already produced this conversion; the repeat is deduplicated. On the pixel the check is server-side as well as cookie-side, so it holds even when the visitor’s browser could not store the tracking cookie. Clicking the ad again starts a new chance to convert. On a postback the same reason means something narrower — see the corner case on repeats below.
window-disabledThat event type has a zero-length window on this action, so it never converts.
cookie-data-missingA cookie matched, but it carried no ad data to build the conversion from.
key-unknownThe key= value does not resolve to a conversion action. key= is the pixel parameter, so this is a stale or mistyped copy of a pixel code block — a postback never sends it.
action-data-missingThe request named no conversion the ad server could read — no subId, no key + click-id pair, or a value in one of them it could not decode. Almost always a truncated postback URL, or a placeholder that resolved to nothing so the parameter arrived empty; a double-encoded click id does it too. Check what your server actually sent, not what the template says.

The rest all say the same thing in different words — the entity named by the cookie or the click id is not live in ad serving: deleted, or with conversion tracking switched off. A cache reload lags a settings change by up to ten minutes, so one of these right after an edit may simply be the ad servers not having caught up.

XD-reasonWhich entity
pair-unknownThe key and the click id both parsed, but together they name no conversion action.
action-unknownThe conversion action.
banner-unknownThe creative — unknown, or conversion tracking is off for it.
campaign-unknownThe campaign — unknown, or conversion tracking is off for it.
advertiser-unknownThe advertiser.
placement-unknownThe placement.
country-unknownNot an entity: the country of the conversion could not be resolved from the request.
errorNot an entity either: the ad server failed while processing the conversion. Worth reporting.

Two more headers ride along on the same response:

HeaderWhat it says
XD-attributionWhich cookie jar answered, as an attribution type (POST_CLICK, POST_VIEW, and the expired variants). Set on the cookie pixels only, and worth reading when a landing page’s click id went missing: the pixel reads both jars and a click beats a view, so a conversion you assumed was post-view is frequently a post-click whose easclid= never arrived.
XD-warningA parameter the ad server did not use on a conversion it otherwise counted. Today the only value is payout-word-refused. Unlike XD-reason these accumulate — one response can carry several.

Outcomes that predate the reason header still emit their original single-purpose flag alongside it, valued 1, for anything already parsing them:

XD-reasonLegacy flag
action-data-missingXD-data-key
pair-unknownXD-pair
action-unknownXD-action
placement-unknownXD-placement
banner-unknownXD-banner
campaign-unknownXD-campaign
advertiser-unknownXD-advertiser
country-unknownXD-countryData
errorXD-exc

Reading these headers from JavaScript on the advertiser’s own page works: all of them, XD-warning included, are named in Access-Control-Expose-Headers. A plain new Image().src = … pixel cannot read response headers at all — use fetch(), or just debug=1 from the command line.

Corner case: on the server-to-server endpoints the HTTP status is almost the same answer — /at replies 404 when nothing was logged and 200 when something was. The exception is the one that matters: an expired conversion logs a diagnostic row, so it answers 200 while XD-reason: expired says it was not counted. Read the header, not the status.

Corner cases and gotchas

Corner case: repeated test conversions from the same machine can silently disappear. The pixel counts one conversion per click or view: fire it twice for the same click and the second is a duplicate, never shows up in reports, and answers already-tracked. A “Duplicate conversion window (per IP)” on the action removes further repeats from the same address. Wait out the window, click the ad again, or test from another machine.

Server-to-server postbacks are different: there the only identity is the one your partner sends, so repeats are counted unless you tick Reject duplicate conversions on the action and your network runs duplicate detection — the checkbox is not even offered when it does not.

The landing-page snippet posts to the same endpoint but refuses the repeat before it leaves the browser, so a second fire of the same event on the same click is not counted whatever those two settings say. See Install the landing-page helper.

Related pages

Please disable Adblock
Are you using adblock? Disable it and reload the page to proceed to the destination page.

A registration has already been submitted from this page. Please try again in 10 minutes.