Systems Lab

Agent skill

google-ads-search-framework

Keyword-first, table-driven method for planning, building, restructuring and auditing Google Ads Search campaigns.

activeSelf-containedInstructions only2,552 words

Filed under ABM and paid.

From lbarberis/gtm-skills · 7 skill entries · 0 · pushed 2026-09-26

What it does when it runs

Keyword-first, table-driven method for planning, building, restructuring and auditing Google Ads Search campaigns. It forces the work through fixed tables (intake, keyword inventory, master table, budget split, negatives, details, self-check) so every keyword is paired with an intent, one ad group, one relevant ad and a bid, and campaigns exist only for budget control. Use this skill whenever someone asks to plan, launch, rebuild, audit or review a Google Ads Search campaign or account, build or clean a keyword list, group ad groups, choose match types, write responsive search ads, set search bidding or budgets, build negative keyword lists, or sanity-check a paid search structure, even if they never say "framework" or "Google Ads" explicitly (for example "paid search plan", "PPC structure", "search ads for X"). Not for Performance Max, Display, Demand Gen, YouTube, Meta or LinkedIn ads.

Automated analysis of the skill and the 0 files bundled beside it. A skill’s own description is written to be selected by an agent, so it describes the job and not the dependencies.

Keys and connectors you must supply
None found.
Hosts it reaches
No third-party host appears in the skill or its bundled files.
Tool permissions it declares
No allowed-tools in the frontmatter. It only issues instructions, so there is nothing to bound.
Actions present in the files
None. Instructions only.

Ask about google-ads-search-framework

Opens your assistant with this page's verified links already in the prompt.

Is this safe to install?ClaudeChatGPT
Adapt it to my stackClaudeChatGPT
What else do I need for it to workClaudeChatGPT
Rather ask a human? Talk to Cheetah
git clone --depth 1 --filter=blob:none --sparse https://github.com/lbarberis/gtm-skills.git /tmp/gtm-skills
git -C /tmp/gtm-skills sparse-checkout set "skills/google-ads-search-framework"
mkdir -p ~/.claude/skills/google-ads-search-framework
cp -R "/tmp/gtm-skills/skills/google-ads-search-framework/." ~/.claude/skills/google-ads-search-framework/

Picked up without a restart. A project skill of the same name is shadowed by your personal one. For one repository only, swap ~/.claude/skills for .claude/skills. Claude Code docs ↗

Or take the whole library

This repo ships a .claude-plugin manifest, so Claude Code can install all 7 skills at once. Plugin skills are invoked as /<plugin>:<skill>, so they never collide with your own.

/plugin marketplace add lbarberis/gtm-skills
/plugin

The folder is the same in every client that implements the format — 46 of them — so if yours is not above, only the destination changes.

Reproduced in full from lbarberis/gtm-skills/blob/aba514c75be2102fa8c91074bb978ee36cfa050b/skills/google-ads-search-framework/SKILL.md, which is licensed MIT (repository). 2,552 words, 18 headings.

Google Ads Search framework

The model

A Search account is a list of keywords. Each keyword is paired with a match type, an intent, one ad group, one ad written for that ad group (with its landing page) and a bid. Everything else is grouping, and each grouping layer has one job:

Rows: the three layers of the framework. Columns: what each layer is built for, and the test that decides what belongs in it.

LayerBuilt forMembership test
Keyword, match type, bidWhat you buyWould we pay this price to appear for this search?
Ad group, ad, landing pageRelevanceCan this ad group's ad and page fully answer the keyword's intent?
CampaignBudget controlDoes the keyword's expected CPA or ROAS, and its role, match the campaign's budget and target?

Google's own structure guidance uses the same two grouping tests: keywords sharing a budget and target share a campaign; keywords sharing a landing page and creative theme share an ad group.

Always start from keywords, never from campaigns. Campaigns are named last, once the performance tiers are visible in the keyword inventory.

