Translated from the Japanese original on mureo.jp.
Once you start pulling ad numbers with an agent or a script, you keep running into cases where they do not match what the platform UI shows. Clicks are off by a few dozen, conversions are short only for yesterday, the reach of each campaign does not add up to the account total. Each time, you suspect the pull and investigate again, and most of the time it turns out the pull was not wrong; the two sides were counting different things.
The causes of a gap fall roughly into four: the metric definition, the date a result is attributed to, reporting delay and later corrections, and metrics that cannot be summed. This article lays out a procedure for checking those four in order, together with how large the gaps were when we actually measured our own ads and tracking. The second half goes as far as the conditions to have an agent output along with the numbers when you hand it the pulls.
The broader picture of handing ad ops to an agent is in Can you automate ad ops with Claude Code?
How large the gaps were in our own numbers
Rather than starting from generalities, first look at how much things actually diverge. The values below were pulled again for this article: the Meta Ads we ran for this site from July 27 to August 10, 2026, the web analytics for the same period, and Search Console for the most recent 30 days.
| What was compared | One value | The other value | Difference |
|---|---|---|---|
| Meta Ads link clicks vs landing page views | 879 | 610 | About 31% fewer |
| Sessions GA4 attributed to the ads, same period | 822 | (landing page views 610) | GA4 about 35% higher |
| Same campaign: the clicks field vs link clicks in the action breakdown | 701 | 732 | 31 |
| Sum of reach by campaign vs account-level reach | 28,780 | 28,857 | 77 people |
| Search Console: sum of daily impressions vs sum of impressions by page | 1,252 | 1,302 | 50 |
| Same: sum of impressions by query | 578 | (daily sum 1,252) | More than half do not appear as a query |
In every row, the pull is working correctly. Neither side is wrong; what is being counted, or how it is aggregated, differs. The sections below go through which cause each row falls under.
The public records of people running their own ads contain the same kind of story. An operator at a brand who switched to pulling Amazon Ads directly through the API wrote that the search term report from the third-party tool they had been using covered only 39% of spend, and through the API it was 100%. They also listed that the day boundary was in a different time zone from what they had assumed, and that sales had to be taken from the sales report rather than the orders endpoint. This record is public on X, and we have not verified the writer’s line of business.
The metric definition differs
The most common gap is two things that look like the same name but count different things. Taking Meta Ads as the example, link clicks are the number of times the link in the ad was pressed, and landing page views are the number of times the page behind it loaded and Meta’s pixel fired. People who went back after pressing but before the page opened, or whose pixel loading was blocked, are counted only in link clicks, so landing page views come out lower. In our case it was 610 against 879.
Web analytics sessions count in yet another way. GA4 counts it as a new session when the same person comes back after a gap, so there were 822 sessions from the ads against 775 users. Sessions exceeding landing page views continued almost every day of the delivery period. Neither number is wrong; it is the difference between arrivals Meta confirmed with its own pixel and visits GA4 counted with its own tag.
Gaps also happen within the same response from the same platform. The third row of the table is a case where the clicks field returned by the Meta Ads API was 701, while link clicks in the action breakdown of the same response were 732. The two are fields aggregated separately, and the action breakdown side is counted according to the ad set’s attribution setting. We have not isolated which mechanism this particular gap came from, but at the very least you cannot treat the two as the same thing just because both are called “clicks”.
In Google Ads, cost being returned in a unit called “micros” also falls under definition differences. The API’s cost field is an integer multiplied by one million, so if you put it straight into a table the digits are off by six. If the first numbers an agent pulls are off by orders of magnitude, suspecting this first gets it sorted quickly.
The date a result is attributed to differs
The number of conversions changes depending on which day you count them on. There is counting that attributes them to the day the ad was shown or clicked, and counting that attributes them to the day the conversion happened, and when the platform’s default and the conditions you specified in the API disagree, the daily numbers do not match.
Conversions in Google Ads reports are, by default, attributed to the day of the interaction, such as a click. If someone clicks on Monday and enquires on Thursday, that one conversion goes into Monday’s column. The API has a separate metric that counts by the day the conversion happened, and using it puts it into Thursday. Depending on which you pulled, the daily numbers in the middle of a week change a lot.
The Meta Ads API lets you specify whether actions are attributed to the time the ad was shown or to the time of the conversion. The attribution window (how many days after a click, and how many days after a view, count as a result) may also not line up with the window you are looking at in the UI unless you specify in the API that the ad set’s setting should be used. When comparing numbers in the UI with numbers from the API, first check that these two conditions are the same on both sides.
Time zones are also a kind of date gap. The platform’s report divides days by the time zone set on the ad account, and web analytics divides them by the time zone set on the property. If either is left on UTC, everything up to 9 a.m. Japan time goes into the previous day. This is the kind of gap the Amazon Ads operator mentioned earlier was describing.
Reporting delay, and later corrections
The most recent numbers are not yet final when you pull them. In this site’s GA4, the previous day’s engagement metrics come back as 0 when pulled the next morning, and have values when read two days later. Session counts themselves can also increase later for the previous day; over 11 days of the delivery period, comparing the value read the next morning with the final value for the previous day, the correction rate varied from day to day, from 0% to 160%. There is no fixed ratio by which you can correct the previous day to get the final value.
Search Console numbers come in two to three days late. On ad platforms as well, clicks judged invalid are removed afterwards, and conversions that happen late within the attribution window are added to past dates, so the numbers for a few days ago change a little every time you pull them.
What follows from this is to leave the most recent days out of what you reconcile. If you compare including yesterday and the day before, most of the gap can be explained by delay, and real definition differences or pull errors get buried. It is safe to close the comparison window at three days ago at the latest.
Metrics that cannot be summed, and rows that do not appear in the table
Reach is a deduplicated count of people, so summing the values by campaign does not give the account-level value. If the same person saw ads in two campaigns, the sum counts 2 people and the account level counts 1. So normally the sum is larger than the account level, but in our case the account level of 28,857 was 77 people more than the sum of 28,780. Meta’s reach is calculated as an estimate, so movement up or down of this size can happen. Reach and frequency are metrics you pull fresh at the granularity you want each time, not ones you build by summing from a lower granularity.
Search Console has two kinds of gap. One is the unit of aggregation: counted for the whole site, multiple pages appearing in the same search result count as 1, but counted by page, each page counts 1. This is why the sum by page came to 1,302 against a daily sum of 1,252. The other is anonymization: search queries with low counts do not appear in the table as queries. The sum by query was 578, meaning for more than half of impressions it was unknown which query they appeared for. If you build the overall number by summing the by-query table, you get less than half of the actual figure.
The order for reconciling
When numbers do not match, checking in the following order gets you to a likely cause quickly.
- Align the window: check the start and end of the period, the time zone, and whether the most recent two to three days are included.
- Align the definitions: check that a metric with the same name counts the same thing on both sides. The closer the names, like clicks and link clicks, or landing page views and sessions, the more you should suspect them.
- Align the attribution conditions: are conversions counted on the day of the interaction or the day they happened? Is the attribution window the same on both sides?
- Align the unit of aggregation: are you summing reach or impressions from a lower granularity? Are there rows dropped by anonymization?
- Only what still differs after all this gets investigated as a pull error: few gaps remain at this stage, and those that do are often a mistake in writing the pull conditions, or rows missed in pagination.
Gaps explained by steps 1 to 4 do not need fixing. What needs fixing is the situation where the person comparing does not know about the difference and treats them as the same number.
The conditions to have an agent output when you hand it the pulls
Whether you can later reconcile the numbers an agent produced depends on whether the pull conditions are kept along with the numbers. If you receive only the numbers, then when they do not match the UI, the only way to find out which of 1 to 4 above applies is to pull again.
When you have Claude Code connect to an ad platform’s API and pull numbers, have it attach at least the following to its report:
- The start and end of the period, and the time zone that divided the days
- The official name on the platform of the metric pulled (not “clicks”, but which field)
- The attribution date for conversions, and the attribution window
- The unit of aggregation (account, campaign, ad set), and whether the value was built by summing from a lower granularity
- The time of the pull, and whether it includes days that are not yet final
All five of these can be pulled with read-only access. Pulling and reconciling numbers needs no write access, so, as written in How much of ad ops to hand to Claude Code, it is easy work to put at the first stage of delegation. In mureo, every operation an agent calls is recorded with its timestamp, arguments and result, so you can trace afterwards under which conditions a reported number was pulled.
How to check that tracking itself is working is in Checking whether ad conversion tracking is working, and reconciling your change record against the platform history is in Keeping your own change log for ad accounts. Both are work to align the premises before you read the numbers.
Where people get stuck reconciling numbers
Deciding on the previous day’s numbers
If you read the previous day’s numbers in the morning, neither conversions nor engagement have fully come in yet. When the previous day looks bad, it is often because of delay, and if you move bids or budgets at that point, you end up reversing the decision once you see the final numbers.
Forgetting the column settings in the UI
If you compare without checking whether the columns shown in the UI are columns with a changed attribution window or the default columns, the numbers will not match however much you fix the API side. Writing down the conditions on the UI side before comparing keeps you from getting lost.
Treating the platform’s numbers and your own CRM counts as the same thing
The conversions a platform counts include your own test submissions and bot submissions. Conversely, enquiries that happen outside the platform’s attribution window are not counted by the platform. Read them with separate roles: the platform’s numbers as values used for optimizing delivery, the CRM count as the actual number of prospects.
Throwing one side away because they do not match
Just because GA4 sessions are higher than landing page views, there is no need to throw either away as wrong. If the direction and size of the difference are roughly the same every day, both are reflecting the same changes through different ways of counting. A day when the difference suddenly widens is the better reason to suspect a tracking fault.
FAQ
Which is correct, the numbers in the UI or the numbers pulled through the API?
In most cases both are correct, and the conditions being counted differ. Align four things (the period and time zone, the metric definition, the attribution date and window for conversions, and the unit of aggregation) and most gaps are explained. Only gaps that remain after aligning the four are candidates for suspecting a pull error.
Why do Google Ads conversion counts increase later for some days?
The default conversions column counts by attributing to the day of the interaction, such as a click. So conversions that happen a few days later are added to past dates, and the numbers for past days increase afterwards. If you use the metric that counts by the day the conversion happened, the numbers for past days move less.
Can I sum Meta Ads reach from the values for each campaign?
Do not sum them. Reach is a deduplicated count of people, so if the same person was shown ads across campaigns, the sum comes out larger. If you need account-level reach, pull it again at the account level. Meta’s reach is an estimate, so the sum and the account level can also come out the other way round.
Why does summing Search Console numbers by query give less than the total?
Search queries with low counts are anonymized to prevent identifying individuals, and do not appear in the by-query table. On this site over the most recent 30 days, more than half of impressions did not appear as a query. For total impressions, use the value pulled without specifying a query.
How often should I reconcile?
The basics are to reconcile row by row against the UI once right after building the pull setup, and once whenever you change metrics or conditions. After that, looking once a week at whether the direction and size of the difference are the same as usual is enough. Only in a week when the difference suddenly widens, check the cause using the reconciliation order above.
Summary
When the numbers in your ad reports and those pulled through the API do not match, the cause is mostly not a pull error but one of four things: the metric definition, the date and time zone a result is attributed to, reporting delay and later corrections, or metrics that cannot be summed. In our own case, too, there were gaps of about 31% between link clicks and landing page views, 50 between Search Console’s daily and by-page figures, and more than half of impressions not appearing by query, and in every case the pull was working correctly.
Reconcile by aligning the window, the definitions, the attribution and the unit of aggregation in that order, and investigate only the gaps still remaining as pull errors. If you hand the pulls to an agent, having it output the period, the official name of the metric, the attribution conditions, the unit of aggregation and the time of the pull along with the numbers lets you get back to the cause without pulling again when they do not match. This work is complete with read-only access.
Related guides
- Can you automate ad ops with Claude Code?
- Checking whether ad conversion tracking is working: what is set up, and the path the numbers take
- Keeping your own change log for ad accounts: the reason behind a change, which the platform history does not keep
- How much of ad ops to hand to Claude Code
- Connect Google Ads to Claude Code
- Connect Meta Ads to Claude Code
- Connect Amazon Ads to Claude Code
- Can you trust the ad numbers an AI agent gives you? Checking which account, which period, and what was counted