adwarp

Start with 1 prompt

Paste it into Claude Code, Codex or Cursor. Your agent installs Adwarp, walks you through your LinkedIn app and checks the connection.

setup prompt
Set up Adwarp for me. It's the open-source ad agent for LinkedIn Ads and Google Ads: https://github.com/adwarp-dev/adwarp

1. Check that Node.js 20 or newer is installed.
2. Walk me through creating my own LinkedIn developer app with the Advertising API product: https://github.com/adwarp-dev/adwarp/blob/main/docs/linkedin-app.md
3. Save the app's client ID and secret to ~/.adwarp/config.json as clientId and clientSecret.
4. Run "npx -y adwarp auth login" and wait while I approve access in my browser.
5. Add Adwarp to the AI client I'm using right now as an MCP server that runs "npx -y adwarp mcp". In Claude Code that's: claude mcp add adwarp -- npx -y adwarp mcp
6. Check the connection by listing my ad accounts, then save the one I pick as defaultAccountId in ~/.adwarp/config.json.

Don't create or change anything in my ad accounts during setup. LinkedIn campaigns start as drafts, so nothing spends until I turn it on.
adwarp
GitHub

Start with 1 prompt

Paste it into Claude Code, Codex or Cursor. Your agent installs Adwarp, walks you through your LinkedIn app and checks the connection.

setup prompt
Set up Adwarp for me. It's the open-source ad agent for LinkedIn Ads and Google Ads: https://github.com/adwarp-dev/adwarp

1. Check that Node.js 20 or newer is installed.
2. Walk me through creating my own LinkedIn developer app with the Advertising API product: https://github.com/adwarp-dev/adwarp/blob/main/docs/linkedin-app.md
3. Save the app's client ID and secret to ~/.adwarp/config.json as clientId and clientSecret.
4. Run "npx -y adwarp auth login" and wait while I approve access in my browser.
5. Add Adwarp to the AI client I'm using right now as an MCP server that runs "npx -y adwarp mcp". In Claude Code that's: claude mcp add adwarp -- npx -y adwarp mcp
6. Check the connection by listing my ad accounts, then save the one I pick as defaultAccountId in ~/.adwarp/config.json.

Don't create or change anything in my ad accounts during setup. LinkedIn campaigns start as drafts, so nothing spends until I turn it on.

How to audit a Google Ads account with Claude: 50 checks

All 50 checks with the rule, query and fix for each, the 8 exports to pull, and the prompt that has Claude run them for you.

By Updated 23 min read

A Google Ads audit is a read-only review of tracking, settings, keywords, search terms, ads and automation that ends in a list of fixes ranked by the money each one puts at risk. Start with conversion tracking, because every cost per conversion depends on it, then run the 50 checks below from CSV exports or let Claude run them through Google Ads Query Language (GAQL).

The checks below come from google-ads-account-audit, an MIT licensed skill in adwarp-dev/paid-ads-skills, down to each threshold and query. It never writes to the account, so the fixes are yours to make in Google Ads.

What a Google Ads audit covers

The skill runs 50 checks in 11 areas, in the order below. It scores Search, Performance Max and AI Max campaigns, and lists Display, Video, Demand Gen, App and Shopping campaigns as out of scope.

Fig. 01The 11 areas clockwise from conversion tracking, each segment sized by its number of checks.
Order, Area, Checks, It asks
OrderAreaChecksIt asks
1Conversion trackingC1 to C9Are the conversions Google bids on real?
2Campaign settingsS1 to S9Is money leaking to the wrong networks or places?
3StructureT1, T2Can every ad group serve?
4KeywordsK1 to K5Which keywords cost too much per conversion?
5Search termsQ1 to Q4How much goes to searches that never convert?
6NegativesN1 to N4Do negatives cover every campaign?
7Responsive search adsR1 to R5Does each ad group have enough approved ads?
8AssetsA1, A2Are sitelinks and the other assets in place?
9Performance MaxP1 to P4Does it overlap your Search campaigns?
10AI Max for SearchX1 to X3Do AI Max matches pay their way?
11Recommendations and change historyH1 to H3What did Google change for you?

Each check ends as pass, warn, fail, n/a or not checked. In the tables, T means your target cost per acquisition, and "judgment call" marks a threshold the skill chose that you can change. Google's help pages set the rest.

Fig. 02In the made-up example, conversion tracking scores 70, since its 3 warns count half and the 4 checks marked n/a or not checked stay out of the math.

Google's help pages, API guides and access levels quoted in this post were checked on 2026-11-07.

Queries carry a leading zero, Q01 to Q21, so they don't get confused with the search term checks Q1 to Q4. A few IDs hold more than 1 query, and all 31 are in references/gaql-checks.md.

The report opens with a scorecard that grades each area as (passes + 0.5 x warns) / (passes + warns + fails) x 100. The checklist below does the same math on your marks and downloads all 50 checks as a CSV.

Audit checklist, 50 checks

