Skip to content
Marketing
Command

/negative-keyword-sweep

Find wasted spend in Google Ads search terms and add negatives at the right scope (account list, campaign, or ad group). Use when the user says "find junk keywords", "stop wasting on bad searches", or wants a search-terms cleanup.

From plugin
417 skills1 agents7 commands1 MCP
shell
$ npx -y skills add markifact/markifact-mcp --agent claude-code

Ships with markifact. Installing the plugin gets this command.

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/negative-keyword-sweep

Context preview

What this command does when you run it.

Find wasted spend in Google Ads search terms and add negatives at the right scope (account list, campaign, or ad group). Use when the user says "find junk keywords", "stop wasting on bad searches", or wants a search-terms cleanup.

Command definition

negative-keyword-sweep.md
description: Find wasted spend in Google Ads search terms and add negatives at the right scope (account list, campaign, or ad group). Use when the user says "find junk keywords", "stop wasting on bad searches", or wants a search-terms cleanup.
disable-model-invocation: true
argument-hint: [scope, e.g. "campaign Spring" or "all Search campaigns"]

Goal

Pull the search-terms report, identify spend that isn't producing, group it intelligently, and add negatives at the right level — without nuking legitimate intent.

Inputs to confirm (batch)

1. Account name (substring) — required. 2. Scope — single campaign, list of campaigns, or "all Search campaigns" — required. 3. Lookback — default 30 days; user can override (60 / 90). 4. Waste thresholds — defaults; allow override:

  • **No-converter**: spend ≥ $X over lookback AND 0 conversions. Default $X = 2× target CPA, or $50 if no target.
  • **Low-CVR offender**: spend ≥ 3× target CPA AND CVR < 25% of account CVR.
  • **Off-brand / off-intent**: terms that match a denylist of words (e.g. `free`, `jobs`, `careers`, `tutorial`, `review`, `salary`, `download`, `cheap`, `pirate`, `crack`) — calibrated to vertical.

5. Negative scope preference — default behavior:

  • Recurring junk seen across multiple campaigns → **account-level shared negative list**.
  • Waste seen only in one campaign → **campaign-level**.
  • Single-theme misintent (e.g. "free" only hurts a paid product ad group) → **ad-group-level**.
  • Default match type: **phrase**, except for single-word obvious junk → **broad** isn't an option (negatives have no broad), so use **exact** for single tokens like `free`.

Workflow

1. **Discover** ops: `gads_select_accounts`, `gads_list_report_fields`, `gads_get_report`, `gads_create_negative_keyword_list`, `gads_attach_negative_list_to_campaigns`, `gads_add_keywords_to_negative_list`, `gads_add_negative_keywords_to_campaigns`, `gads_add_negative_keywords_to_ad_groups`. 2. **Inspect** every op via `get_operation_inputs`. 3. **Resolve account** (substring). 4. **Pull search-terms report** via `gads_get_report` at the search-term granularity (`search_term_view` resource). Required fields: search_term, campaign_id/name, ad_group_id/name, impressions, clicks, cost, conversions, conv_value, ctr, cvr. 5. **Compute baselines**: account-level CVR over lookback. Compute target CPA if not given (use account history / average across the scope). 6. **Apply thresholds** → candidate list. Tag each candidate with the trigger reason (no-conv, low-CVR, denylist). 7. **Cluster candidates by intent**. Group on shared roots / themes (e.g. `free trial spreadsheet`, `free template excel`, `free download` → cluster "free*"). For each cluster, propose:

  • Negative keyword(s) (the minimum tokens needed to block the cluster — usually a phrase).
  • Match type (phrase by default; exact for single-token denylist hits; phrase for multi-word patterns).
  • Scope (account / campaign / ad-group) per the rules above.

8. **Build a preview table** showing every proposed negative with: keyword, match, scope, target campaigns/ad groups, wasted spend that would have been blocked, and a sample of 1–3 search terms it covers. Wait for user confirmation. 9. **Execute**:

  • Account-level batch → if a list with the right purpose already exists, use `gads_add_keywords_to_negative_list`. If not, `gads_create_negative_keyword_list` then `gads_add_keywords_to_negative_list` then `gads_attach_negative_list_to_campaigns`.
  • Campaign-level batch → `gads_add_negative_keywords_to_campaigns`.
  • Ad-group-level batch → `gads_add_negative_keywords_to_ad_groups`.

10. **Confirm**: count by scope, total estimated spend blocked.

Use `safe-write-operations` for steps 9 onward.

Platform-specific rules the model MUST respect

  • **Negatives have no broad match.** Match types are `EXACT`, `PHRASE`, `BROAD` — but Google's docs note that broad-match negatives only block the exact words and their close variants. The mental model: prefer **phrase** for clusters, **exact** for single-word junk.
  • **Phrase negative blocks any query containing the phrase in order**, ignoring close variants on individual words. Don't add `running shoes` as exact if you mean to block `cheap running shoes`, `red running shoes`, etc.
  • **Don't over-negate.** Negating a single broad term like `software` from a software seller will block legitimate intent. Always look at the cluster's full search-term sample before adding.
  • **Account-level shared lists scale better.** Use them for evergreen junk (`jobs`, `careers`, `download`, `crack`). Don't pollute campaigns with the same negative repeated 10 times.
  • **Don't add negatives that conflict with active keywords.** If the ad group bids on `free trial`, don't add `free` as a negative — Google will silently stop serving it.
  • **PMax has its own negative-keyword surface** (account-level only, requires support request historically; check current op availability). Search negatives don't apply to PMax automatically.
  • **Branded terms**: never negate the brand. Always exclude brand variants from candidate clusters.
  • **Symmetric vs asymmetric search terms**: if a term has converted at all in lookback (≥ 1 conv), drop it from candidates regardless of CVR thresholds.

Failure modes & recoveries

  • Search-terms report empty or near-empty → campaign too new, lookback too short, or campaign isn't Search/PMax. Tell user.
  • "Negative keyword conflicts with positive keyword" rejection → list the conflict and ask user to choose.
  • Cluster has both winners and losers (some terms convert, some don't) → don't add a phrase negative; recommend tighter ad group structure or single-keyword exact negatives instead.

Output to user

Preview:

| Negative | Match | Scope | Target | Wasted spend blocked | Sample terms | |---|---|---|---|---|---| | free | EXACT | account list "Junk - Free" | all Search | $312 | `free crm`, `free tool` | | jobs | PHRASE | account list

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withmarkifact

Manage Google Ads, Meta Ads, TikTok Ads, LinkedIn Ads, Microsoft Ads, Reddit Ads, Pinterest Ads, Snapchat Ads, Amazon Ads, DV360, GA4, BigQuery, Google Search Console, Google Business Profile, Google Merchant Center, Facebook, Instagram, LinkedIn, Shopify,

Get the whole plugin, auto-invoked
Stats
41
Stars
0
Views
4
Forks
Maintained
Maintenance
Shell
Language
MIT
License
2mo ago
Last commit
3mo ago
Created

Repo: markifact/markifact-mcp

Other commands on markifact.