House style for every output

  • Tables first. Prose only as one or two lines of connective commentary between tables.
  • Directly above every table, write one line stating what the rows and the columns represent (Rows: ... Columns: ...).
  • Mark assumptions inside the tables (a Source column with given or assumed), not in a paragraph afterwards.
  • Label illustrative numbers as illustrative.
  • Never use em dashes.
  • Default to markdown tables. If the user asks for a document, page or printable output, render the same tables as HTML.

Why tables: they force every keyword through the same attributes, so gaps become visible empty cells (a keyword with no landing page, an ad group serving two intents, a campaign with no target) instead of being hidden in prose.

Workflow

Run the stages in order and end each stage with its table. Do not jump to the master table: the earlier tables are where the thinking happens. For a small request (for example "write ads for this ad group"), run only the stages it needs, but still use their tables.

Stage 1: Intake

Rows: inputs needed to build the account. Columns: Input | Value | Source (given or assumed) | What breaks if it is wrong.

Required inputs: product and core use case; target customer; markets and languages; primary conversion action; target CPA or ROAS; daily or monthly budget; landing pages that exist; brand terms; main competitors; sales cycle (B2B long or B2C short); current monthly conversion volume; existing account (yes or no).

If target CPA (or ROAS) or budget is missing, ask for it once before Stage 4, because campaigns cannot be split without it. For everything else, assume, flag it as assumed, and continue.

Stage 2: Keyword inventory

Rows: candidate keywords, typically 30 to 150. Columns: Keyword | Intent | Fit | Expected tier | Landing page that answers it | Decision.

ColumnAllowed values
IntentNavigational, Transactional, Comparative, Problem-aware, Informational, Irrelevant
FitHigh, Lower, Negative
Expected tierBrand, Core, Competitor, Discovery (add a tier only when its expected CPA truly differs)
DecisionKeep, Negate, Park

Rules:

  • Informational and Irrelevant intents become negatives, not ad groups.
  • A keyword with no page that answers it is Parked, and the page to build is named.
  • Group near-duplicates (plurals, reorderings) on one row; close variants will catch them.

Stage 3: Master table (the core deliverable)

Rows: one per keyword, grouped into ad groups, with ad groups grouped under a campaign band row. Columns, exactly in this order: Keyword and match type | Intent | Ad group | Ad text written for the ad group | Bidding.

Format rules:

  • Keyword syntax: [exact], "phrase", broad, followed by the match type in words.
  • Campaign band row before each campaign: first cell **Campaign: <name>**, second cell Budget: <daily amount> (<share>), third cell Strategy: <bid strategy and target>, remaining cells empty.
  • Ad text cell, on the first row of each ad group: H1 (pinned) / H2 / one description / final URL. On the following rows of the same ad group, write same ad.
  • Bidding cell: the max CPC under Manual CPC, or Set by strategy plus the target or cap.

Apply the two tests to every row, then fix the table before moving on:

  • Relevance test: if the ad group's ad and page cannot answer the keyword's intent, move the keyword or create an ad group (one keyword is fine when it needs its own page, like "brand pricing").
  • Budget test: if the keyword's expected CPA differs from its campaign's, move it to another campaign.

See references/northbill-example.md for a complete master table at the expected level of detail.

Stage 4: Campaign budget split

Rows: campaigns. Columns: Campaign | Keyword group | Match types | Expected performance | Budget share | Bid strategy | Budget rule.

Rows: default campaign tiers. Columns: starting budget share (illustrative) and the rule that protects it.

CampaignStarting shareBudget rule
Brand5 to 10%Never limited by budget
Core: high fit50 to 60%First claim on money; should never show "Limited by budget" while on target
Competitor10 to 15%Capped, judged on its own CPA, never averaged into Core
Discovery: lower fit15 to 25%Hard cap; carries routing negatives of Core keywords

Create another campaign only when budget, target, country, language or conversion goal differs. Never split by device or by match type.

Stage 5: Negative keywords

Rows: negative categories. Columns: Category | Why it wastes spend | Example negatives | Match type | Level.

