---
name: run-n-gram-analysis
description: >-
  Finds the word patterns quietly draining spend across a Search account by decomposing search terms into one- and
  two-word fragments, aggregating cost and conversion metrics per fragment, and negating the proven losers as
  phrase-match exclusions into two separate shared lists, one for patterns that never convert, one for patterns
  that convert too expensively. This is the statistically sound way to do performance-based negation: a word like a
  freebie qualifier can bleed budget across forty individually-insignificant terms. Run weekly on high-spend
  accounts, monthly on smaller ones or for Shopping/PMax terms. For simple business-irrelevance negation use
  analyze-search-term-reports; for promoting good queries use promote-search-terms-to-keywords; the exclusion-list
  infrastructure itself is created by build-search-campaign-structure or here on first run.
---
# N-gram Waste Analysis and Exclusion

## Purpose
Individual search terms rarely carry enough data to justify a performance verdict, but the words inside them do.
Aggregating spend and conversions per recurring word fragment surfaces systematic waste that no single-term review
can see, and phrase-match exclusions kill the whole pattern at once. Keeping never-converters and
expensive-converters on separate lists matters because they have different futures: the first list is essentially
permanent, the second deserves periodic re-testing.

## When to run
- Cadence by spend: weekly for Search campaigns over roughly €5K/month, bi-weekly mid-spend, monthly low-spend, and
  monthly for Shopping and PMax search terms.
- Immediately after a big keyword or match-type expansion floods in new query patterns.
- Cost per conversion climbed without an obvious cause, pattern waste is a prime suspect.

## When NOT to run
- Under ~500 search terms AND under 30 days of data: the aggregation has no statistical footing yet; wait.
- The waste is obvious single-term irrelevance → `analyze-search-term-reports` handles that faster.
- You want to add winners, not cut losers → `promote-search-terms-to-keywords`.
- Brand traffic questions, brand terms are excluded from this analysis by design.

## Prerequisites
- Target CPA (and for value-bidding accounts, target ROAS) per campaign in scope.
- 30–90 days of search term history: 30 days for high-volume (1,000+ clicks/month), 60 for mid, 90 for low.
- The two shared exclusion lists exist, or will be created in step 6.

## Procedure
1. **Pull the raw terms.** `gads_get_search_terms_report` across in-scope campaigns for the volume-appropriate
   window, with impressions, clicks, cost, conversions, and conversion value. Use `gads_run_gaql_query` on
   `search_term_view` where finer control (per-campaign segmentation, value fields) is needed.
2. **Clean the dataset.** Strip all brand-term rows, brand economics would mask everything else. Compute per-term
   CPA, and for ROAS accounts also ROAS and average order value. Confirm the 500-term/30-day floor holds;
   otherwise stop and report insufficient data.
3. **Decompose into fragments.** For every term, extract single words and adjacent two-word sequences (three-word
   sequences optional for very large datasets, the first two orders carry most of the signal).
4. **Aggregate per fragment.** Sum impressions, clicks, cost, conversions, and value across every term containing
   each unique fragment; compute fragment-level CPA (and ROAS/AOV for value accounts) plus frequency = number of
   distinct terms containing it. Discard fragments appearing in fewer than 3 distinct terms, two data points is
   an anecdote, and anecdotes are handled term-by-term in `analyze-search-term-reports`.
5. **Classify into the two buckets.**
   - NEVER-CONVERTS: zero conversions AND fragment cost above 2x target CPA (ROAS accounts: cost above 2x AOV
     with zero conversions).
   - TOO-EXPENSIVE: converts, but fragment CPA above 1.75x target CPA (ROAS accounts: fragment ROAS below 0.7x
     target).
   Multipliers are risk-tolerance knobs: tighten toward 1.5x CPA / 0.8x ROAS to cut harder, loosen toward 2x /
   0.5x to preserve traffic.
6. **Validate every candidate against its own best terms.** For each qualifying fragment, list all containing
   terms. If even one is a genuine performer, DROP the fragment exclusion, a phrase-match negative blocks the
   good term along with the bad, and handle the weak siblings individually via `analyze-search-term-reports`.
   Only fragments that underperform across their entire term set survive to exclusion. Present the final
   candidate table (fragment, bucket, cost, conversions, terms affected) to the user.
