Run one account audit. Keep the watch with a plan.
Connect Google Ads with no card and run one deterministic audit for that eligible account. It names the checks that fired and changes nothing. Repeat audits, scheduled monitoring and alerts require an active trial or plan. Every proposed account change still waits for exact approval.
Google's consent screen asks for Ads management access. Sable Mako enforces read-only behavior until you turn writes on, and exact approval is still required.
Demo account · illustrative figures
- Connect an eligible Google Ads account and run one deterministic audit without a card.
- A trial or plan keeps repeat audits, daily monitoring, alerts, Mako and approved publishing available.
- If ongoing service ends, new reads stop and the reports already stored in your workspace remain visible.
The commitment is written down. Our terms state the same boundary: one initial deterministic audit is included per eligible account, while repeat audits, monitoring, alerts and AI require an active trial or subscription. A test reads that clause and the server gate together.
The standing watch
You cannot check every campaign every day. Mako can.
On an active trial or plan, each eligible connected ad account gets one full read a day, in your brand's own timezone, from 07:00 local. Platform conversion figures keep settling after that, so every finding carries its measured window and pull time. The read spends no credits and calls no language model: the checks are arithmetic, and an import-graph test fails the build if any part of the sweep starts importing a model client.
Product view · demo data · nothing was changed; scheduled reads require active service
Section 03 · every check, named
Eleven checks on a Meta account. Eleven on a Google Ads account.
Connect both and you get two audits, two histories and two alert streams, because the numbers are not comparable across platforms and an alert about one says nothing about the other. Every check below names the rule that fired and the bar it was judged against.
| Check | What it catches | The bar | Where the bar comes from |
|---|---|---|---|
account.status | The ad account itself is not active: billing hold, disabled, or under review. | Any account status other than active. | Platform state |
account.not_delivering | A campaign reads active but Meta is not delivering it: disapproved, in review, ad set paused, or waiting on billing. | The effective status disagrees with the configured status. | Platform state |
tracking.zero_conversions | Real sales spend, and no purchase recorded anywhere in the account. | Sales spend clears the money floor and purchases are zero. | Fixed floor of US$50, converted into your billing currency |
budget.wasted_spend | Delivering sales campaigns that spent and bought nothing. | Zero purchases, spend over the floor, campaign at least 4 days old. Critical once those campaigns hold 10% of live sales spend. | Fixed floor and fixed age guard |
budget.sub_target | Converting campaigns returning under your target return on ad spend. | Those campaigns hold 25% of live sales spend, critical at 50%. | Your gross margin, raised by your measured return rate |
budget.concentration | One campaign carrying too much of live spend. | 40% of live sales spend, and only once 3 or more live sales campaigns exist. Raised when the dominant campaign is itself under your target and holds 60%. | Fixed |
performance.reallocation | A clear winner and a clear loser running side by side. | Winner at 2x your target with 3 or more purchases; loser under target, at least 4 days old, with 3 or more purchases. Both over the spend floor. | Your target return, fixed multiple |
performance.cpa_outlier | A campaign paying far more per purchase than the rest of your converting campaigns. | 2x the average cost per purchase across your converting campaigns, with 3 or more purchases behind it. | Your own converting-campaign cost per purchase |
creative.frequency_fatigue | The same people seeing the ads too often. | Frequency of 2.2 over 7 days, 3 over 14, 4 over 30, 6 beyond. | Fixed, scaled to the window. Shipped as a heads-up to confirm against a falling click-through rate, never as a verdict |
structure.no_active_campaigns | Campaigns exist and none of them is running. | Campaign count above zero, active count zero. | Platform state |
structure.fragmentation | Budget spread too thin for the platform to learn on. | 8 or more active campaigns, with 5 or more of them each under 2% of active spend. | Fixed |
| Check | What it catches | The bar | Where the bar comes from |
|---|---|---|---|
tracking.google_zero_conversions | The account spent and recorded no conversion at all. | Spend clears the money floor and conversions are zero. | Fixed floor of US$50, converted into your billing currency |
budget.google_wasted_search_terms | Search terms that took clicks or money and converted nothing. | A term is dead at 3x the clicks your account normally needs to buy a conversion, bounded 10 to 300 and falling back to 25 when there is nothing to derive from, or once it cost more than 2x what a conversion costs you. The account-level alarm fires once those terms hold 10% of search spend, critical at 25%. | Your account's own arithmetic, fixed multipliers |
budget.google_sub_target | Campaigns converting but returning under your target return on ad spend. | 3 or more conversions each, holding 25% of live spend, critical at 50%. | Your gross margin. Reports itself unavailable, in writing, when the account records conversion counts but no conversion value |
structure.google_no_active_campaigns | Campaigns exist and none is enabled with spend. | Campaign count above zero, delivering count zero. | Platform state |
structure.google_duplicate_keywords | The same keyword bidding against itself in two ad groups of one campaign. | Same text and match type, both enabled, each past 5x your account's average cost per click. | Your account's own cost per click |
budget.google_wasted_campaign | A whole campaign that spent real money and bought nothing, once it is past its ramp. | Zero conversions on 2x what a conversion costs you, or the money floor, whichever is higher, and older than 7 days on Search or Shopping and 21 days on Performance Max or Demand Gen. | Your account's own cost per conversion. Reports itself unavailable, in writing, when Google returns no start date to age the campaigns by |
budget.google_lost_to_budget | A campaign already clearing your profit bar that ran out of budget before it ran out of demand. | At least 10% of its available impressions lost to budget, clearing your target return on 3 or more conversions, serious at 30%. Never raised on a campaign under target. | Your gross margin, and the campaign's own impression share. Capped below critical on purpose: this is headroom rather than a leak, and it must never be triaged above one |
performance.google_lost_to_rank | The other reason a campaign does not show up, where more budget buys nothing at all. | Losing more impression share to rank than 1.5x what the rest of your account loses, falling back to 40% when fewer than 3 campaigns reported a share, serious at 60%. | Your own account's median rank loss, clamped so it can only ever get harder |
budget.google_bid_target_below_profit_bar | A campaign told to aim for a return your margin cannot afford, so every sale it buys loses money by design. | A configured target return below 90% of your margin-derived bar, critical once those campaigns hold 25% of live spend. | Your gross margin and measured return rate, against the target set in the campaign. Campaigns on a shared bid strategy are named as not judged rather than accused, because their target is set outside the campaign |
budget.google_value_bidding_without_a_target | Value bidding left with no bar at all, long after the campaign had the history to carry one. | Past 7 days on Search or Shopping and 21 days on Performance Max, 3 or more conversions, and returning under your bar. Raised as minor: starting untargeted is a legitimate way to collect conversion history. | Your gross margin, and the campaign's own age and return |
tracking.google_no_primary_purchase_action | A purchase action that exists and is not the one Google is bidding toward, so the budget buys add-to-carts while the account looks healthy. | An enabled purchase or paid-subscription action with none of them marked primary for the account goal. Spending with no enabled conversion action at all counts the same way. | Google's own conversion action settings. Runs even when the tracking check has already fired, because it is often the reason, and reports itself unavailable when the list came back cut short |
One rule sits above all of these. If the tracking check fires, the budget and performance checks are dropped for that run and listed as skipped, with the reason attached. A broken pixel poisons every return and cost-per-purchase figure in the account, and a verdict computed on numbers we do not trust is worse than no verdict. The account, tracking, creative and structure checks still run.
A check that cannot look says so. Where a run has no search terms to read, no spend to judge, or no conversion value to compute a return from, that check reports itself unavailable with the reason in plain language, and the reason appears in the report. Nothing silently scores well because it was never assessed.
Section 04 · one finding, in full
This is a finding. The words are written in code, so they cannot be talked up.
budget.wasted_spendUSD 1,840 spent with zero purchases (14% of live spend)
3 live sales campaigns spent USD 1,840 and recorded no purchases. The worst is "Prospecting-TOF-Broad" at USD 920.
Do thisPause or fix these. If they should convert, check the pixel, offer, and audience before spending more.
- metric
- spend
- value
- USD 920
- scope
- Prospecting-TOF-Broad
- window
- last 30 days
- pulled
- stamped on the audit when the read completed
Every word above except the campaign name and the figures is written in this codebase. No language model writes a finding, a severity or a score. That is why the same account on the same data produces the same finding twice, and why a finding cannot be softened, embellished or invented.
The severity is arithmetic. This one is critical because those campaigns hold 14% of live sales spend and the line is 10%. Below the line the same finding is major. Nothing about the wording changes.
Every number a finding cites is checked against the data pulled in that run. The check is scope-aware, so a figure cannot be grounded against a different campaign, and matching is strict, so a hundredfold unit error cannot pass as a rounding difference. A figure that does not trace raises a grounding warning in our logs for us to fix. It does not block the finding from being stored today, and this page will keep saying so until it does.
The account gets one score out of 100, weighted by category. budget 28%, performance 22%, tracking 16%, account 12%, creative 12%, structure 10%. Each high-confidence critical takes five points off, capped at fifteen. The score is computed by our server from the findings, never supplied by a model.
Section 05 · where the bar comes from
Judged against your account. Not against an industry average.
There is no universal answer to how many clicks with nothing to show is too many, or what return on ad spend counts as profitable. Both depend on your business, so both are computed from your own numbers, and every finding prints the basis it used so you can argue with the right thing.
Your profit bar, from your margin
Your target return on ad spend is one divided by your gross margin, so a 60% margin means a campaign has to return 1.67x to cover its own ad cost. If your Shopify store is connected and has at least 21 days of data, we measure what actually came back and raise the bar: at a 20% return rate the same brand's real bar is 2.08x, and a campaign at 1.8x that looked profitable is losing money. A measured return rate above 60% is treated as broken data and refused rather than used.
Your click economics, from your account
The Google bars are ratios applied to your own numbers rather than fixed counts. If your account converts once every 40 clicks, a term needs 120 clicks with nothing to show before it counts as dead. If you convert every 8 clicks, it needs 24. Every derived bar carries a sentence saying which basis it used, and that sentence is printed inside the finding.
The floors that do not travel, marked as such
Some numbers are fixed on purpose and we say which. The 4-day age guard is a judgment rule: a campaign that young is unstable by design, its numbers forecast nothing, so the audit refuses to call it a loser and says it is too young to read. The 3-purchase minimum exists because one order can swing a return figure. The US$50 money floor is converted into your billing currency before it is applied, because a flat fifty meant about half a US dollar to an Indian advertiser and about 162 to a Kuwaiti one.
If you have not set a margin, the audit still runs. It falls back to breakeven on ad cost, records that it did, and the stored report says which bar it judged against, so a reader months later can tell an ad-cost audit from a profitability one instead of assuming. Withholding the whole product until somebody fills in a number they may not know is a worse answer than running and being honest about what could not be judged. Every bar the audit and the agent judge against, and where each one's number comes from, is tabled on the diagnosis page.
Section 06 · how wasted spend is computed
The exact sum. And the three things we refuse to add to it.
wasted spend = sum of spend on campaigns where the campaign is delivering and spent in the window the objective is sales purchases = 0 spend >= the money floor (US$50, in your currency) campaign age >= 4 days critical when that total >= 10% of live sales spend
Click-to-WhatsApp and Messenger campaigns are excluded. Meta files them under a sales objective and they record messaging conversations rather than purchases, so counting them would flag a working campaign as dead and would also report the account's tracking as broken.
wasted search spend = sum of spend on search terms where conversions = 0 and either clicks >= 3x your account's clicks per conversion or spend >= 2x your account's cost per conversion reported only when that total clears the money floor and holds >= 10% of search spend (critical at 25%)
The search-terms report is read in capped pages. Where it was capped, the finding states the figure as at least that much and says the real total is higher. A floor you can trust beats a total we guessed.
Three things could inflate that number and none of them belongs in it.
Spend on campaigns returning under your target is a different quantity. That money bought something. Moving it is a judgement about where budget should sit, not a recovery, so it is reported as its own finding with its own figure.
Frequency, fragmentation and concentration findings carry no money figure at all. The money at stake in them cannot be computed without guessing, so they carry the count and the share instead and stay silent about dollars.
There is no cross-platform total and no monthly or annual projection. Meta wasted spend and Google wasted search spend are reported separately, per finding, per window, because that is the grain at which each was actually measured. Two platforms in two currencies with two denominators do not add up to a number that means anything.
Section 07 · what lands in your inbox
You hear from it when something changed. Not every morning.
The audit runs every day. The alert does not. Each scheduled run is compared against the last scheduled run for that same account, by check id. You are alerted when a finding is new or when its severity got worse, and not otherwise. A finding that resolved does not alert. A finding that is unchanged does not alert.
The first run for a connection is a baseline and never alerts. A first look at an account has nothing to compare against, so treating everything it found as new would make the one email you were most likely to read the least useful one.
The comparison deliberately ignores which campaign was the worst example. A finding's identity across runs is its check id alone. A leak that persists while its worst offender changes week to week is one ongoing problem, not a new one every Tuesday.
The email is plain text. Severity, the finding title, the recommendation, a link to the full audit, and a one-click unsubscribe in the header as well as the body. Turning the email off in Settings stops the email. The audit still runs, the finding still lands in the app, and the in-app alert is written whether or not the email is on.
Section 08 · what it will not do
What it will not do. Written down, so you can hold us to it.
- It does not change anything. Scheduled reads are read-only. Nothing in the monitor writes to a platform. The write path is a separate switch you grant per account, and even with it on, every individual change waits for you to approve it on its own card.
- It does not propose anything on a schedule. The monitor writes findings, a diff and an alert. It never queues a change for you to wake up to.
- It does not write you prose unless you ask. A scheduled run stores findings and numbers and makes no model call at all. The plain-English write-up of an audit is a button you press, and that one is part of the subscription.
- The audit page starts with Google Ads. The controlled beta offers Google Ads accounts. Existing Meta test connections may also be audited for supervised validation, but Meta is not an ordinary beta connection while app review remains open.
- A lead-generation advertiser gets less of it than a store does. The profit checks assume purchases and a gross margin, and campaigns that convert in a chat rather than on a website are excluded from the Meta sales universe on purpose. If you run messaging or form-fill campaigns you still get the account, tracking, creative and structure checks, and the wasted-spend and return checks will have little to judge. We would rather say that here than have you find it out after connecting.
- It does not audit GA4 or Search Console. GA4 has a read-only traffic-source path and Search Console a read-only search-query path, both open to the controlled beta and read nightly and live in chat. Neither is an advertising audit engine, and no audit check reads either.
- It does not audit Shopify. Your store feeds the revenue side and the return-rate measurement that sets your profit bar. There is no commerce audit. Shopify is read-only today: no write permission is requested and no write path exists in our code.
- It does not settle yesterday by breakfast. Ad platforms keep attributing conversions for days after a day closes, so a figure read this morning can move. Nothing here pretends otherwise: every finding carries the window it was measured over and the moment the data was pulled, and the diff that decides whether to alert you compares one scheduled run against the previous one rather than against a moving target.
Section 09 · what it needs and what it can touch
What it needs, and what it can touch.
| Platform | What it reads | What it can change | Write switch |
|---|---|---|---|
| Meta Ads | Account status and currency, campaigns, spend and performance insights, ads and creative thumbnails. | Pause or activate a campaign, set a campaign daily budget, move daily budget between two campaigns or two ad sets in the same account. | Off until you turn it on, per account |
| Google Ads | Campaigns, performance, ad groups, keywords, search terms, ad text and policy status. | Pause or enable a campaign, set a campaign daily budget, add negative keywords to a campaign. | Off until you turn it on, per account |
| TikTok Ads | Advertiser accounts with currency and timezone, campaign ids and names, and daily spend, impressions, clicks, conversions and TikTok's own attributed purchase value. | Nothing. Campaign creation is written and switched off, and the write switch cannot be armed for TikTok. | Cannot be armed |
| Shopify | Daily sales aggregates, order counts and a sampled order revenue total with its sample size, product count, shop currency and timezone. | Nothing. No write permission is requested and no write path exists in the code. | Cannot be armed |
| Google Analytics 4 | Sessions, key events, purchases and revenue by traffic source and medium, day by day, plus the channel-group rollup. Read-only. | Nothing. | Cannot be armed |
| Search Console | Search queries and pages, with clicks and impressions, day by day. Read-only. | Nothing. | Cannot be armed |
- Meta. We ask for ads_read, ads_management and business_management, and, because Meta ties every ad to a Page, pages_show_list and pages_read_engagement to list the Pages you manage at connect. Where the connection runs through Facebook Login for Business the permission set is decided by a configuration in our Meta app rather than by our code, and Meta's own consent screen shows you the permission set you are actually granting. That screen is the authority, and we will not tell you otherwise.
- Google Ads. There is one Ads permission Google publishes and it is read plus write. Read-only behaviour is enforced by our own code and by the per-account write switch, not by the permission.
- Shopify. Order revenue over a window is a sample taken from a capped read, and the sample size is returned and shown alongside the figure. Any blended figure built on it inherits the same caveat.
The write switch exists for two platforms. Meta Ads and Google Ads are the only providers our code will arm, and arming one does not arm the other. TikTok Ads, Shopify, GA4 and Search Console cannot be armed at all.
The daily watch covers those same two platforms. Meta and Google Ads are the platforms with an audit engine behind them, so they are the ones a scheduled run reads and judges. TikTok Ads, Shopify, GA4 and Search Console are not audited on a schedule and this page will not imply they are.
Availability is narrower than implementation. Google Ads, GA4, Merchant Center and Search Console are the ordinary controlled-beta connections. Meta is reviewer-only, Shopify accepts existing installs only, and TikTok Ads remains a supervised test path.
The full permission table, the exact changes and what we never collect are on the security page.
Section 10 · straight answers
Straight answers to the questions that decide it.
What can I run without a card?
One initial deterministic audit for each eligible connected account. A failed attempt can be retried, and a completed report consumes that included proof. Repeat audits, daily monitoring, alerts and Mako require an active trial or plan. Stored reports remain visible after ongoing service ends.
Will it change anything in my account without asking?
No, and there are two locks rather than one. Write access is off on every connection until you turn it on for that specific account, behind a confirmation. While it is off, the tools that could change your account are never sent to the model, so the agent cannot ask for something it has not been handed. With it on, the agent can only propose: every proposal is a card you approve, showing the current value beside the proposed one. Approving executes it once, then re-reads the platform to compare what actually landed against what you approved. A disagreement is recorded as a failed verification, never as a success.
Does the daily watch burn my credits?
No. A scheduled run spends zero credits and makes zero model calls, and an import-graph test walks the whole transitive import graph of the cron route and fails the build if any part of it starts importing a model client. Credits are spent when you ask the agent something, when you press the button that turns an audit into plain English, or when you approve a change.
How often does it run, and when?
Once a day per eligible connected ad account while the workspace has active service, from 07:00 in your brand's own timezone. The scheduler ticks hourly and picks each brand up when its local morning arrives, so a missed tick is caught by the next one rather than waiting a day.
What if my account is too small or too new to judge?
The checks say so rather than guessing. A campaign under 4 days old is never called a loser. A verdict that depends on return on ad spend or cost per purchase needs at least 3 purchases behind it. A Google check that needs conversion values reports itself unavailable, in writing, with the reason. Skipped checks are listed in the report with their reason rather than dropped, so a category never scores well because nobody looked at it.
What does a subscription actually buy, then?
Ongoing service: repeat audits, daily monitoring, alerts, continued metric sync, Mako, report narration, the creative analyzer and approved publishing. The first eligible account audit is the included proof before that ongoing service.
Included account audit
See what your account is really doing.
Connect Google Ads through Google's own OAuth flow. The first audit lands before the agent can change a thing.
- official Google OAuth
- revocable at any time, from either side
- every figure on this page: one demo account
Invited partners connect read-only first. Ongoing service uses the published trial or plan terms.
Receipts
- Our terms state that one initial deterministic audit is included per eligible connected account. Repeat audits, monitoring, alerts and Mako require active service. Tests fail the build if that clause and the server gates stop agreeing.
- Every finding carries the window it was measured over and the moment its data was pulled. Platform conversion figures keep settling for days after a day closes, so a figure read this morning can move.
- The daily sweep spends no credits and calls no language model. An import-graph test walks the cron route's whole transitive import graph and fails the build if a model client appears anywhere in it.
- A check that cannot judge this run reports itself unavailable with a reason in plain language, and skipped checks are listed in the report rather than dropped.
- Findings, severities and the account score are computed in code. No language model authors any of them.
- The money floor is written in US dollars and converted into your account's billing currency before it is applied.
- Where a capped read means the total is understated, the finding states the figure as a floor and says the real total is higher.
- Alerts fire only when a finding is new or has worsened. The first scheduled run for a connection is a baseline and never alerts.
- Scheduled reads are read-only. A change needs write access you grant per account, plus your explicit approval on that individual change.