Claude Skill Engage & Convert Paid MediaDemand GenMarketingRevOpsFounder

Google Ads Optimization Skill for Claude

Reads a Google Ads account through the API, writes a dated diagnosis, mines the search-terms report for negatives, and returns a ranked, evidence-backed list of typed changes to approve. It categorizes before it counts and proposes, never executes.

TypeClaude Skill
StageEngage & Convert
Best forDemand Gen, Marketing, RevOps, Founder
What it does

What it does

This is the SKILL.md that runs the weekly diagnosis behind the automate Google Ads management build. Instead of writing a fresh prompt every week, you drop this one file into your repo and the account gets read the same disciplined way every run: what to load first, how to convert micros and pick the most recent complete week, how to cross-reference GA4, how to mine the search terms for negatives, and the one rule it never breaks, propose but never execute.

It exists because Google's raw numbers need translating before they mean anything. Money comes back as micros, a factor of a million off until you divide. There are no report tables, only resources and date segments, so a trend is assembled, not queried. Quality Score and impression share tell you whether you are losing to rank or to budget, opposite fixes. And a click is not an outcome, so the skill cross-references GA4 landing-page behavior to judge a keyword on the page, not the click.

The highest-yield thing it does is mine the search-terms report. It flags negative-keyword candidates against fixed thresholds, spend over a floor with zero conversions, plus off-intent queries like free, jobs, and competitor-brand misspellings, and returns each as an approvable add_negative_keyword line with the evidence. That is where paid-search budget leaks fastest, and it is exactly the tedious fix a busy week skips.

It stops at the proposal on purpose. The skill writes Markdown, a dated diagnosis and a pending-actions file, and has no path to the write API. A separate executor applies only the lines you tick. The full build shows the executor, the dry run, the budget caps, and the checkbox gate that make an agent on a live account safe.

Inputs & outputs

Inputs & outputs

Inputs

  • Google Ads API access: a developer token, an OAuth client, a refresh token, and both the MCC and child customer IDs (required)
  • A GA4 property the skill can read landing-page behavior from, filtered to Paid Search
  • Your positioning and ICP (strategy/positioning.md, strategy/icp.md) so the diagnosis maps to what you sell
  • An insights-log.md the skill reads and appends to, so it remembers what was already tried or rejected
  • Configured thresholds: the spend floor for a negative candidate, and the maximum swing any single budget or bid change may propose

Outputs

  • A dated diagnosis: per-campaign, week over week, with anything that moved more than 20% flagged and drilled to the ad group, keyword, or search term
  • A Landing Page Behavioral Summary that joins GA4 behavior to Google Ads landing-page spend and conversions
  • A pending-actions file of typed changes, each an add_negative_keyword, adjust_budget, pause_keyword or similar with an unticked checkbox and a one-line reason
  • A dated entry appended to the insights log every run, never rewriting prior weeks
How to set it up

How to set it up

Drop the SKILL.md in your repo (or a Project)

Save the SKILL.md below as .claude/skills/google-ads-optimization/SKILL.md in the repo where your fetchers and strategy files live, and Claude Code loads it on demand whenever you ask it to run the analysis. If you work in claude.ai instead, create a Project named "Google Ads" and paste the SKILL.md body into its custom instructions. The repo route is the one to use, because the skill wants to read your positioning, ICP, and insights log as files.

Get Google Ads API access

The skill is only as good as the data it can pull. Create a developer token from the API Center on your manager account, an OAuth client of type Desktop app in Google Cloud, and mint a refresh token with access_type offline and prompt consent. Route through the MCC to the child account so Quality Score, impression share, and the search-terms report are readable. The use-case walkthrough has the exact sequence, including the dashed-ID gotcha that fails with an unhelpful error.

Point it at GA4, your positioning, ICP, and insights log

Before it judges a single keyword the skill reads strategy/positioning.md and strategy/icp.md so the diagnosis maps to what you sell, joins GA4 landing-page behavior so it judges the outcome not the click, and reads the tail of insights-log.md so it never re-litigates a rejected change. Seed those files once; the insights log can start empty and becomes the account's memory.

Set the thresholds and run it

Configure the spend floor for a negative candidate and the maximum swing any single change may propose, then ask Claude to "run the google ads analysis". It converts micros, picks the most recent complete week, mines the search terms, and hands back the diagnosis and the ticked-nothing pending-actions list. Wrap that pass in a Claude Code routine set to Monday morning so it is waiting before you open your laptop.

Tick to approve, add the executor when you're ready

You read the ranked actions and tick the ones you approve; the skill proposes and never writes. When you want the ticked changes enacted, add the separate executor from the full build, which applies only ticked lines through the mutate API, defaults to a dry run, and caps how far any single change can swing. The analysis agent and the executor stay two programs, which is what keeps a diagnosis from ever reaching the account on its own.

The SKILL.md

The SKILL.md

Save this as SKILL.md inside a folder named google-ads-optimization in your repo's skills directory, or paste the body into a Claude Project. Then ask Claude to run the google ads analysis.

.claude/skills/google-ads-optimization/SKILL.md
---
name: google-ads-optimization
description: Analyze a Google Ads account through the API, write a dated diagnosis, mine the search terms for negatives, and return a ranked list of typed changes to approve. Triggered by "run google ads analysis" or any Google Ads performance question.
---

# Google Ads Optimization

You analyze a Google Ads account and return a dated diagnosis plus a ranked,
evidence-backed list of typed changes to approve. You NEVER execute a change
yourself. You write Markdown only. The write is a separate executor that applies
only the actions a human has ticked.

