Why your DSP and your verification numbers never match
An impression discrepancy is the gap between two counts of the same campaign. It is usually filed as noise. It is not noise: it has causes, the causes can be counted, and most of them cost you money.
Pixtru guides · updated
What an impression discrepancy is
Your DSP says it bought 10,000 impressions. Your verification vendor, or your own ad server, says 8,460 of them happened. The 1,540 in between is the impression discrepancy, and it is usually written as a percentage of the billed count:
discrepancy = (billed − measured) ÷ billed
Here that is 1,540 ÷ 10,000, or 15.4%. Try your own numbers in the discrepancy calculator.
Most guides to discrepancies are written for publishers, who want to know why an exchange paid them for fewer impressions than their ad server counted. This one is for the other side of the table: the buyer, who paid for the larger number.
Two counts, taken at two different moments
Nobody's count is wrong. They are counting different events, at different points in the life of one impression:
| Who counts | When they count | What they cannot see |
|---|---|---|
| The DSP | When it wins the auction and sends the ad on its way. | Whether the ad ever arrived. |
| The exchange or ad server | When it serves the ad to the page. | Whether the ad rendered, or was seen. |
| The verification tag | When its code runs inside the rendered ad, in the browser. | Anything that happened before it ran. |
Every impression that fails between the first moment and the last is in one count and not the other. So the discrepancy is not a measurement error to be tolerated; it is a list of impressions that stopped somewhere, for a reason.
Where the missing impressions go
Follow one campaign's day, impression by impression, and each one stops at the first stage it fails:
| Stage | Reached it | Stopped here | Why |
|---|---|---|---|
| Billed by the DSP | 10,000 | — | The number on the invoice. |
| Served by the exchange | 9,400 | 600 | The ad never reached the page: a timeout, a page closed early, a request that went nowhere. |
| Verification tag ran | 8,460 | 940 | The ad was served, but the code that counts it never ran. This is the gap you can see. |
| Measurable | 7,073 | 1,387 | The tag ran but could not see where the ad was, usually because it was boxed in a cross-domain iframe. |
| Viewable | 5,305 | 1,768 | Measured, and never on screen long enough: below the fold, or scrolled past. |
| Valid | 5,146 | 159 | On screen, but to a known bot or an automated browser. |
The discrepancy you can see is the first two drops: 600 never served and 940 never measured. But look further down. Of the 8,460 your verification report counted, only 5,146 were on screen long enough to count and passed the invalid-traffic checks. A report that shows a 15% gap and a healthy viewability rate can still describe a campaign where nearly half the budget bought nothing that did its job. The served, measurable and viewable guide walks through each of these counts.
The usual causes, and how to spot each
| Cause | What it looks like |
|---|---|
| Latency and early exits | Worse on slow pages, heavy creatives and mobile. The DSP counted the win; the page was gone before the ad arrived. |
| The tag is in the wrong place | A gap that is near-total for one creative or one partner. A verification tag outside the ad, or in its own iframe, measures the page rather than the ad. See when the tag never fires. |
| Unexpanded macros | IDs that arrive literally as ${AUCTION_ID} or %%CACHEBUSTER%%. The ad server did not substitute them, so the measurement cannot be matched to a billed impression. |
| Blocked verification code | A steady gap on desktop browsers with content blockers; the ad renders, the counting code does not. |
| Different invalid-traffic filters | A gap that moves with traffic quality. Each system removes bots by its own rules, at its own time. |
| Time zones and reporting windows | A gap that shrinks when you compare whole weeks instead of days. One system closes its day at midnight UTC, another at midnight in New York. |
| Unsettled data | Yesterday's gap is different today. Google says Display & Video 360's figures can take 48 to 72 hours to settle; compare finished reports, not live dashboards. |
How big a gap is normal?
The industry's contract default is 10%. Under the 4A's/IAB standard terms, when the measurement used for invoicing is lower than the other by more than 10% over the invoice period, the parties reconcile. Google's own help pages for Campaign Manager 360 and Display & Video 360 call variances of up to 20% normal. Neither figure says the gap is harmless — only that nobody will argue about it. What gap is acceptable covers where the 10% comes from and what it actually commits anyone to.
How to investigate one
- Compare like with like. The same date range, the same time zone, finished reports rather than the live interface, and at least a few thousand impressions — Google will not investigate fewer than 1,000.
- Split it. By site, creative, partner, browser and hour. A cause almost always lives in one slice: one creative with a broken tag, one exchange with slow pages.
- Check the IDs. Look for macros that arrived unexpanded. One wrong macro can make a whole partner unmatchable.
- Fire the tag yourself. Load the creative, open the browser's network panel, and confirm the verification request leaves and is answered.
- Find the stage. Was the impression never served, never measured, not measurable, not viewable, or invalid? Each has a different owner and a different fix.
Questions buyers ask
Which number is right?
Both, for what they count. The DSP's number is right about what it bought; the verification number is right about what rendered where its code could see it. The question worth asking is which impressions are in one and not the other, and why.
Should I pay for impressions that were never measured?
That is set by your contract, not by the measurement. Under the 4A's/IAB terms the invoicing count is the Controlling Measurement named in the insertion order. What measurement gives you is the evidence for the conversation: how many were never served, how many were never measured, and why.
Why is the gap the same size every month?
Because it has a cause that does not change month to month: a share of slow pages, a share of readers with content blockers, a creative trafficked without its tag. Noise moves around; a steady gap is structural, which also means it can be found.
My viewability rate is high. Can the gap still matter?
Yes. Viewability is usually quoted as a share of measurable impressions, so it says nothing about impressions that were never measured. A 75% viewability rate and a 53% viewable share of what you paid for can describe the same campaign.
Is the gap fraud?
Mostly not. Invalid traffic is one cause among several, and it is usually a small one next to impressions that were never served or never measured. Treating the whole gap as fraud sends the investigation to the wrong place.
Why totals are not enough
Two totals can only tell you that a gap exists. To say where each impression went, you have to join the two sides impression by impression, on an ID both of them recorded — then every billed impression can be given exactly one reason, and the reasons add back up to the invoice.
That join is what Pixtru does. The tag carries the impression ID your ad server already writes in its log; the hourly log carries the same ID; each billed impression walks the stages above and stops at one. Where a partner cannot pass that ID, its own auction ID is matched through the logs instead and labelled as such, never mixed into the exact rate. The method describes each gate, and the integration guide what a partner sends.
What this does not cover. Pixtru measures display ads on the web. Its invalid-traffic checks are the general kind — known bots, crawlers, headless and automated browsers — not sophisticated fraud built to look human, and it is not MRC-accredited. The standards section says exactly what is applied.