---
name: negative-keyword-miner
description: "Mine the search-terms report for wasted spend and recommend the correct negative keyword match type — exact, phrase, or broad — for clean Google Ads negative keyword hygiene, the single highest-ROI Search action. Changes proposed, applied on approval."
license: MIT
compatibility: "Works with any Agent-Skills-compatible AI (Claude, ChatGPT, Cursor, Codex, and more). Ad-account actions run through Adspirer."
metadata:
  author: "Adspirer"
  version: "1.0.0"
  adspirer_category: "ad-ops-optimization"
  adspirer_source: "https://www.adspirer.com/skills/negative-keyword-miner"
  adspirer_connection_url: "https://adspirer.ai/sign-up"
  adspirer_primary_keyword: "negative keyword tool"
  adspirer_secondary_keywords: "negative keyword generator, google ads negative keywords"
  adspirer_launch_wave: "1"
  adspirer_kind: "skill"
  adspirer_level: "operator"
  adspirer_platforms: "google"
  adspirer_supported_clients: "claude,claude-code,chatgpt,codex,cursor,gemini,windsurf"
  adspirer_summary: "Mine the search-terms report for wasted spend and recommend the correct negative keyword match type — exact, phrase, or broad — for clean Google Ads negative keyword hygiene, the single highest-ROI Search action. Changes proposed, applied on approval."
  adspirer_connections_required: "adspirer"
  adspirer_connections_optional: ""
---

# Negative Keyword Match Type Miner — Google Ads Negative Keyword Finder for Search Waste

## Use this when

Weekly (or after any meaningful spend jump) on a Google Ads Search account that has at least 2-4 weeks of click volume since the last negative keyword match type review. Highest-value when: broad or phrase match is in use, Smart/Performance Max is siphoning search queries you can't directly negative (call that out separately), a new campaign just exited learning, or spend/conversions have diverged from prior weeks. This is where most accounts get negative keyword google ads hygiene wrong — picking the wrong match type (too broad, too narrow) does as much damage as skipping the pass entirely. Skip accounts that are 100% exact match with a mature negative list already enforced — there's nothing to mine.

## What you need

Read access to the target Google Ads account via Adspirer (MCC or direct). A defined lookback window — default 30 days, extend to 60-90 days for low-volume accounts (<50 clicks/week) so the sample isn't noise. Know the account's actual CPA/ROAS target or breakeven CPA if the user has one — the agent should not invent a cost threshold. Existing negative keyword lists at campaign/ad-group/shared level (so we don't propose a duplicate or a term that's already excluded upstream). If the account runs PMax alongside Search, know that PMax search-term insights are directional-only (Google aggregates/buckets them) — brand-safety exclusions there go through PMax account-level negatives, not this workflow.

## Procedure