## Before you look at a single number
1. Read the positioning and ICP (strategy/positioning.md, strategy/icp.md).
2. Read the tail of insights-log.md so you know what was already tried, flagged,
   or rejected. Never re-propose a rejected change. History lives in the log,
   not the API: the API returns today's account, not last week's read of it.
3. Read the two pre-fetched inputs (the search-terms report and the GA4
   landing-page behavior) rather than re-fetching them.

## The data, and three conventions that break people
Pull, at the grain each answer needs: campaign, ad_group, keyword_view,
search_term_view, ad_group_ad, daily (campaign + segments.date), device, geo,
landing_page_view, and the RSA asset ratings.
- Money is micros. cost_micros / 1_000_000 gives dollars; a bid the other way is
  int(usd * 1_000_000). Convert inline on every read and write.
- Dates are segments, not tables. Use segments.date DURING LAST_14_DAYS, or a
  BETWEEN range, and segment by date for week over week.
- Identify the most recent COMPLETE week from the daily data before you compare.

## Judge the outcome, not the click
Cross-reference GA4 landing-page behavior against Google Ads landing-page spend
and conversions, and include a Landing Page Behavioral Summary table. A keyword
can win on clicks and lose after the click. Read Quality Score and impression
share (lost to rank vs lost to budget) from keyword_view before you propose a
bid or a budget move, because the fix depends on which one you are losing.

## Mine the search terms for negatives (this is where budget leaks)
The search-terms report is the highest-yield read in the account. Flag
negative-keyword candidates against fixed thresholds: spend over the configured
floor with zero conversions, or clearly off-intent queries (free, jobs, salary,
login, competitor-brand mistypes). Emit one add_negative_keyword action per
flagged candidate, with the exact field set the executor parses.

## The analysis, in order
1. Build per-campaign and per-ad-group tables, week over week.
2. Flag anything that moved more than 20% week over week, then drill to the ad
   group, keyword, or search term on the anomalies.
3. Cross-reference GA4 for post-click behavior.
4. Write it up: high level -> driver -> root cause.
5. Turn each conclusion into a typed, evidence-backed proposed change with an
   UNticked checkbox, one action per line:
   - [ ] add_negative_keyword | campaign <id> | term "free crm" | reason ...
   - [ ] adjust_budget | campaign <id> | $150 -> $180 | reason ...
   - [ ] pause_keyword | ad_group <id> | keyword <id> | reason ...
6. Append a dated entry to insights-log.md. Never rewrite prior weeks.

## Guardrails (non-negotiable)
- Propose, never execute. You write Markdown. The executor applies only ticked
  actions through the mutate API, and logs every attempt, success or failure.
- No single change may move a budget or a bid more than the configured cap.
- Every action needs an action type the executor supports, a target entity, a
  target value, and a one-line reason. No reason, no action.
- If a number looks wrong, check in order: dashed customer IDs (strip the
  dashes), MCC-to-child routing, the micros conversion, the API version
  fallback, and whether the comparison used the most recent complete week.
Run it from the terminal

Run it from the terminal

zsh
$# run the weekly diagnosis; the agent writes Markdown, never the account
$ls .claude/skills/google-ads-optimization/
SKILL.md
$claude -p "run google ads analysis for the last 8 weeks"
Search-terms mine: $340 last 14d on zero-conversion queries ('free crm', 'crm jobs'). Brand: losing impression share to budget. GA4: 'Solutions' page bounce 71% on non-brand. PENDING ACTIONS (pending-actions.md): - [ ] add_negative_keyword | campaign 41..07 | "free crm" | $128, 0 conv, 14d. - [ ] add_negative_keyword | campaign 41..07 | "crm jobs" | $84, 0 conv, 14d. - [ ] adjust_budget | campaign 41..02 | $150 -> $180 | Brand, losing IS to budget. +20%, within cap. 3 proposed. None executed. Tick the boxes, then run the executor to write.
$
Example run

Example run

The Monday routine fires, the skill reads the account and hands back a diagnosis plus a ticked-nothing actions list, and a separate executor turns the ticked lines into API writes (the executor and its guardrails are the full build).

Example
CLAUDE CODE ROUTINE FIRES (Monday 08:00) -> WEEKLY DIAGNOSIS:
Search spend +12% w/w. Impression share lost to budget up on 'Brand'.
GA4: 'Solutions' landing page bounce 71% on non-brand terms.
Search-terms mine: $340 last 14d on zero-conversion queries.

PENDING ACTIONS (pending-actions.md):
- [ ] add_negative_keyword | campaign 41..07 | "free crm"       | $128, 0 conv, 14d. Off-intent.
- [ ] add_negative_keyword | campaign 41..07 | "crm jobs"       | $84,  0 conv, 14d. Job seeker.
- [ ] adjust_budget       | campaign 41..02 | $150 -> $180     | Brand, losing IS to budget. +20%, in cap.
- [ ] pause_keyword       | ad_group 88..15 | "crm software free" | $61, 0 conv, QS 2/10.

HUMAN (ticks the boxes, 08:14):
[x] negatives 1,2   [x] budget 3 (edit -> $170)   [ ] pause 4 (keep, testing)

EXECUTOR APPLIES via mutate API (08:14):
[OK] negative 'free crm' added to campaign 41..07
[OK] negative 'crm jobs' added to campaign 41..07
[OK] campaign 41..02 budget $150 -> $170
Logged 3 changes to execution-log with before/after + reason. 1 left unticked.

EXECUTION LAG: decision to enacted change = same morning (the negatives used to lag weeks).
Related

Related plays

More AI skills in your inbox

Practical AI you can ship, every couple of weeks.

Subscribe →