Mark each check as you go. Pick an area in the scorecard to see its checks, and press a result again to clear it.

Overall not scored yet · 0 pass, 0 warn, 0 fail, 0 n/a, 50 not checked

Conversion tracking, C1 to C9

  • C1Conversion tracking is onQ01
  • C2A primary action is firingQ02, Q03
  • C3Primary actions are business outcomesQ02
  • C4No double countingQ02, Q03
  • C5Counting matches the actionQ02
  • C6Values exist when bidding on valueQ02, Q04
  • C7Enhanced conversionsQ01
  • C8Consent Mode is active (European Economic Area, UK, Switzerland)None, UI only
  • C9Auto-tagging is onQ01

Score = (passes + 0.5 x warns) / (passes + warns + fails) x 100, rounded, per area and overall. N/a and unmarked checks stay out of the score.

Checks, rules and queries: google-ads-account-audit (MIT). The example is the made-up Fernhill account from the skill's examples folder. Sources in the CSV were checked 2026-11-07.

Before you start

Pick the window and the target first, then decide where the data comes from: CSV exports with nothing connected, or GAQL through Claude, which also reads account settings that no export carries.

Fig. 03In the made-up example, exports left 19 checks not checked, while GAQL leaves only Consent Mode (C8) to the UI.

Pick a window and a target cost per acquisition

The skill uses the last 30 days unless you name another window. With no target, it takes the account's own cost per conversion over the window and labels it "account average, used as target". Recent days undercount conversions, so for a long sales cycle end the window 7 days ago (a judgment call).

Fig. 04Conversions from the last few days are still coming in, so a long sales cycle gets a 30-day window that ends 7 days ago.

Option 1, CSV exports

In Google Ads, open each page below, set the window, click the download icon above the table and pick Excel CSV (Google Ads Help).

Report, Where in Google Ads, Columns the checks use, Checks
ReportWhere in Google AdsColumns the checks useChecks
CampaignsCampaigns > CampaignsBudget, Bid strategy type, Cost, Conversions, Conv. value, Search impr. share, Search lost IS (budget) and (rank)S5 to S9
Campaigns by networkThe same table, segmented by network with search partners shown separatelyNetwork, Cost, Clicks, ConversionsS1, S2
KeywordsCampaigns > Keywords, with the Quality Score columns addedKeyword, Match type, Status, Max. CPC, Quality Score, Exp. CTR, Ad Relevance, Landing Page Exp., Cost, ConversionsS6, T2, K1 to K5
Search termsInsights and reports > Search terms, plus its Performance Max viewSearch term, Match type, Added/Excluded, Keyword, Cost, ConversionsQ1 to Q4, P4
AdsCampaigns > AdsAd type, Status, Ad strength, Cost, ConversionsR1, R2, R5
Conversions summaryGoals > Conversions > SummaryConversion action, Action optimization, Source, Category, Count, Status, All conv.C2 to C6
Change historyCampaigns > Change historyDate and time, User, Campaign, ChangesH2, H3
Google Ads Editor exportAccount > Export > whole accountNetworks, Targeting method, Bid Strategy Type, Headline 1 to 15 with positions, Description 1 to 4, Keyword, Criterion TypeS1 to S4, R3, R4, N1 to N3, A1, A2

Option 2, GAQL through Claude

Claude runs each check's query through an MCP server, set up in Run the whole audit with Claude. The audit only reads, so Explorer access is enough: 2,880 operations a day on production accounts, per Google's access levels page.

The same page says developer tokens were sunset on September 9, 2026. Access now belongs to a Google Cloud project, where enabling the Google Ads API grants Test access and you apply for Explorer in the Cloud Console.

Fig. 05With developer tokens gone, enabling the Google Ads API on a Cloud project grants Test access, and the audit's reads need Explorer at 2,880 operations a day.

If you read the rows yourself, divide any field ending in _micros by 1,000,000 to get account currency. GAQL has no LAST_90_DAYS, so a longer window is written segments.date BETWEEN '2026-07-01' AND '2026-09-30'.

5 settings no report shows

For these, screenshot each setting page or mark the check "not checked". The skill never guesses a setting.

  • Auto-tagging (C9): Admin > Account settings. Q01 reads it.
  • Enhanced conversions (C7): Goals > Settings. Q01 reads this one too.
  • Consent Mode (C8): Goals > Conversions > Summary, a website action, then Diagnostics. No API field reports it.
  • Auto-apply (H1): the Recommendations page. Q20 sees only the types the API supports.
  • AI Max (X1 to X3): campaign settings, or queries Q04, Q12 and Q13.
Fig. 06GAQL reads 4 of the 5 settings, auto-apply only in part, while Consent Mode (C8) can be read only in the UI.

Conversion tracking (C1 to C9)

Smart Bidding learns from primary conversion actions, and every cost per conversion in this audit divides by them. Google's help page says primary actions are "used for bidding" when their goal is, and secondary ones are "for observation only" (Google Ads Help).