Check every one of these categories: free and pirated; job seekers; learning and DIY; informational; existing customers (login, support, cancel); different meaning of the same words; wrong segment; wrong geography or tax regime; competitors (only if no competitor campaign); own brand in non-brand campaigns; cross-campaign routing; cross-ad-group routing.

Rows: negative match types. Columns: syntax and blocking rule.

Negative typeSyntaxBlocks a search when
Negative broadfree invoiceIt contains every word, in any order
Negative phrase"free invoice"It contains the words in the same order
Negative exact[free invoice]It is exactly those words, nothing else

Negatives do not expand to close variants: add plurals and synonyms yourself. They do follow casing and the misspellings Google auto-corrects.

Rows: where negatives live. Columns: scope and use.

LevelScopeUse it for
Account-levelAll Search and Shopping inventory, including the search part of Performance MaxUniversal exclusions
Shared listCampaigns it is attached to (up to 20 lists of 5,000)Themed lists reused across campaigns
CampaignThat campaignRouting between campaigns, country exclusions
Ad groupThat ad groupRouting between ad groups

Add each new negative at the narrowest level that solves the problem.

Stage 6: Important details (kept separate)

Rows: settings and assets. Columns: Detail | What to do | Setting for this account.

Keep this table outside the master table: none of these items changes which keyword sits in which ad group or campaign. Cover at least: sitelinks (at least 4, ad-group-level where a theme has its own pages, unique text, both description lines); callouts (specific, not repeating headlines); structured snippets; at least 3 image assets; 4 or more asset types; headline 3 pin decision; Display Network off and Search partners off on Search campaigns; location option "Presence"; AI Max for Search off in Brand and Core; auto-apply recommendations off; conversion quality checked against the CRM; weekly search terms review.

Stage 7: Self-check

Rows: checks. Columns: Check | Pass or Fail | Fix.

  • Every keyword has exactly one match type in its ad group (no duplicates across match types).
  • Every keyword's intent is answered by its ad group's ad and landing page.
  • Every campaign has one budget and one target; no two tiers with different expected CPA share a campaign.
  • Broad match appears only where a winning experiment justifies it.
  • Headlines at most 30 characters, descriptions at most 90, paths at most 15, sitelink text and callouts at most 25. Run scripts/check_ad_lengths.py when code execution is available.
  • No competitor trademarks in ad text.
  • Routing negatives exist in Discovery for Core keywords and their variants.
  • Assumptions are flagged in the tables.

Rules (vetted against Google documentation and practitioners, September 2026)

Read references/sources.md when someone challenges a rule or asks why.

Match types

Rows: match types. Columns: role in this framework.

Match typeRole
ExactTop converters and brand. Most efficient on CPA and ROAS in practitioner data.
PhraseThe everyday workhorse for Core and Competitor; strongest in lead generation.
BroadNot a default. Only in Discovery, and only after the broad match experiment below proves its extra conversions cost no more than target.

Why this departs from Google: Google recommends broad match only, one ad group per theme, arguing broad reaches everything exact and phrase do plus more. That argument is about reach, and reach also grows spend. Practitioner data measures cost per conversion and favours exact and phrase, especially in lead generation. Two caveats keep this honest: practitioner data has its own biases (exact usually holds the proven best terms), and broad can find conversions exact never would. Hence the test.

Other rules:

  • One match type per keyword per ad group. An eligible exact keyword identical to the search already wins over phrase, broad and Performance Max, so duplicates only split data.
  • Plurals and synonyms are not "identical" for that priority rule: use routing negatives to push them to the right campaign.
  • Broad match modifier no longer exists (retired 2021).

Broad match experiment: Google Ads custom experiment on the Discovery campaign, 50/50 split. Control: phrase keywords on current bidding. Treatment: the same keywords in broad with Target CPA and the same negatives. Run at least 4 weeks and until both arms have enough conversions to compare. Marginal CPA = (treatment cost minus control cost) divided by (treatment conversions minus control conversions). Adopt broad only if marginal CPA is at or below target and lead quality holds in the CRM. Brand and Core stay on exact and phrase regardless.

Ads (responsive search ads)