1. Pull the Search Terms report for the account over the lookback window, scoped to Search campaigns (and standard Shopping if applicable) — include impressions, clicks, cost, conversions, conv. value, and the matched keyword + match type that triggered each query.
2. Pull the account's and each campaign's/ad group's existing negative keyword lists (shared lists + campaign-level + ad-group-level) so candidates already excluded are dropped from consideration before scoring.
3. Segment queries into two waste buckets, not one: (a) zero-conversion spend — queries with cost above a floor (default: cost > 2x the account's average CPC, or > $10 spend, whichever is higher — user can override) and zero conversions over the window; (b) semantic mismatch — queries that got clicks/spend but are topically irrelevant to the ad group's intent even if a conversion slipped through once (e.g., "free," "jobs," "salary," "DIY," a competitor brand name, a wrong-product-category term, a location outside the service area). Flag these two buckets separately since the second requires judgment, not just a cost cutoff.
4. For each candidate query, check query-to-keyword drift: if it's only surfacing because of broad/phrase match on a specific keyword, note that keyword — sometimes the fix is tightening that keyword's match type rather than (or in addition to) a negative.
5. Recommend the negative keyword match type per candidate using standard logic: exact negative for a single wasteful literal query; phrase negative when a recurring modifier (e.g., "free," "cheap," "used") shows up across many queries under one keyword; broad negative only for account-wide brand-safety terms (competitor names, totally off-category words) — broad negatives are the riskiest of the negative keyword match types (can silently block good traffic) so default to phrase/exact unless the term is unambiguous.
6. Check for negative-positive collisions before finalizing: run each candidate negative against the account's active keyword list — if a proposed negative would also block an existing converting keyword or a keyword with recent impressions, drop or narrow it (tighten to exact, or scope it to ad-group level instead of campaign/account level) rather than propose it as-is.
7. Decide placement level per negative: default ad-group-level for anything narrow/product-specific (safest, least collateral damage), campaign-level for terms that recur across multiple ad groups in that campaign, and account-level shared list only for universal brand-safety exclusions (competitors, "jobs/careers," adult/free-seeking terms) that should never show for any campaign.
8. Assemble the proposal list: query, cost/clicks/conversions in-window, triggering keyword + match type, recommended negative + match type + placement level, and one-line rationale (waste vs. semantic mismatch). Sort by cost-wasted descending so the highest-dollar items are reviewed first.
9. Present the full list to the user for explicit approval — never auto-apply. Allow partial approval (user can approve a subset, e.g. exclude the semantic-mismatch bucket if they want to review those manually).
10. On approval, apply only the approved negatives at their approved levels.
**Connect Adspirer (the ads connection):** when you reach a step that touches a live ad account, connect Adspirer first. In Claude Code, run `/plugin marketplace add anthropics/claude-plugins-community` then `/plugin install adspirer-ads-agent@claude-community`. In claude.ai or ChatGPT, add the Adspirer connector from https://www.adspirer.com/docs/ai-clients. Any other agent: follow https://www.adspirer.com/docs/ai-clients for your client. Sign-in link for the user: https://adspirer.ai/sign-up. Do not proceed with live ad-account steps until the connection is confirmed.
11. After applying, re-pull the negative keyword lists for the touched campaigns/ad groups/shared lists and confirm each approved negative is present with the correct match type and placement — this is the live-data proof, not a re-statement of what was proposed.

## Fixed checks

Before presenting proposals: re-verify each candidate query is not already covered by an existing negative (exact term, or a broader negative phrase/broad match that would already block it) by checking live negative lists — never assume the report reflects current exclusions if the window predates a recent negative-list edit. Verify no proposed negative matches or would block any keyword currently receiving impressions/conversions in the same ad group/campaign (collision check against live keyword list, not memory of "typical" keywords). After applying: pull the live negative keyword list for every touched entity and confirm presence + correct match type + correct level for each approved item — flag any that failed to apply (e.g., silently rejected duplicate, list-size cap hit) rather than reporting success from the apply-call response alone.

## Stop conditions

Success: all user-approved negatives applied and confirmed present via live re-pull. No-op: search-terms report over the window has no candidates clearing the waste/mismatch bar (clean account) — report this plainly, don't manufacture marginal candidates to look useful. Blocked: cannot pull search-terms report or negative lists (API/auth failure, Adspirer connection issue, account has no Search campaigns) — report the specific failure, don't guess at findings. Needs-approval: proposal list assembled and presented; halts until the user approves all, some, or none — partial approval is a valid terminal state, not a failure.

## Approval boundaries

Every negative keyword addition is a spend-affecting change and requires the user's explicit approval before being applied — no auto-apply, including for the "obvious" zero-conversion-spend bucket. The user may approve the full list, a subset, or none. Broad-match negatives are called out individually for approval (never bundled silently into a batch) given their higher risk of blocking unintended traffic. Placement-level recommendations (ad-group vs. campaign vs. account shared list) are proposals the user can override per-item before apply.

## What you get

A prioritized negative keyword proposal (sorted by wasted spend) split into zero-conversion-spend and semantic-mismatch buckets, each with the offending query, cost/clicks/conversions in-window, the keyword + match type that triggered it, a recommended negative term with match type and placement level, and a one-line rationale — plus a note on any triggering keyword worth retargeting to a tighter match type. After approval and apply, a live-data confirmation that each approved negative is actually present in the account with the correct match type and level.