Fig. 07C1 and C2 hold up the 14 checks that compare cost per conversion, and if either fails, all 14 are marked unreliable.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
C1Conversion tracking is on (Q01)Status is NOT_CONVERSION_TRACKED-Goals > Conversions > New conversion action
C2A primary action is firing (Q02, Q03)No enabled primary action converted in 30 daysNewest primary conversion is 8 to 30 days old (judgment call)Open the action's Diagnostics, then test the thank-you page with Tag Assistant
C3Primary actions are business outcomes (Q02)Every primary action is a page view, engagement or outbound clickOne of those is primary next to real outcomesSet it to Secondary under Action optimization
C4No double counting (Q02, Q03)-2 or more primary actions in the same category both record conversions, such as a Google tag form fill and a Google Analytics 4 generate_lead (judgment call)Keep 1 primary, set the other to Secondary
C5Counting matches the action (Q02)-A lead category counts every conversion, or a purchase counts 1Edit settings > Count
C6Values exist when bidding on value (Q02, Q04)Value-based bidding with 0 conversion value in 30 daysEvery primary action always uses its default valueSend a value in the tag, or bid on conversions instead
C7Enhanced conversions (Q01)-Effective setting off, or customer data terms not acceptedGoals > Settings: accept the terms, send hashed email from the form
C8Consent Mode is active for European Economic Area, UK and Swiss traffic-Diagnostics shows no active statusUI only: the action's Diagnostics tab
C9Auto-tagging is on (Q01)Off-Admin > Account settings > Auto-tagging

If C1 or C2 fails, the skill marks S1, S2, S5 to S9, K1, K5, Q1, Q3, Q4, P4 and X1 "unreliable: tracking" and still reports their raw spend.

C5 follows Google's counting guide, which says usually only 1 lead per ad click adds value while every sale does (Google Ads Help). For C8, give a new Consent Mode setup time: its status can take 48 hours to show in Diagnostics, and up to 2 weeks in some cases (Tag Manager Help).

Q01 reads 3 of these checks in 1 call:

Q01 Account settings (C1, C7, C9)
SELECT customer.id, customer.descriptive_name, customer.currency_code, customer.time_zone,
  customer.auto_tagging_enabled,
  customer.conversion_tracking_setting.conversion_tracking_status,
  customer.conversion_tracking_setting.accepted_customer_data_terms,
  customer.conversion_tracking_setting.enablement_setting,
  customer.conversion_tracking_setting.effective_enablement_setting
FROM customer

That's the v26 form. Adwarp pins API v25 unless ADWARP_GOOGLE_API_VERSION says otherwise, and on v25 the last 2 fields become customer.conversion_tracking_setting.enhanced_conversions_for_leads_enabled. It covers leads only, so check web enhanced conversions in the UI.

Campaign settings (S1 to S9)

Settings decide where the money can go before any keyword matches. Most of these checks compare a campaign with T, or its partner and Display traffic with its own Google Search traffic.

Fig. 09A Search campaign's budget splits 3 ways, and S1 and S2 price the share that leaks to search partners and Display.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
S1Search partners on Search campaigns (Q04, Q05)Partners cost per conversion over 1.5x Google Search's (judgment call), or partners cost over 2x T with 0 conversionsPartners onNetworks: untick Google search partners
S2Display expansion on Search campaigns (Q04, Q05)The same test on Display trafficDisplay onNetworks: untick Display Network, or set it to Low priority with a budget cap
S3Location option is presence (Q04, Q07)-Presence or interest, with over 5% of cost from outside the targeted countries or worse results on area-of-interest traffic (judgment calls)Locations > Location options > Presence
S4Location targeting exists (Q04, Q06)A Search or Performance Max campaign has no positive location, or reports MISSING_LOCATION_TARGETING-Campaign settings > Locations
S5Bidding matches conversion volume (Q04)-Target cost per acquisition, or Maximize conversions with a target, under 30 conversions in 30 days. Target return on ad spend, or Maximize conversion value with a target, under 50Pool campaigns, raise the target, or bid on a higher-volume action
S6Broad match runs with Smart Bidding (Q09)Broad keywords on manual or click bidding spent over 2x T with 0 conversionsAny enabled broad keyword on manual or click biddingPhrase or exact, or Smart Bidding once S5 passes
S7Budget-limited campaigns (Q04)-10% or more of impressions lost to budget (judgment call)On target, move budget from campaigns over target. Over target, fix efficiency first
S8Rank-limited campaigns (Q04)-50% or more lost to rank on a campaign at or under T (judgment call)Raise bids on converting keywords, or fix the Below average components from K2
S9Campaigns that spend without converting (Q04)Cost over 2x T, 0 conversions (judgment call)Cost 1x to 2x T, 0 conversionsPause, or narrow to the ad groups that convert

Q05 splits each Search campaign by network: SEARCH is Google Search, SEARCH_PARTNERS is search partners and CONTENT is the Display Network.