7. **Consult the policy guardrail** (`gads_policy_guardrail`) before the session's first Google Ads write.
8. **Apply exclusions to the two lists.** Create missing lists via `gads_create_shared_negative_set` (one for
   never-converting patterns, one for expensive patterns, never merged). Add approved fragments via
   `gads_add_keywords_to_shared_set` as phrase-match negatives. Every write previews first (validate_only
   default) and commits only after explicit user approval.
9. **Link where the patterns apply.** `gads_link_shared_set_to_campaign` for both lists to all relevant Search,
   Shopping, and PMax campaigns (PMax accepts shared negative lists). Preview → approval → commit.
10. **Verify no self-inflicted damage.** `gads_run_gaql_query` to check for conflicts between new negatives and
    active keywords, and spot-check that top-value terms still serve. A conflict → remove the fragment (preview →
    approval) and downgrade to individual term handling.
11. **Log and schedule.** Record window, dataset size, fragments extracted, additions per list, and estimated
    monthly waste removed (sum of excluded fragments' cost, annualized to monthly). Note the next cadence run.
    Every 6–12 months, optionally test the expensive-patterns list via `run-a-campaign-experiment`: unlink it in
    a 50/50 trial arm for 4–6 weeks, it is the only honest way to re-test excluded patterns, since exclusion
    removed their fresh data.

## Decision rules
- **Frequency floor: 3+ distinct terms per fragment.** Below it, no pattern exists.
- **Never-converts:** 0 conversions + cost > 2x target CPA (or > 2x AOV on value accounts).
- **Too-expensive:** CPA > 1.75x target (or ROAS < 0.7x target). Adjust multipliers only as an explicit
  user-approved risk decision.
- **Absolute veto:** a fragment present in any high-performing term is never excluded, whatever its aggregate says.
- **Match type: phrase for all fragment exclusions**, blocks the exact sequence, permits other words around it;
  broad-negative over-blocks (any order), exact-negative under-blocks (whole query only). Broad is tolerable for
  single-word fragments only.
- **Two lists, always:** never-converters get reviewed rarely (annually at most); expensive converters get the
  experiment-based re-test every 6–12 months because pages, offers, and seasons change their economics.
- **Dataset floor:** 500+ terms or 30+ days, brand rows removed, or the run does not happen.

## Common failure modes
- **Skipping the per-fragment term review** and phrase-blocking a sequence that lives inside a top converter. The
  veto check in step 6 is the single most important step in the skill.
- **Broad-match multi-word negatives**, which block every query containing those words in any order, far wider
  than the analyzed pattern.
- **One combined list.** Convenience today, chaos at review time: permanent irrelevance and provisional
  inefficiency have different lifecycles.
- **Short windows.** Two weeks of data produces fragments that flip classification every run; respect the
  30/60/90-day tiers.
- **Brand contamination.** Brand terms' cheap conversions drag fragment averages down and hide waste; strip them
  first, every time.
- **Treating exclusions as facts forever.** The expensive list encodes last year's landing pages and offers; the
  periodic unlink-experiment exists to catch improvements.
- **Acting on two-term "patterns".** That is a coincidence with a spreadsheet; the 3+ floor is not negotiable.

- **Forgetting the impression check after applying.** A 7-day post-application volume spot-check catches
  over-exclusion while it is still one week of lost traffic instead of a quarter.

## What done looks like
- Dataset met the floors (500+ terms/30+ days, brand-free) and both fragment orders were extracted.
- Every excluded fragment survived the containing-terms veto review.
- Both lists updated in phrase match, linked to all relevant Search/Shopping/PMax campaigns, zero conflicts.
- The log carries the estimated monthly waste removed and the date of the next cadence run.

## Related skills
- Run alongside (different cadence, different question): `analyze-search-term-reports`, relevance negation and
  promotion candidates.
- Run after: `promote-search-terms-to-keywords` for the winners the same data reveals.
- Re-test vehicle: `run-a-campaign-experiment` for the expensive-patterns list review.
- Orchestrated by: `run-search-campaign-optimization-cycle` (query-management phase) and
  `run-shopping-campaign-optimization-cycle` for Shopping terms.
