Execute approved draft actions in Google Ads accounts. Supports four safe mutation types plus bounded budget writes: add campaign-level negatives, add ad-group-level negatives, pause keywords, pause a…
Library skill — the default version is maintained in GitHub; edits you make live in your own clone.
API v20 confirmed working (2026-03-15). v18 is sunset (404), v19 unstable (500). Full write cycle proven: add campaign negative → GAQL verify → remove → verify removal. Keyword pauses and ad group pauses fully scaffolded and hardened. CLI scripts at
scripts/apply-layer/. Smoke test:scripts/apply-layer/gads-smoke-test.sh <customer_id>SeeAPPLY-LAYER.mdfor design details andscripts/apply-layer/README.mdfor the public CLI implementation guide. SeeOPERATOR-PLAYBOOK.mdfor the full operator workflow loop.
Read first:
- OPERATOR-PLAYBOOK.md — full operator workflow (connect → select → review → apply → verify → undo)
- APPLY-LAYER.md — design document, API specs, error handling
- drafts/DRAFTS.md — draft system documentation
Read workspace:
- workspace/ads/drafts/_index.md — current queue
- workspace/ads/drafts/_summary.md — prioritized summary
- workspace/ads/audit-trail/_log.md — previous apply sessions (if any)
- workspace/ads/audit-trail/reversal-registry.json — active reversals
/google-ads apply [draft-file]
Flow: 1. Read the draft file 2. Parse all proposed actions (manifest-first for budget drafts; legacy parsing for v1 negatives/pauses) 3. Validate each action (correct account, valid targets, within live apply scope) 4. Resolve human-readable names to Google Ads resource IDs via GAQL 5. Display dry run with every mutation listed, action type summary, and risk assessment 6. Wait for operator confirmation ("confirm" or "cancel") 7. Execute each action via Google Ads REST API v20 8. Verify changes via GAQL re-query 9. Write audit trail (session log, master log, reversal registry) 10. Update draft status to "applied" 11. Show post-apply summary with undo instructions
/google-ads apply review [draft-file]
/google-ads apply review --all
Flow: 1. Parse the draft into structured actions 2. Show action breakdown with counts by type and risk levels 3. Show confidence and dependencies 4. Provide a proceed/defer recommendation 5. Show next-step commands (dry-run or full apply)
No network calls, no API access needed. Pure local analysis.
/google-ads apply status
Shows at a glance: - Connection state (account, API version, credentials) - Pending drafts with status - Active reversals grouped by draft - Recent apply sessions - Suggested next step
/google-ads undo [reversal-id]
Flow:
1. Look up reversal record in workspace/ads/audit-trail/reversal-registry.json
2. Display what will be reversed
3. Warn if change has been live >7 days
4. Wait for confirmation
5. Execute reversal via Google Ads API
6. Verify via GAQL
7. Update reversal registry (status: "undone")
/google-ads undo-draft [draft-file]
Reverses ALL active actions from a specific draft. Same confirmation flow.
/google-ads apply log
Shows recent apply sessions from workspace/ads/audit-trail/_log.md.
| Action | Target | Scope | Risk |
|---|---|---|---|
| Add negative keyword | Campaign criterion | Campaign-level negative | Low |
| Add negative keyword | Ad group criterion | Ad group-level negative | Low |
| Pause keyword | Ad group criterion | Set status to PAUSED | Low |
| Pause ad group | Ad group | Set status to PAUSED | Medium |
| Set campaign daily budget | Campaign budget | Update amount_micros |
Medium |
If a draft contains actions outside the supported scope, the apply command will: 1. List the out-of-scope actions 2. Explain which are out of scope and why 3. Offer to apply ONLY the in-scope actions 4. Never execute out-of-scope actions regardless of confirmation
| Action | Version | Why Blocked |
|---|---|---|
| Bid strategy changes | v2 | Can disrupt Smart Bidding learning |
| Campaign creation | v3 | Large blast radius |
| RSA modifications | v4 | Learning period impact |
| Enable paused entities | Never in v1 | Higher risk than pausing |
| Delete anything | Never | Pause instead |
The apply layer parses these sections from draft markdown files:
| Section | Action Type | Template |
|---|---|---|
| Section A: Negatives to ADD | ADD_NEGATIVE |
negative-draft.md |
| Section D: CRITICAL KEYWORD-LEVEL RECOMMENDATION | PAUSE_KEYWORD |
negative-draft.md |
| Section A: Keywords to PAUSE | PAUSE_KEYWORD |
pause-draft.md |
| Section B: Ad Groups to PAUSE | PAUSE_ADGROUP |
pause-draft.md |
Both negative-draft.md and pause-draft.md templates are supported. Mixed-type drafts (negatives + pauses in one file) are fully supported — the parser extracts from all applicable sections and deduplicates.
Budget drafts are different:
- They MUST include ## Apply Manifest
- The manifest is authoritative when present
- Draft-level meta.budget_policy controls whether any net increase is allowed
drafts/templates/negative-draft.md — negative keyword additions + removals + narrowsdrafts/templates/pause-draft.md — keyword pauses + ad group pauses + impact summaryBefore showing the dry run, validate:
If validation fails, report which actions failed and why. Don't block the entire apply — allow valid actions to proceed.
═══════════════════════════════════════════════════════
DRY RUN: [draft-file]
═══════════════════════════════════════════════════════
Account: [Name] (CID: [ID])
Actions: [N] valid / [M] total
# Action Target Detail Risk
--- --------------- --------------------------- -------------------------- ------
1 ADD NEG Campaign: [name] "near me" [PHRASE] Low
2 ADD NEG Campaign: [name] "debris chute" [PHRASE] Low
...
13 PAUSE KW AG: [name] "waste mgmt" [EXACT] Low
14 PAUSE AG Campaign: [name] [ad group name] Medium
Summary:
• 12 negative keyword addition(s)
• 1 keyword pause(s)
• 1 ad group pause(s)
• Reversibility: All actions reversible
⚠️ This will make REAL changes to account [CID].
Type 'confirm' to proceed, or 'cancel' to abort:
After execution, run verification queries:
| Action | Verification Query | What's Confirmed |
|---|---|---|
| Add campaign negative | campaign_criterion WHERE negative=TRUE |
Keyword exists in campaign |
| Add ad group negative | ad_group_criterion WHERE negative=TRUE |
Keyword exists in ad group |
| Pause keyword | keyword_view + status check |
Status is PAUSED |
| Pause ad group | ad_group + status check |
Status is PAUSED |
After every apply session, these files are updated:
workspace/ads/audit-trail/_log.md — append-only session summaryworkspace/ads/audit-trail/YYYY-MM-DD-apply-session.md — full action-by-action logworkspace/ads/audit-trail/reversal-registry.json — machine-readable undo recordsworkspace/ads/drafts/_index.md — moved to Applied sectionworkspace/ads/change-log.md — record of what changed| Script | Purpose |
|---|---|
gads-apply.sh |
Full apply flow: parse → validate → dry-run → confirm → execute → verify → audit |
gads-apply.sh --dry-run |
Parse and show dry run only |
gads-apply.sh --parse-only |
Parse draft to JSON (debugging) |
gads-review.sh |
Parse and show operator-facing review (no API calls) |
gads-review.sh --all |
Review all pending drafts |
gads-undo.sh <rev-id> |
Undo a single action |
gads-undo.sh --draft <file> |
Undo all actions from a draft |
gads-undo.sh --list |
List all active reversals |
gads-status.sh |
Full operator status overview |
gads-status.sh --applied |
Show only applied actions |
gads-status.sh --pending |
Show only pending drafts |
gads-smoke-test.sh |
End-to-end write cycle test |