Q05 Cost by network on Search campaigns (S1, S2)
SELECT campaign.id, campaign.name, segments.ad_network_type,
  metrics.cost_micros, metrics.clicks, metrics.conversions
FROM campaign
WHERE campaign.advertising_channel_type = 'SEARCH' AND campaign.status = 'ENABLED'
  AND segments.date DURING LAST_30_DAYS

Google's own page on the Search Network warns that partner clicks "may not always reflect highly targeted traffic" (Google Ads Help).

Google is changing Display expansion. It added High and Low priority tiers in October 2026, and from February 2027 Search campaigns with Display Expansion move to channel prioritization automatically, which Google warns can shift spend between Google Search, search partners and Display (Google Ads Help). The skill found no API field for the tiers, so read them in campaign settings.

Presence or interest is Google's default and recommended location option (Google Ads Help), and it suits a business people travel to. S3 warns only when the data shows leakage.

Fig. 10S1 and S2 check the search partners and Display Network boxes on a Search campaign, and S3 checks which location option it uses.

For S5, Google lets target cost per acquisition bidding start with no history but recommends judging it over 30 days with at least 30 conversions (Google Ads Help), or 50 for target return on ad spend (Google Ads Help). S6 rests on 1 line in Google's match type guide: "It's critical to use Smart Bidding with broad match" (Google Ads Help).

Structure and keywords (T1, T2, K1 to K5)

T2 looks for brand keywords inside non-brand campaigns. They convert cheaply and drag the blended cost per conversion down, so a shared target ends up overbidding on brand. The keyword checks after it hunt for cost without conversions, by match type and keyword by keyword.

Fig. 11K2 ranks keywords by cost and reads Quality Score components only on those that make up 80% of spend.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
T1Enabled ad groups can serve (Q08)Reason includes NO_AD_GROUP_ADS, NO_KEYWORDS or AD_GROUP_INCOMPLETE-Add an ad and keywords, or pause the ad group
T2Brand and non-brand are split (Q09)-A campaign mixes keywords with and without your brand terms (judgment call)Give brand its own campaign, add brand negatives elsewhere
K1Cost per conversion by match type (Q09)-A match type over 1.5x the account's cost per conversion, with cost over 2x T (judgment calls)Move its weakest keywords to phrase or exact
K2Quality Score components on top keywords (Q09)-A keyword in the top 80% of spend has a Below average componentBy component: headlines that repeat the query, a split ad group, or a page about the keyword
K3Keywords that can't serve (Q10)DisapprovedRarely served (Low search volume) or below first page bidRewrite or appeal, swap rarely served terms, raise bids only where the keyword converts
K4Duplicate keywords (Q09)-Same text and match type enabled in 2 or more ad groups (judgment call)Keep the copy whose ads fit, pause the rest
K5Keywords that spend without converting (Q09)Cost over 2x T, 0 conversions (judgment call)Cost 1x to 2x T, 0 conversionsPause, or narrow the match type

Google's help page says Quality Score "is not an input in the ad auction" and "should not be optimized or aggregated with the rest of your data" (About Quality Score). K2 never averages it and reads the 3 components only on the keywords that carry the spend.

K3 has its own query, Q10, because a keyword with 0 impressions never appears in Q09's performance rows.

Search terms and negatives (Q1 to Q4, N1 to N4)

The search terms report is where waste shows, though not all of it. Google says "some search terms that don't have enough query activity are omitted from the search terms report" to meet its privacy standards (Google Ads Help). So the waste Q1 reports is a floor, and Q2 measures how much of the cost shows up in the report at all.

Fig. 12Google hides low-volume search terms, so the waste Q1 finds is a floor.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
Q1Wasted search term spend (Q11)Zero-conversion terms over 2x T each make up over 10% of search term cost (judgment calls)5% to 10%Negatives from google-ads-search-terms
Q2Share of cost you can see (Q11, Q04)-Search term cost under 70% of Search campaign cost (judgment call)None: report Q1 as a floor
Q3Close variant and expansion drift (Q11)-Close variant, broad and AI Max matches over 1.5x the exact match cost per conversion (judgment call)Negatives for the drifting terms, and X1 for AI Max
Q4Converting terms not yet keywords (Q11)-2 or more conversions at or under T, not a keyword (upside, judgment call)Add them as exact keywords
N1Every Search campaign has negatives (Q14, Q15)None from any source, with cost over 2x TNone, with lower costAttach a list in Tools > Exclusion lists > Negative keyword lists
N2Shared lists are attached (Q15)-A list attached to 0 campaigns, or to some Search campaigns and not othersAttach it everywhere or remove it
N3Negatives don't block keywords (Q10, Q14, Q15)A keyword reports CAMPAIGN_CRITERION_NEGATIVE, or a negative blocks its own text-Remove or narrow the negative
N4Account-level negatives cover Performance Max and AI Max (Q15)-Either runs with no account-level list linkedAdmin > Account settings > Negative keywords
Q11 Search terms in Search campaigns (Q1 to Q4)
SELECT campaign.id, campaign.name, ad_group.id, ad_group.name,
  search_term_view.search_term, search_term_view.status,
  segments.search_term_match_type,
  metrics.cost_micros, metrics.clicks, metrics.impressions,
  metrics.conversions, metrics.conversions_value
