Measurement · Data coverage
Google Ads missing data
A zero in an ads report means one of two things. Nothing was delivered, or nobody was counting. Google’s own API documentation says the row is dropped when every selected metric is zero. So the day that had no activity and the day that never arrived look identical in your export. This page separates them, on your file, in your browser.
Your report says 0 on the 14th.
You cannot tell, from that number, whether the campaign delivered nothing that Tuesday or whether Tuesday never reached your report.
Both come out as a flat line.
One operator drew the line better than we had
In a thread about numbers that refuse to match, somebody put the whole distinction in one sentence:
“Attribution disagreement is philosophical and you learn to live with it. A missing conversion is a bug and you can fix it.”
u/ksz2018, r/PPC, 3 August 2026. Collected in our own ICP voice bank.
Those two problems get treated as one, and only one of them is solvable
Attribution disagreement is a difference of opinion between two models looking at the same events. It does not resolve, and the honest response is to pick a source of record and move on. We wrote that argument out in marketing attribution.
A collection gap is different in kind. It has a date, it has a cause, and somebody can go and find it.
A collection gap is also the cheaper question, so it should be asked first. Almost nobody asks it first, because the platforms give you no reason to suspect there is a question at all.
What can a 0 in an ads report actually mean?
Four shapes, and they are not equally reportable. The first is a measurement. The other three are holes wearing the same clothes. What separates them is not the value in the cell, it is whether the row for that date exists at all.
| What is in the file | What it probably means | Verdict on the total that spans it |
|---|---|---|
| A row for that date, value 0 | The day was measured and had no activity | Report it. This is a real zero, and the only one of the four that is |
| No row for that date | Either nothing delivered, or nothing was collected. The file cannot say which | Do not report it yet. If it was a collection gap, your total is understated and you do not know by how much |
| Rows stop before the period ends | Paused, ended, or the connection broke and nobody noticed | Do not average across it. The trailing days are not zeros, and a month-over-month drop built on them is fiction |
| One row per campaign for the whole range | You exported the default view, which is a period summary | Unknowable. There is no timeline in the file, so no gap can be seen. Re-export by day |
The fourth row is the one that catches people, including me. More on that below.
Why will the platform not tell you which one it is?
Because on Google it is documented behaviour, and it is deliberate. A day with nothing in it does not come back as a zero. It does not come back.
“Rows whose selected metrics are all zero won’t be returned.” And, on segmented reports: “Dates with no metrics are not returned in such a report.”
Google Ads API documentation, Zero metrics (retrieved 2 September 2026).
Read that twice, because it inverts the usual assumption
People assume the empty day arrives as a zero and the broken day arrives as nothing. On Google, both arrive as nothing. Every reporting layer above the API is then free to draw that absence as a zero, and most of them do.
So the visible zeros in your dashboard were frequently not measured. They were filled in.
And the daily breakdown is not the default on either platform
Meta’s Marketing API is explicit about it. The parameter that controls the time split has a documented default:
“Default value:
Meta Marketing API reference, Ad Account Insights,all_days[…] If ‘all_days’ is used, it means one result set for the whole period.”time_increment(retrieved 2 September 2026).
Google Ads behaves the same way in the interface. A report with no time segment is one total for the whole range, and adding the segment runs into a limit worth knowing:
“Note that you can only segment by ‘Day’ when your date ranges 16 days or less.”
Google Ads Help, Use segments in your tables (retrieved 2 September 2026).
Put the three together and you get the actual trap
The export you take by default has no timeline in it, so it cannot show a gap. The moment you add the timeline on Google, the days you most need to see are the ones that get removed. And a calendar month is longer than the 16 days the in-table segment will give you, so most people never take the daily view at all.
None of that is hidden. It is just spread across three pages that nobody reads together.
Check your own export
This runs entirely in your browser. Nothing is uploaded, there is no account, and no email is asked for. Drop in a CSV with one row per campaign per day and it will tell you which campaigns have gaps, and on exactly which dates.
If you hand it a summary export it will refuse and tell you what to change, rather than returning a verdict it has not earned. That refusal exists because of a real failure, described further down.
Drop a daily CSV export here
or . It never leaves your browser.
The logic is open source under MIT. The copy running on this page is the same file, inlined so it works with the page and with nothing else.
How do you export a daily breakdown?
Exporting by day is the one step that decides whether any of the rest is possible. You need one row per campaign per day, not one row per campaign.
Getting an export a coverage check can actually read
What the four verdicts mean
- trusted. No collection gaps inside the active period. Report these totals as they are.
- suspect. Days reporting exactly zero, sitting between active days. Not provably broken, and worth a look before you quote the average.
- gaps. Dates missing entirely from inside a run of activity. Any total spanning them is understated by an unknown amount.
- stopped. Reporting ends before the period does. The trailing days are not zeros, so both the total and the trend are wrong.
A campaign that launched mid-period is not flagged. Only gaps inside a run of real activity count, because everything before a launch is genuinely absent and correctly so.
Want this run across every campaign in both accounts instead of one file? Free read →
What this cost me to learn
In 2025 I spent more than 10,000 euros of my own money on ad management platforms. Not a client’s money. Mine.
What they gave back was the commentary the ad platforms already show you inside their own interfaces. Not one of them ever said “three days are missing from this month, so do not trust the total”. I do not think any of them were checking.
So I built the check. Then I pointed it at real exports, and it was the tool that turned out to be wrong.
Three defects, and the first one is the one that matters
- It passed a file it had never checked. The default export from both platforms is a period summary. Meta repeats one date range on every row, so the analysis saw a single day where everything was present and returned trusted. A clean bill of health on a file with no timeline in it. That is worse than an error, because an error stops you.
- A Clicks column could be read as the date column. In JavaScript,
new Date('490')does not fail. It parses as the year 490. I re-ran it while writing this page:'2026'gives 2026,'490'gives the year 490,'12'gives 2001, and'31'is the only one of those that comes back invalid. A column of small integers looks enough like dates to be picked as the timeline. - Spend was missed on Spanish exports, and budget was counted as activity. The header is Importe gastado, which does not contain the word the matcher looked for. Meanwhile budget, CPM and cost-per-result were being read as evidence of delivery. Counting a budget hides gaps by construction: a campaign with a budget set and no delivery looks active, and its gap disappears.
The first one is the failure this whole page is about
An instrument that cannot measure has to say so. Silence gets read as a clean result, which is exactly the confusion between a zero and a gap, one level up. The tool now refuses a summary export and tells you what to re-export.
The same mechanism bit me building the change-history import. The first run pulled four identical rows, and the impact sat on “measuring” forever because one campaign arrived with two different internal references. The join returned nothing and said nothing. Details of that window are in Google Ads change history.
You found a gap. Now what?
In the order that actually helps.
- Stop quoting the total, before anything else. A number you will defend in a meeting that happens to be wrong is more expensive than a number you did not have. Say the range is incomplete and give the dates.
- Establish which kind of gap it is. Check the campaign status and the change log for those exact dates. A pause leaves a trace. A broken connection usually does not.
- Check whether the gap is one campaign or all of them. One campaign is an account event. Every campaign on the same dates is a pipe, and the pipe is yours or your reporting vendor’s.
- Do not backfill from a second source without saying so. Patching Monday from another tool with a different attribution model produces a complete-looking series that is now internally inconsistent. Leave the hole and label it.
- Write down what you expected to find before you look. This is the same discipline as deciding from memory, and it is the only thing that stops a gap becoming a story.
The uncomfortable part, and it goes against us
The strongest argument against this page came from an operator who had the problem and did not want it solved.
“I didn’t explain properly. The 5x conversions in event manager are real. Not duplicated. Campaigns are massively under reporting.”
u/Resident_Age_8399, r/FacebookAds, 14 August 2026. Same voice bank.
He was living with a five to one gap between two official screens of the same platform. He mentioned it in passing, and the question he actually wanted answered was about something else entirely.
A hole that nobody experiences as a hole is the honest counter-signal. Most operators do not experience a measurement hole as a hole, so a tool that finds holes is answering a question they have not asked yet. I think they are wrong about that, and I am aware that thinking so is not evidence.
What I still do not know
- Meta does not document the omission either way. Google states plainly that all-zero rows are dropped. I could not find the equivalent statement in Meta’s Insights documentation, and its help pages do not return readable text to the tools I use. What I have on the Meta side is behaviour observed in real exports, not a published rule, and those are different grades of evidence.
- Nothing here separates a pause from a broken connection. The file looks the same either way. The check tells you where to look, and then a human has to look.
- I do not know how common this is. I have found gaps in the accounts I have checked. I have no sample that would let me say what share of accounts carry one in a given month. I would not trust a number I made up for that.
- A daily export is still one platform’s account of itself. If the platform never recorded an event, no coverage check on its own export can see the absence. This finds gaps in the record, not gaps in reality.
Related reading. Marketing attribution: why two tools give different numbers for the same week, and the four dials behind it. Google Ads change history: the thirty-day API window, and why there is no backfill. What is a good ROAS: the conversion volume below which no comparison is readable. Incrementality testing: what a held-back group answers that a report cannot. Marketing report template: the definitions header that stops a number being misread out of context.
Why is my Google Ads report showing 0?
Either the campaign delivered nothing that day, or that day never reached your report. The two are not distinguishable from the number itself. Google Ads API documentation states that rows whose selected metrics are all zero are not returned, so a genuinely empty day is usually removed rather than shown as a zero. A visible zero often comes from a reporting tool filling the gap in.
What is the difference between a real zero and missing data?
A real zero is a day that was measured and had no activity, so the total that spans it is correct. Missing data is a day that was never collected, so the total that spans it is understated. The first is reportable. The second is not, until you know why the day is absent.
How do I export Google Ads data broken down by day?
In the statistics table, use the segment icon and choose Time, then Day. Google Ads Help notes you can only segment by Day when your date range is 16 days or less. For a month, use the report editor or a scheduled report instead. Download as CSV with one row per campaign per day.
How do I export Meta ads data by day?
In Ads Manager, set Breakdown to Time and then Day before exporting. Through the Marketing API the equivalent is time_increment, whose documented default is all_days, meaning one result set for the whole period. The default export in both places is a period summary with no timeline in it.
Why do my ads reporting numbers not match?
There are two different causes and they need different fixes. Attribution disagreement comes from two tools using different models and windows on the same events, and it never fully resolves. A collection gap is a day that is simply absent, and it can be found and fixed. Check for the gap first, because it is the cheaper question.
Can a reporting tool tell me if data is missing?
Most will not, because they render an absent day and an empty day the same way. A missing day only becomes visible when you compare the dates present in the file against the dates you expected. That comparison needs a daily export, which is not what either platform gives you by default.
Is a campaign that stops reporting mid-month paused or broken?
The export cannot tell you, and neither can any tool reading it. Both look like data that simply ends. What you can establish is that the trailing days are not real zeros, so any total or average that includes them is wrong. Then check the campaign status and the connection separately.
Last updated:
Who wrote this
I am Manu. I have been buying media for eight years, and I got tired of reporting that is confident by default. So I started building an open-source console that reads my Meta and Google data, tells me when a period is incomplete, and changes nothing I have not approved. It is Apache-2.0, with a runnable demo on synthetic data. If you would rather have the gap check run across your real accounts than paste one file at a time, the audit below does that and changes nothing.