What we find
Twenty-six ways an account quietly loses money.
None of them announces itself and all of them are boring to look for, which is why the same budget returns less this quarter than last. 7 run today — the table says which.
What you get back
A list of problems is not worth anything. A list with prices on it is.
Every audit tool hands you findings. What decides whether any of it was worth reading is which one to do first — and that is a question about money, not severity.
$5,730
5
- CriticalCritical severity$3,180/mo
Brand terms are being bought by two campaigns at once
search-terms/brand-overlap412 terms · 19% of spend
- HighHigh severity$1,450/mo
Three asset groups are below the headline minimum
pmax/asset-group-thin3 of 7 groups · 4 headlines each
- HighHigh severity—
Two conversion actions record the same submit
conversions/double-countedForm_Lead · Contact_Thanks
- MediumMedium severity$890/mo
Search — Core lost 22% impression share to budget
budget/capped-searchLost IS (budget) 0.22 · 28d
- LowLow severity$210/mo
Presence-only targeting is off on two campaigns
geo/spill2 campaigns · 6% of clicks out of area
The list
All twenty-six, and what each one is costing somebody right now.
7 of the 26 run today — the last column says which, and both numbers are counted from the code rather than typed. The key beside each check stays the same week to week, so you can follow one and see whether it came back.
| What goes wrong | Why it costs you | Read from | Runs |
|---|---|---|---|
You are bidding against yourselfbrand-overlapSearch terms | Two campaigns buying the same brand terms, so you are the competition that pushed your own price up. You pay the higher click and the conversion was yours either way. | search_term_view | Not yet |
Paying for searches that never convertsearch-term-wasteSearch terms | Terms that have taken real spend across the window and returned nothing, ranked by what they cost. This is usually the largest single number in a first review. | search_term_view | Today |
Buying traffic you then blocknegative-conflictSearch terms | A negative keyword blocking a keyword you are actively bidding on. You pay to compete for the auction and then refuse the click it wins. | campaign_criterion | Today |
The same keyword in two placesduplicate-keywordKeywords | Only one of them can serve, and the other quietly splits the performance history that decides what you pay for the position. | keyword_view | Today |
Broad match buying the wrong intentmatch-type-driftKeywords | Terms arriving that share no intent with the keyword that bought them — the clicks are real, the buyers are not, and the spend lands in the campaign you judge by conversions. | search_term_view | Not yet |
Paying more for the same positionquality-score-dropKeywords | Quality Score falling on keywords that still carry spend. Nothing about the campaign changed except the price of every click in it. | keyword_view | Not yet |
Clicks landing on a broken pagelanding-page-mismatchAds | Final URLs that redirect, 404, or land somewhere the ad did not promise. The click is billed whether or not the page loads. | ad_group_ad | Not yet |
One conversion counted twiceconversion-double-countConversions | Two actions recording the same submit, which inflates every ratio the bidding strategy optimizes against — so the algorithm buys more of whatever produced the phantom. | conversion_action | Not yet |
Bidding towards a conversion that stopped firingconversion-action-staleConversions | A primary conversion action that has not fired all window, usually a tag removed from the site. Smart bidding is still chasing it. | conversion_action | Not yet |
Conversions measured two different waysattribution-mismatchConversions | Attribution models or lookback windows that differ between actions feeding one bid strategy, so the strategy is comparing numbers that are not comparable. | conversion_action | Not yet |
A winning campaign cut off earlybudget-cappedBudget | A campaign hitting its daily budget and losing impression share it was winning on rank. You were beating the auction and stopped showing up for it. | campaign_budget | Not yet |
A profitable campaign held down by an old numberbudget-starvedBudget | Budget set far below what the campaign could spend at its own target. The ceiling is not a strategy, it is a figure nobody revisited. | campaign_budget | Not yet |
A bid strategy that never gets to settlebid-strategy-churnBidding | A strategy or target changed again before the last learning period finished. Every reset spends real money re-learning what it had almost worked out. | change_event | Not yet |
A target the campaign has never hittarget-cpa-unreachableBidding | A target CPA set below anything in the campaign's history. It does not lower your cost, it throttles delivery until the campaign stops mattering. | campaign | Not yet |
Impressions you were winning and stopped gettingimpression-share-lostBidding | Lost impression share split into the part budget caused and the part rank caused. They need opposite responses, and doing the wrong one costs twice. | campaign | Not yet |
Asset groups too thin to serve everywhereasset-group-thinPerformance Max | Groups below Google's own minimums, which caps the placements they are eligible for. You are paying for a campaign that is only allowed to compete in part of its inventory. | asset_group | Not yet |
Disapproved assets holding a slotasset-rejectedAssets | Rejected or limited assets still sitting in rotation, occupying a position that serves nothing while the ones that work fight over what is left. | asset_group_asset | Today |
The same headline over and overheadline-duplicationAssets | Repeated headlines across responsive ads collapse the number of combinations that can be assembled, so the system has far less to test than the asset count suggests. | ad_group_ad_asset_view | Not yet |
Free space on the results page left emptysitelink-missingAssets | Campaigns running without sitelinks. The space costs nothing, takes the click-through rate with it, and a competitor is using it. | campaign_asset | Today |
Asset types missing, campaign by campaignextension-coverageAssets | Which asset types are present against which are available, per campaign rather than per account — because an account-level average hides the campaign that has none. | campaign_asset | Today |
Paying for clicks outside your areageo-spillTargeting | Clicks billed from outside the region you targeted, with the share of spend they account for. Nobody in that list can buy from you. | geographic_view | Not yet |
Buying people who searched about a placepresence-only-offTargeting | Location targeting left on presence-or-interest, which is the default and is not what you meant. You are paying to reach people reading about your city, not people in it. | campaign | Today |
Ads running when nobody answersschedule-blind-spotTargeting | Hours and days that take spend and return nothing. For anyone whose conversion is a phone call, this is the cheapest money on the list to stop spending. | campaign_criterion | Not yet |
A device converting differently, bid the samedevice-bid-gapTargeting | A device converting at a materially different rate with no adjustment against it, so you pay the same for traffic worth measurably less. | campaign_criterion | Not yet |
Audience lists built and never usedaudience-unattachedTargeting | Lists collecting data that no campaign is observing or bidding on. The work was already done and none of it is reaching the auction. | ad_group_audience_view | Not yet |
Clicks arriving untrackedtracking-template-brokenTracking | Tracking templates producing a redirect chain or dropping the parameters your analytics needs. The spend is real and the attribution for it is gone. | campaign | Not yet |
Why you can trust the list
A review you cannot reproduce is an opinion with a number attached.
Ask a model to audit an account twice and you get two different audits — no way to tell which run was wrong. Fine for exploring, useless for acting on.
- gaqlSELECT search_term_view.search_term, metrics.cost_micros …
- run_pythonmewads.run_audit(manifest, profile)
- run_pythonbrand_overlap(terms, profile.brand_tokens)
- gaql… WHERE campaign.id IN (17 ids) AND segments.date …
- propose_change_set4 operations · validate-only
And is the change worth making
Knowing what is wrong is not the same as knowing what to do about it.
A check can tell you that 412 search terms overlap with a brand campaign. It cannot tell you which of the two should keep them.
| Resource | Field | Current | Proposed | Decision |
|---|---|---|---|---|
| Search — Brand | negative_keyword | — | +412 terms | Approved |
| Search — Core | campaign_budget.amount_micros | $120.00 / day | $168.00 / day | Approved |
| PMax — Retail | asset_group.headlines | 4 headlines | 11 headlines | Pending |
| Search — Core | geo_target_constant | everywhere | 3 metros | Rejected |
Find out which of these are costing you.
Seven days, one full review, nothing charged until day seven. The connection is read-only, so the worst case is a list you disagree with.