FROM search_term_view
WHERE segments.date DURING LAST_30_DAYS AND metrics.impressions > 0
Fig. 13In Fernhill's search terms, zero-conversion rows past 2x T count as Q1 waste and become negatives, while converting terms that aren't keywords yet get flagged by Q4.

Q3 groups these rows by segments.search_term_match_type and compares NEAR_EXACT, NEAR_PHRASE, BROAD and AI_MAX with EXACT.

N3 applies Google's negative matching rules (Google Ads Help). A negative broad keyword blocks a query holding all its words in any order, a negative phrase needs them in order, and a negative exact needs the same words with nothing added. Negatives don't match close variants.

Fig. 14The negative "scheduling jobs" blocks fewer searches as it goes from broad to phrase to exact, and the close variant gets past all 3.

The account-level list in N4 takes up to 1,000 negatives and covers Search and Shopping inventory in Search, Performance Max, App, Shopping, Smart and Local campaigns (Google Ads Help).

The audit sizes the waste. For the full negative list and an upload file, run google-ads-search-terms.

Responsive search ads and assets (R1 to R5, A1, A2)

Google asks for "at least 2 responsive search ads (RSA) with 'Good' or 'Excellent' Ad Strength per ad group" and allows up to 15 headlines and 4 descriptions in each ad (Google Ads Help). An ad group takes 3 enabled responsive search ads at most (account limits).

Fig. 15A responsive search ad holds up to 15 headlines and 4 descriptions, and Google builds each impression from them.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
R1Responsive search ads per ad group (Q16)0 enabled1 enabledAdd a second, up to Google's 3
R2Ad strength (Q16)-An ad with spend rated Poor or AverageUnique headlines that use the ad group's keywords
R3Enough headlines and descriptions (Q16)-Under 8 headlines or under 3 descriptions (judgment call)Fill toward 15 and 4
R4Pinning (Q16)-Over half the headlines pinned, or a pinned position with 1 headline (judgment call)Unpin, or pin 2 or 3 headlines to the same position
R5Policy status (Q16)An enabled ad is disapprovedApproved (limited)Status column > policy details: edit or appeal
A1Sitelinks (Q17)Under 2 eligible at campaign or account levelUnder 6Add sitelinks, at account level when they fit every campaign
A2Callouts, structured snippets, business name and logo (Q17)-Any of the 4 missing (judgment call)Add the missing type

R2 never fails. Google says Ad Strength "doesn't determine whether your ad is eligible to serve" and "isn't used to calculate Ad Rank, Quality Score, or auction wins" (About Ad Strength).

R4 takes Google's line that pinning "isn't recommended for most advertisers and can affect ad strength".

Fig. 16Google rotates headlines through each position, and R4 warns when a pinned position holds just 1 headline.

For A1, sitelinks need at least 2 to show, and Google's tip is at least 6 with descriptions (Google Ads Help).

Fig. 17Sitelinks don't show until 2 are eligible and A1 warns below Google's tip of 6, so this ad with 4 would get a warn.

Performance Max (P1 to P4)

Performance Max can show on the same searches as your Search campaigns. P1 and P3 look at that overlap through brand and search themes. P2 grades the asset groups, and P4 prices the Performance Max search terms that never convert.

Fig. 18Search themes compete with phrase and broad keywords for the same queries, and brand terms land in the overlap without a brand exclusion.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
P1Brand exclusions (Q18, Q19)Brand terms over 10% of the campaign's search term cost, no brand exclusion (judgment call)No brand exclusion while a brand Search campaign runsCampaign settings > Brand exclusions
P2Asset group health (Q18)-Ad strength Poor or Average, or status Not eligible or LimitedAdd the asset types the asset group page lists as missing
P3Search themes (Q18)-A theme repeats a phrase or broad Search keywordRemove the theme, or make the keyword exact
P4Performance Max search term waste (Q19)Zero-conversion terms over 2x T each (judgment call)1x to 2x TCampaign negatives, or the account-level list

Brand exclusions in Performance Max apply to Search and Shopping inventory (Google Ads Help). An asset group takes up to 25 search themes, and they get "the same prioritization as your phrase match and broad match keywords in Search campaigns", while an exact keyword identical to the query still wins (Google Ads Help).

P4 reads campaign_search_term_view, because search_term_view has no Performance Max cost. In Google Ads, it's the "Search terms and landing pages for Performance Max" view of the search terms report (Google Ads Help).

AI Max for Search (X1 to X3)

AI Max lets Google match searches beyond your keywords and adapt ad text and landing pages. Google's API guide says that under AI Max "all keywords are treated as broad match by default" (Google Ads API).