Rows: RSA elements. Columns: limit and relevance rule.

ElementLimitRule
Headline 130 charactersThe ad group's core keyword, pinned to position 1
Headline 230 charactersA proven benefit; pin it in low-volume ad groups so the system learns faster
Headlines 3 to 15Up to 15 in total, at least 3Variants, proof, offer, call to action; each must read correctly next to every keyword in the ad group, in any order
DescriptionsUp to 4, 90 characters each, at least 2The job the searcher wants done, one proof point, one next step
Paths2 fields, 15 characters eachRepeat the theme
Final URLOne pageBuilt for the ad group's intent, headline echoing the search
Ads per ad groupUp to 3 enabledRun 1 or 2 with different angles; judge on conversions per impression
  • Write every ad for one ad group only. Never share ad copy across themes.
  • Ignore Ad Strength as a score: practitioner data finds no link to CTR or conversion rate. Its "more unique" and "more relevant to keywords" prompts are still useful checks.
  • If AI Max final URL expansion is on, Google can send traffic to other pages and skip pinned assets. Keep AI Max off where ad-to-page relevance is the point.
  • No competitor trademarks in ad text.

Bidding

Rows: bid strategies (Google's labels from June 2026). Columns: per-keyword control and where they fit.

StrategySeparate bid per keyword?Use it for
Manual CPCYes (ad group default, keyword overrides)Launch, brand, Discovery tests, B2B or long sales cycles with thin data
Maximize clicksNo (one cap)Gathering search-term data before conversions exist
Target impression shareNo (one cap)Brand defence
Maximize conversions / Target CPANo; target settable per ad groupCore and Competitor once conversion tracking is reliable
Maximize conversion value / Target ROASNo; target settable per ad groupWhen conversions carry different values
  • Google says Target CPA can start with no history; practitioners wait for roughly 30 to 50 conversions a month. State which rule you are applying.
  • Smart Bidding removes per-keyword bids, so tiering survives only through separate campaign (or portfolio) targets. This is why the budget test matters.
  • For B2B with long sales cycles, Manual CPC plus rule-based adjustments is a legitimate long-term choice, not only a launch phase.

Quality Score

Quality Score is a keyword-level diagnostic (expected CTR, ad relevance, landing page experience), not an auction input and not a KPI. Never optimize the number. Use the weakest component to decide the fix: weak ad relevance means split the ad group; weak landing page experience means build a matching page.

Audit mode

When given an existing account (export, screenshots or a description):

  1. Rebuild its master table from what exists, as-is, including the flaws.
  2. Produce a findings table. Rows: findings. Columns: Finding | Rule broken | Evidence | Fix | Priority (High, Medium, Low).
  3. Produce the corrected master table and the diff: Rows: keywords that move. Columns: Keyword | From (campaign / ad group / match type) | To | Reason.

Common findings to look for: several intents in one ad group; one ad reused across ad groups; the same keyword in several match types; broad match everywhere without experiment evidence; brand and non-brand in one campaign; campaigns split by device or match type; Core "Limited by budget" while Discovery is not; Display or Search partners on; AI Max final URL expansion on in Core; no routing negatives; negatives missing plurals.

Reference files

  • references/northbill-example.md: a complete worked example of every stage table. Read it before the first build in a session to calibrate the level of detail.
  • references/sources.md: official Google positions versus practitioner positions, with links and the date checked. Read when a rule is challenged, and re-verify anything older than six months.
  • scripts/check_ad_lengths.py: checks headline, description, path, sitelink, callout and snippet lengths from a CSV. Usage: python scripts/check_ad_lengths.py ads.csv with a type,text header line (types: headline, description, path, sitelink, sitelink_description, callout, snippet).

Other skills for the same job

Different authors, same problem. Matched on the words in the skill name, across every library in the catalogue except this one.

Need help setting it up?

This page tells you what google-ads-search-framework does and what it needs. Cheetah builds the agent setup it runs inside: data, CRM, sequencing and the guardrails.

Book a call →

The directory stays free. There is nothing gated behind this.