Open this doc every day. Do the routine. Close it. Total time: 5 to 10 minutes per campaign. Most days you’ll add 1 to 5 negatives. After ~60-90 days the daily haul drops to 0-2; keep doing it anyway.
Why daily
The agency minimum cadence is “at least 2 times per week” for the search-terms report. Daily is the stricter version with no downside: catches a bad term in 24 hours instead of 3 to 7 days. One bad term running for a week often costs more than a full week of 5-minute daily reviews.
The job, in one sentence
Find the search terms that triggered your ads yesterday but should never trigger them again, and add them as negative keywords at the right level with the right match type.
That’s it. Everything below is how.
When to do this
- Every day, ideally first thing in the morning
- Bidding state doesn’t matter (works the same on Maximize Clicks or Smart Bidding)
- Continues forever, no end date, no graduation
Before you start
- Phase 1 (Day 1 Health Check in optimization-overview.md) passed for this campaign
- Have access to Google Ads with the saved column set from onboarding
Step 1: Pull yesterday’s search terms report
Campaigns → select the campaign → Insights → Search Terms (or Keywords → Search Terms in the older interface). Filter the date range to Yesterday only. Sort by Cost (descending) so the worst bleeders surface first.
You’re looking at the actual queries Google triggered your ads on yesterday, not the keywords you bid on. The two are different by design (Google expands keywords semantically). The whole point of this routine is catching the expansions you don’t want.
Step 2: Scan for the 7 negative-keyword patterns
For each search term in yesterday’s list, ask “should this term ever trigger our ads again?” The answer is usually obvious. The 7 universal cost-bleeder patterns:
| # | Pattern | Examples | What to negate |
|---|---|---|---|
| 1 | Geographic mismatch | plumber folsom when client serves Roseville only | The city name (e.g., "Folsom") |
| 2 | Wrong service line | commercial plumbing for a residential-only client; tree trimming for a removal-only client | The service modifier ("commercial", "trimming") |
| 3 | DIY / self-service | how to unclog a drain, DIY plumbing, fix it yourself | "DIY", "how to", "yourself" |
| 4 | Job seekers | plumber jobs, HVAC hiring near me, roofer salary | "jobs", "hiring", "career", "salary", "employment" |
| 5 | Educational / wholesale | plumbing course, how to start a roofing business, HVAC training | "course", "training", "how to start", "school", "supplier" |
| 6 | Big-box / retailer hijack | Home Depot plumbing, Lowe's roof, Costco HVAC | "Home Depot", "Lowe's", "Costco", "Walmart", "Target" |
| 7 | Competitor brand names | Roto Rooter near me, Mr Rooter Sacramento | The competitor’s brand ("Roto Rooter", "Mr Rooter") |
If the term doesn’t fit one of these patterns and you’re unsure, wait. Don’t negate aggressively in the first 48 hours, and don’t negate borderline terms until they’ve cost more than the target CPA without converting.
Step 3: Pick the match type (phrase vs exact)
Local lead gen uses two negative match types:
| Match type | Notation | What it blocks | When to use |
|---|---|---|---|
| Phrase | "keyword" | Any search containing the word(s) in any context | Default for most negatives. Catches variations and misspellings. Use for the trigger word that shows up across many bad searches. |
| Exact | [keyword] | Only that exact phrase + its close variants | One-off specific phrases that wouldn’t recur in different contexts. Use as a backup alongside phrase. |
The agency rule of thumb:
- For a recurring trigger word (e.g., a city name showing up in 5+ bad searches), add phrase match on the trigger word:
"folsom". Done. Catches everything fromplumber folsomtofolsom drain repair. - For a specific bad phrase that’s a one-off (e.g.,
competitor name 24/7), add exact match:[competitor name 24/7]. - For a high-stakes universal (competitor brand, DIY, jobs), add both phrase AND exact for belt-and-suspenders coverage. The cost is one extra row; the upside is no edge-case leak.
Real example:
A window-tint client only serves Roseville. Yesterday’s search terms include window tint folsom, window tint folsom CA, and tinting folsom area.
- Add phrase:
"folsom"(catches all 3 above plus any future Folsom-related searches) - Add exact:
[window tint folsom](belt-and-suspenders on the literal phrase)
Two rows, ~30 seconds. Folsom is now permanently excluded.
Step 4: Pick the level (campaign vs ad-group)
| Level | When | Why |
|---|---|---|
| Campaign-level | Universal junk that should never serve from any ad group in this campaign | One add, blocks everything below it |
| Ad-group-level | Cross-ad-group misfire: the term should serve a different ad group in the same campaign | Redirects, not blocks. The term still serves; just not from the wrong ad group. |
Campaign-level negatives (the default):
- All 7 patterns above (geographic, wrong service line, DIY, jobs, educational, big-box, competitor brands) → campaign-level
- These are universally bad for this client and shouldn’t trigger any ad
Ad-group-level negatives (special case, often skipped in first 60 days):
- Used when one ad group is “stealing” searches that belong to another ad group in the same campaign
- a “Tree Service” ad group is triggering for
[tree service near me]when you’d rather that search route to your premium “Tree Removal” ad group. Add[tree service near me]as a negative on the Tree Service ad group, and the search now serves from Tree Removal only. - if you have separate “Plumber Henderson” and “Plumber Las Vegas” ad groups, add
"las vegas"as a negative to the Henderson ad group and"henderson"to the Las Vegas ad group so they don’t compete.
Skip ad-group negatives in the first 30 to 60 days. Let the algorithm learn without surgical restrictions; come back to them after 60 days when you have data on which ad group converts best for which search.
Step 5: Add the negatives in Google Ads
Campaign-level:
- Open the campaign → left sidebar → Keywords → Negative Keywords
- Click + to add
- Set scope to “Add to campaign”
- Paste the negatives, one per line, with match-type notation:
"folsom"
[window tint folsom]
"DIY"
[DIY plumbing]
"Home Depot"
- Save
Ad-group-level:
- Open the campaign → click into the specific ad group → left sidebar → Keywords → Negative Keywords
- Click + to add
- Set scope to “Add to ad group”
- Paste the negatives with notation
- Save
Step 6: Log changes in clients/<client>/optimization-log.md
[Inferred internal documentation] One line per change:
2026-05-06 | added campaign neg "folsom" + [window tint folsom] | reason: client only serves Roseville
2026-05-06 | added campaign neg "DIY" + [DIY plumbing] | reason: not the offering
This trail matters when a future operator (or future-you) wonders why a search term that “obviously” should match isn’t triggering ads. They check the log, see when and why it was negated, and decide whether to revisit.
Watch out for
- Don’t negate aggressively in the first 48 hours. Some seemingly-irrelevant terms turn out to convert. Wait until cost > target CPA before negating, unless the term is obviously off-pattern (a geographic mismatch is obvious; a borderline service term often isn’t).
- Don’t negate at the campaign level when the issue is ad-group routing. That kills the term across all ad groups instead of redirecting it. Use ad-group-level for routing (Step 4 above).
- Don’t pile up the daily review. If you skip 3 days, the report has 72 hours of mixed signal and the daily framework breaks down. Catch up by doing each day separately if possible, or do a single deep weekly review and reset.
- Don’t add broad-match negatives. Phrase + exact only for local lead gen. Broad-match negatives can accidentally block converting traffic.
- Don’t blanket-negate “free” without thinking. “Free quote” is high-intent. “Free service” is bad. Phrase match
"free service"is safer than phrase match"free"alone.
Done when (each day)
- ✅ Yesterday’s search terms report pulled and sorted by cost
- ✅ Bad terms identified using the 7-pattern scan
- ✅ Match type picked for each (phrase by default, exact for one-offs, both for high-stakes)
- ✅ Level picked for each (campaign-level default, ad-group only for cross-routing in 60+ day campaigns)
- ✅ Negatives added in Google Ads
- ✅ Changes logged in the client folder
Where to go from here
- At the end of the week: open optimization-weekly.md for the broader weekly rhythm.
- At the end of the month: open optimization-monthly.md for the deeper monthly review (use the variant matching your current bidding state).
- If something looks badly broken (CPA spike, conversions drop to zero overnight): the daily cadence isn’t enough. Open optimization-weekly.md and run the weekly checks ahead of schedule.