Fig. 19Keywords match the inner ring of searches, AI Max reaches the outer one, and X1 compares what each costs per conversion.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
X1AI Max matches pay their way (Q12)AI Max matches spent over 2x T with 0 conversionsAI Max cost per conversion over 1.5x the keyword matches' (judgment call)Turn off search term matching on weak ad groups, or AI Max for the campaign
X2Auto-migrated campaigns reviewed (Q04)-A broad match or automatically created assets migration date is setReview AI Max, text customization and final URL expansion, and decide each on purpose
X3Final URL expansion and pins (Q13, Q16)-Final URL expansion is on and the ads rely on pinned textTurn final URL expansion off, or exclude the URLs that need the pins

Q12 splits search terms by segments.search_term_match_source and compares the AI_MAX_KEYWORDLESS and AI_MAX_BROAD_MATCH rows with ADVERTISER_PROVIDED_KEYWORD (AI Max reporting). It runs only when campaign.ai_max_setting.enable_ai_max is true.

For X2, API v25 added broad_match_migration_date_time and aca_migration_date_time, which record when Google moved a campaign to AI Max. X3 matters if your ads carry required text, since Google says "pinned assets aren't used if a more relevant URL is chosen" (Google Ads Help).

Fig. 20With final URL expansion on, Google can send the click to another page and skip the pinned headline, which is what X3 looks for.

Auto-applied recommendations and change history (H1 to H3)

In the made-up Fernhill account, change history shows Google's recommendations adding the broad match keyword "scheduling software" on October 18, and switching on search partners in a competitor campaign on October 2. Nobody on the team made either change. H1 to H3 find which auto-apply types are on and what they did.

Fig. 21The API keeps 30 days of change history, and H2 picks out the days a Google recommendation changed something.
ID, Check, Fail, Warn, Fix
IDCheckFailWarnFix
H1Auto-apply recommendations (Q20)On for broad match, search partners or Display expansionOn for keywords or bidding typesTurn those types off in the auto-apply settings on the Recommendations page
H2Changes made by Google recommendations (Q21)-A recommendation changed networks, bidding or keywords in the last 30 daysReview each in Change history and undo what you didn't intend
H3Change churn on Smart Bidding campaigns (Q21)-More than 3 bidding, target or budget changes on 1 campaign in 14 days (judgment call)Change targets less often, since each change makes the strategy recalibrate
Q20 Auto-apply subscriptions (H1)
SELECT recommendation_subscription.type, recommendation_subscription.status,
  recommendation_subscription.create_date_time, recommendation_subscription.modify_date_time
FROM recommendation_subscription

H1 fails on an enabled USE_BROAD_MATCH_KEYWORD, SEARCH_PARTNERS_OPT_IN or DISPLAY_EXPANSION_OPT_IN subscription. The API doesn't cover every auto-apply type (Google Ads API), so also open the Recommendations page, where "Add broad match keywords" and "Use Display expansion" are among the options (Google Ads Help).

Fig. 22H1 fails when auto-apply is on for broad match, search partners or Display expansion, and warns when it's on for keywords or bidding.

H2 and H3 read change_event, which needs a date filter inside the last 30 days and a LIMIT of 10,000 rows or fewer, and doesn't return Google Ads Editor changes (Google Ads API).

Turn findings into fixes ranked by spend at risk

To order the fixes, the skill prices every finding in account currency for the window, with the rules below. The scorecard stays secondary: by the skill's own rule, the score never outranks this list.

Fig. 23Measurement fixes go first with no dollar figure, and the rest line up by spend at risk, largest first.
Finding, Spend at risk
FindingSpend at risk
Zero-conversion spend (S9, K5, Q1, P4, the broad keywords in S6)The cost of the failing rows, counting each keyword or search term once
Network leak (S1, S2)Network cost minus network conversions x Google Search cost per conversion in the same campaign, floored at 0. If Google Search has no conversions, the whole network cost
Location leak (S3)Cost from people outside the targeted countries, plus area-of-interest cost when it converts worse than presence
Cost per conversion gap (K1, Q3, X1)Cost minus conversions x T, floored at 0
Measurement (C1 to C6)No figure. Labeled "blocks bidding" with the spend of the Smart Bidding campaigns that learn from the action, or "blocks reporting"
Budget-limited on target (S7)Upside: conversions x impression share lost to budget / impression share, labeled a rough estimate

The fix list then runs in this order:

  1. Measurement findings, any fail or warn on C1 to C6, with the cost per acquisition as reported next to the one counting only the primary action that matches the business goal.
  2. Quantified findings by spend at risk, largest first.
  3. Upside from S7 and Q4.
  4. Warnings with no dollar figure, ordered by the spend of the campaigns they touch.

Measurement goes first without a figure because a double-counted lead changes every cost per conversion in the report, and Smart Bidding learns from that count. A search partners finding measured on it can point the wrong way.

Fig. 24Fernhill's reported cost per acquisition, 142.81 USD, sits under the 150 USD target, and counting only demo requests puts it at 219.09 USD.

Thin data gets no verdict. A cost per conversion check needs at least 2x T of cost in the slice or it's marked "too little data", and Q3, K1 and X1 need 10 conversions in the comparison group (judgment call).

Run the whole audit with Claude

The skill runs in Claude Code, Codex, Cursor and other agents that read SKILL.md files. It works from the CSV exports alone, and with an MCP server connected it runs the queries itself.

Fig. 25Claude sends SELECT queries through Adwarp and reads the rows that come back, and no step in the audit writes to the account.
  1. Install the skills with npx skills add adwarp-dev/paid-ads-skills.
  2. Connect Adwarp or Google's MCP server, or skip this and use exports.
  3. Paste the prompt.
  4. Read the report, starting with "Do these 3 first".
Terminal
npx skills add adwarp-dev/paid-ads-skills
claude mcp add adwarp -- npx -y adwarp mcp
npx adwarp google auth login

Adwarp is a free, MIT licensed MCP server and CLI for LinkedIn Ads and Google Ads that runs from your terminal (Google Ads setup). Claude runs each query through gads_search, which refuses anything but a SELECT, and pulls conversion actions with gads_list_conversion_actions and search terms with gads_performance. From a terminal, the same query is adwarp google query "<GAQL>". The Google tools run only on your machine, because the hosted endpoint serves LinkedIn Ads.

Google's Google Ads MCP server runs the same GAQL through its search tool. It also has tools that create assets and labels, and its README says to set labels: false and assets: false in tools_config.yaml for a strictly read-only setup.

claude ~ google ads audit

> Audit Google Ads account 123-456-7890 for the last 30 days with the google-ads-account-audit skill. Target cost per acquisition is 150 USD. Read only, change nothing.

adwarp.gads_search Q01 account settings: 1 row

adwarp.gads_list_conversion_actions 123-456-7890: actions

adwarp.gads_search Q04 campaigns, last 30 days: by campaign

adwarp.gads_search Q05 cost by network: by network

adwarp.gads_performance search_term, last_30_days: by cost

Then Q02, Q03 and Q06 to Q21, each a SELECT

50 checks run. Nothing was written to the account.

Scorecard, fixes ranked by spend at risk, 3 to do first

The prompt

Name the account, the window, the target and your brand terms, and say read only.

The prompt
Audit Google Ads account 123-456-7890 for the last 30 days with the
google-ads-account-audit skill. Target cost per acquisition is 150 USD.
Our brand terms are "fernhill". Read only, change nothing.

For exports, start with "Audit the Google Ads exports in this folder" and put the 8 CSV files in it.

A sample report

This is the skill's report on the made-up Fernhill exports, cut down to the scorecard, the top 5 fixes and "Do these 3 first". 19 checks show "not checked" because exports carry no negatives, assets, Performance Max detail or the 5 settings above. A connected run fills them in.

Fig. 26Fernhill's scorecard comes out at 50 overall with 4 areas unscored, and the report closes on the 3 fixes to make first.
Sample report, made-up account
# Google Ads audit: Fernhill (made-up account)
Window: 2026-09-21 to 2026-10-20 | Currency: USD | Target CPA: $150.00 (user target)
Data: Export mode | Campaigns in scope: 4 Search, 1 Performance Max | Out of scope: none

## Scorecard
| Area | Pass | Warn | Fail | Not checked | Score |
| --- | --- | --- | --- | --- | --- |
| Conversion tracking | 2 | 3 | 0 | 3 (+1 n/a) | 70 |
| Campaign settings | 2 | 3 | 3 | 1 | 44 |
| Structure | 1 | 0 | 0 | 1 | 100 |
| Keywords | 0 | 4 | 1 | 0 | 40 |
| Search terms | 1 | 2 | 1 | 0 | 50 |
| Negatives | 0 | 0 | 0 | 4 | not scored |
| Responsive search ads | 0 | 4 | 1 | 0 | 40 |
| Assets | 0 | 0 | 0 | 2 | not scored |
| Performance Max | 0 | 0 | 0 | 4 | not scored |
| AI Max | 0 | 0 | 0 | 3 | not scored |
| Recommendations and history | 0 | 2 | 0 | 1 | 50 |
| Overall | 6 | 18 | 6 | 19 (+1 n/a) | 50 |

Spend at risk in the window: $5,366.19 (27.8% of $19,280.00 total cost), counting each campaign, keyword and search term once.

Measurement first: reported conversions are 135, so reported CPA is $142.81. Counting only "Demo request (Google tag)" (88), CPA is $219.09, above the $150.00 target.

## Fixes ranked by spend at risk
| # | Check | Finding | Spend at risk | Fix |
| --- | --- | --- | --- | --- |
| 1 | C4 Double counting | 2 primary "Submit lead form" actions both record conversions: "Demo request (Google tag)" (88) and "GA4 generate_lead" (31) | Blocks bidding ($11,040.00) | Goals > Conversions > Summary: set "GA4 generate_lead" to Secondary |
| 2 | C3 Micro action as primary | A booking link click (Outbound click, 16 conversions) is primary | Blocks bidding ($11,040.00) | Set it to Secondary in Action optimization |
| 3 | C5 Counting | "Demo request (Google tag)" counts every conversion | Blocks bidding ($11,040.00) | Edit "Demo request (Google tag)" > Count > One |
| 4 | S9 Spends without converting | Search - Competitors: $1,790.00, 350 clicks, 0 conversions | $1,790.00 | Pause the campaign, or rebuild it with exact terms and a CPA cap |
| 5 | Q1 Wasted search terms | 5 terms outside Search - Competitors, 0 conversions, each over $300 | $1,980.00 | Run google-ads-search-terms for the negative list |

## Do these 3 first
1. Fix conversion counting (C4, C3, C5): 1 primary lead action counted once per click.
2. Pause or rebuild Search - Competitors (S9): $1,790.00 in 30 days with 0 conversions.
3. Turn off search partners on Search - Crew Scheduling and Search - Field Service (S1, $1,032.19 excess cost) and add the negatives from google-ads-search-terms (Q1, $1,980.00).

Every threshold and the full report format are on the google-ads-account-audit docs page.

How often to audit

Run the full audit when an account changes hands and once a quarter. When cost per acquisition jumps, run the 9 tracking checks before anyone touches bids or budgets.

Fig. 27A full audit at each handover and each quarter, with the 9 tracking checks run whenever cost per acquisition jumps.

The API's change history reaches back only 30 days, so read the rest of the quarter on the Change history page in Google Ads, which keeps 2 years (Google Ads Help). February 2027 belongs on the calendar too. That's when Google moves Search campaigns with Display expansion to channel prioritization, so review every campaign S2 flags before then.

Between audits, paid-media-health-check runs a daily check that stays quiet unless something is wrong. For more on running Google Ads from Claude, see Google Ads in Claude and Google Ads reporting.

Put it to work

Google Ads in Claude

Connect Claude Code to Google Ads with Adwarp and run the audit's queries from your terminal.

adwarp.dev/google-ads/claude

By Stan Rymkiewicz, maintainer of adwarp. Published November 7, 2026.

FAQ

Questions Short answers, with sources.

Ask on GitHub
What is a Google Ads audit?

A read-only review of an account's conversion tracking, campaign settings, keywords, search terms, ads and automation. It ends in a list of fixes ranked by the money each one puts at risk, with tracking fixes first because every cost per conversion depends on them.

Does Google do audits?

Not as such. Google's Recommendations page and optimization score suggest changes, broad match keywords and search partners among them, and the score reaches 100% once every recommendation is applied or dismissed. An audit checks those suggestions against your own conversion data before you accept them.

What should I check first in a Google Ads audit?

Conversion tracking. Check that tracking is on, that a primary action converted in the last 30 days, and that no 2 primary actions count the same lead. If tracking fails, every cost per conversion in the rest of the audit is unreliable.

How often should I audit a Google Ads account?

In full when the account changes hands and once a quarter. Run the 9 conversion tracking checks on their own whenever cost per acquisition jumps, before anyone changes bids or budgets.

Can Claude audit my Google Ads account, and is it safe?

Yes. With the google-ads-account-audit skill installed, Claude runs the 50 checks from your CSV exports or through Adwarp's gads_search tool, which accepts only SELECT queries. The skill writes nothing, and Adwarp can't edit existing Google campaigns, so you make the fixes yourself in Google Ads or Google Ads Editor.

google-ads-account-audit

Do I need a developer token to query Google Ads from Claude?

Google's access levels page says developer tokens were sunset on September 9, 2026, and access levels are now managed per Google Cloud project. A read-only audit needs only Explorer access, which allows 2,880 operations a day against production accounts.

Did auto-apply recommendations change my account?

Checks H1 and H2 answer it: H1 reads which auto-apply types are on, and H2 lists the changes Google's recommendations made in the last 30 days. In Google Ads, the History tab on the Recommendations page and the Change history page, which keeps 2 years, show the same changes.

Should I worry about a low Quality Score or Ad Strength?

Not on their own. Google says Quality Score is not an input in the ad auction and Ad Strength isn't used to calculate Ad Rank, so the audit only warns on them. It reads Quality Score components on the keywords that carry 80% of spend, where a Below average component points to a specific fix.

Is $500 a month enough for Google Ads?

It depends on what a conversion costs. Google recommends judging target cost per acquisition bidding on at least 30 conversions in 30 days, so 500 USD a month supports it only when a conversion costs under about 17 USD. Below that volume, check S5 warns and suggests pooling campaigns or bidding on a higher-volume conversion action.

Free and open source MIT licensed. Run it locally, self-host the endpoint, or read every line on GitHub.

$ claude mcp add adwarp -- npx -y adwarp mcp

Read the docs

GitHub