--- name: google-ads-write-operations context: fork description: "Safely executing Google Ads write operations through the adloop MCP server. Covers campaign creation, keyword management, ad copy, extensions, bidding changes, and entity status changes. Every mutation follows the CEP Protocol (Confirm > Execute > Post check) and requires Michael explicit approval before execution." argument-hint: "[client-name] [customer-id] [operation]" allowed-tools: - mcp__adloop__draft_campaign - mcp__adloop__draft_ad_group - mcp__adloop__update_campaign - mcp__adloop__draft_responsive_search_ad - mcp__adloop__draft_keywords - mcp__adloop__add_negative_keywords - mcp__adloop__update_ad_group - mcp__adloop__draft_callouts - mcp__adloop__draft_structured_snippets - mcp__adloop__draft_sitelinks - mcp__adloop__draft_image_assets - mcp__adloop__pause_entity - mcp__adloop__enable_entity - mcp__adloop__remove_entity - mcp__adloop__confirm_and_apply - mcp__adloop__estimate_budget - mcp__adloop__get_campaign_performance - mcp__adloop__get_keyword_performance - mcp__adloop__get_ad_performance - mcp__adloop__get_search_terms - mcp__adloop__get_negative_keywords - mcp__adloop__run_gaql - mcp__adloop__health_check - mcp__google-ads__run_gaql - mcp__google-ads__get_campaign_performance - mcp__google-ads__get_ad_performance - mcp__google-ads__list_accounts triggers: - "create campaign" - "create ad group" - "add keywords" - "add negatives" - "negative keywords" - "create ad" - "create RSA" - "write to google ads" - "update campaign" - "update bidding" - "change budget" - "pause campaign" - "pause ad" - "enable campaign" - "add sitelinks" - "add callouts" - "add extensions" - "budget forecast" - "keyword planner" - "adloop" --- ## Campaign Creation Strategy Prerequisites Before creating any campaign, the agent must have one of: a. An approved Architecture Output from the PPC Analysis Framework Phase 5 b. An approved greenfield build plan for a GREENFIELD lifecycle stage account c. Explicit instructions from Michael specifying exactly what to create The agent never creates campaigns based solely on its own judgment. When creating from an Architecture Output, follow specs exactly: campaign type, bid strategy, budget, naming per `.claude/rules/campaign-naming-convention.md`, targeting, ad copy. After creation, generate monitoring rules from `.claude/rules/post-creation-monitoring.md`. For Chrome based UI interactions, load `.claude/frameworks/platform-ui-guide.md`. # Google Ads Write Operations (adloop MCP) This skill covers all Google Ads write operations executed through the adloop MCP server. The adloop MCP is the ONLY path for programmatic Google Ads mutations. The read only Google Ads MCP (cohnen/mcp-google-ads) remains the primary tool for auditing and analysis. Use adloop when the task requires creating, modifying, pausing, enabling, or removing entities in a Google Ads account. ## CEP Protocol (Confirm > Execute > Post Check) Every single write operation follows this protocol. No exceptions. ### Step 1: Confirm (Draft and Preview) Draft the change using the appropriate `draft_*` or `update_*` tool. This creates a pending change that has NOT been applied yet. Present the full details of what will happen to Michael in a clear summary: - What entity will be created or modified - Which account and campaign it affects - All settings, values, and targeting parameters - Any budget or bidding implications - What the current state is (for modifications) Then STOP and wait for Michael's explicit approval. Do not proceed. Do not assume. If Michael says go ahead or approved or do it, that counts. Anything ambiguous does not. ### Step 2: Execute (Apply with dry_run=false) Only after receiving explicit approval, call `confirm_and_apply` with `dry_run=false`. The default for `confirm_and_apply` is `dry_run=true`, which simulates the change without applying it. You must explicitly set `dry_run=false` to make the change live. ### Step 3: Post Check (Verify the Change) After execution, verify the change took effect by querying the entity. Use either the adloop read tools (`get_campaign_performance`, `get_keyword_performance`, `run_gaql`) or the read only Google Ads MCP (`mcp__google-ads__run_gaql`) to confirm: - The entity exists with the correct settings - Status matches what was intended (PAUSED for new campaigns, ENABLED if explicitly approved) - Budget, bidding, targeting, and other parameters match the draft Log the verification result. If something does not match, flag it immediately to Michael. ## Safety Rules (Non Negotiable) These rules cannot be overridden under any circumstances. 1. **NEVER execute without Michael's explicit approval.** This is the single most important rule. Drafting is fine. Executing is not. The `confirm_and_apply` tool with `dry_run=false` is the point of no return. 2. **New campaigns always PAUSED.** When using `draft_campaign`, the campaign must be created in a PAUSED state. If the tool does not default to PAUSED, explicitly set the status. Michael decides when to enable. 3. **Budget increases capped at 20% per operation.** If the current daily budget is $100, the maximum new budget in a single operation is $120. For larger increases, break them into multiple steps with approval at each step. This prevents accidental overspend. 4. **Broad match keywords blocked without Smart Bidding.** Never add broad match keywords to a campaign that is not running a Smart Bidding strategy (Maximize Conversions, Maximize Conversion Value, Target CPA, or Target ROAS). Broad match without Smart Bidding wastes budget on irrelevant queries. 5. **All mutations logged.** Every write operation must be recorded in the client's history.md with: date, what was changed, which account, the adloop tool used, and the outcome. 6. **dry_run=true is the default.** The `confirm_and_apply` tool defaults to `dry_run=true`. You must consciously and explicitly set `dry_run=false`. Never pass `dry_run=false` without having completed Step 1 (Confirm) and received approval. 7. **remove_entity is IRREVERSIBLE.** Removals cannot be undone. Always confirm with Michael twice before using `remove_entity`. Prefer `pause_entity` when the goal is to stop something from running. Only use removal when the entity truly needs to be deleted permanently. 8. **Verify account ID before every write.** Before any write operation, confirm you are targeting the correct Google Ads customer ID. A mutation sent to the wrong account is catastrophic. ## Tool Reference ### Campaign and Ad Group Creation | Tool | What It Does | Key Parameters | |---|---|---| | `draft_campaign` | Creates full campaign structure: budget, campaign, ad group, keywords, geo targeting, language targeting | campaign_name, budget_amount_micros, bidding_strategy, geo_target_ids, language_ids, keywords | | `draft_ad_group`| Creates ad group in existing campaign | campaign_id, ad_group_name, cpc_bid_micros | |`update_campaign` | Modifies campaign settings | campaign_id, plus any of: bidding_strategy, budget, geo_targets, language, networks | | `update_ad_group` | Updates ad group name or CPC bid | ad_group_id, name, cpc_bid_micros | ### Ad Copy and Keywords | Tool | What It Does | Key Parameters | |---|---|---| | `draft_responsive_search_ad` | Creates RSA with headlines and descriptions | ad_group_id, headlines (up to 15), descriptions (up to 4), final_url, path1, path2 | | `draft_keywords`| Adds keywords to ad group | ad_group_id, keywords (text + match_type pairs) | |`add_negative_keywords` | Adds negative keywords to campaign | campaign_id, keywords (text + match_type pairs) | ### Extensions (Assets) | Tool | What It Does | Key Parameters | |---|---|---| | `draft_callouts`| Creates callout extensions | callout_texts, customer_id | |`draft_structured_snippets`| Creates structured snippet extensions | header, values, customer_id | |`draft_sitelinks`| Creates sitelink extensions | sitelinks (link_text, final_url, description1, description2) | |`draft_image_assets` | Uploads image assets | image_url or image_data, customer_id | ### Status Changes | Tool | What It Does | Key Parameters | |---|---|---| | `pause_entity`| Pauses campaign, ad group, ad, or keyword | entity_type, entity_id | |`enable_entity`| Enables a paused entity | entity_type, entity_id | |`remove_entity` | IRREVERSIBLE removal | entity_type, entity_id | ### Execution and Planning | Tool | What It Does | Key Parameters | |---|---|---| | `confirm_and_apply`| Executes a drafted change. dry_run=true by default. | dry_run (boolean, default true) | |`estimate_budget` | Keyword Planner budget forecasting | keywords, geo_target_ids, language_ids, date_range | ## Common Workflows ### Workflow 1: Creating a New Search Campaign Prerequisites: client name, customer ID, keyword list, geo targets, budget, landing page URL. 1. **Load client context.** Read `clients/{client-name}/` for profile, history, and open items. Confirm the customer ID matches the client account. 2. **Run budget forecast.** Use `estimate_budget` with the target keywords, geo, and language to validate the proposed budget against Keyword Planner projections. Present the forecast to Michael. 3. **Draft the campaign.** Use `draft_campaign` with: - Campaign name following client naming convention - Budget in micros (multiply dollars by 1,000,000) - Bidding strategy appropriate to the data volume (see bidding selection guide below) - Geo target IDs for the target locations - Language IDs (typically 1000 for English) - Initial keyword list with appropriate match types - Campaign status: PAUSED 4. **Present the full draft to Michael.** Show: campaign name, daily budget, bidding strategy, geo targets, language, keyword count by match type, and estimated performance from the forecast. 5. **Wait for approval.** Do not proceed without it. 6. **Execute.** Call `confirm_and_apply`with`dry_run=false`. 7. **Post check.** Query the campaign via `mcp__google-ads__run_gaql`or`mcp__adloop__run_gaql`to verify it exists, is PAUSED, and has the correct settings. 8. **Draft RSAs.** Use`draft_responsive_search_ad` to create at least one RSA per ad group with 15 headlines and 4 descriptions. Present to Michael for approval before applying. 9. **Add extensions.** Draft sitelinks, callouts, and structured snippets. Present to Michael for approval before applying. 10. **Log everything.** Update `clients/{client-name}/history.md` with the full creation record. ### Workflow 2: Adding Keywords to Existing Campaign 1. **Identify the target ad group.** Query the account to find the correct ad group ID. 2. **Check the campaign bidding strategy.** If the campaign uses Manual CPC or Enhanced CPC, do NOT add broad match keywords. Only exact and phrase match are safe without Smart Bidding. 3. **Draft the keywords.** Use `draft_keywords` with the ad group ID and keyword list. Include match type for each keyword. 4. **Present the draft.** Show the full keyword list with match types and the target ad group/campaign name. 5. **Wait for approval, execute, post check.** Follow CEP. 6. **Verify.** Use `mcp__adloop__get_keyword_performance` or GAQL to confirm the keywords were added with the correct match types. ### Workflow 3: Adding Negative Keywords from Search Term Analysis 1. **Pull search terms.** Use `mcp__adloop__get_search_terms`or`mcp__google-ads__run_gaql` to pull recent search terms with spend and conversion data. 2. **Identify waste.** Flag search terms with significant spend and zero conversions, irrelevant queries, and terms that do not match the client business. 3. **Check existing negatives.** Use `mcp__adloop__get_negative_keywords`to see what is already excluded. Do not add duplicates. 4. **Draft the negative list.** Use`add_negative_keywords` with the campaign ID. Choose match types carefully: - Exact match negatives: block only the specific query - Phrase match negatives: block queries containing the phrase - Broad match negatives: block queries containing all words in any order (use sparingly, can over block) 5. **Present the full list to Michael.** Include the search term data that justifies each negative (spend, clicks, zero conversions). 6. **Wait for approval, execute, post check.** Follow CEP. ### Workflow 4: Creating RSA Ads 1. **Identify the target ad group.** Confirm the ad group ID and the campaign it belongs to. 2. **Draft the RSA.** Use `draft_responsive_search_ad` with: - Up to 15 headlines (30 character limit each). Include at least 2 with keywords, 2 with value props, 2 with CTAs. - Up to 4 descriptions (90 character limit each). Include features, benefits, and a clear CTA. - Final URL (the landing page) - Path fields (path1 and path2, 15 characters each, appear in the display URL) 3. **Pin strategically.** If certain headlines must always show (brand name, legal disclaimers), pin them to specific positions. But do not over pin. Google AI needs flexibility to test combinations. 4. **Present the full ad copy to Michael.** Show all headlines, descriptions, pinning, final URL, and paths. 5. **Wait for approval, execute, post check.** Follow CEP. ### Workflow 5: Updating Bidding Strategy 1. **Pull current performance.** Use `mcp__google-ads__get_campaign_performance` or GAQL to get the campaign trailing 30 day performance: conversions, conversion value, cost, ROAS, CPA. 2. **Assess data volume.** Check if the campaign meets Smart Bidding thresholds: - Target ROAS: 15+ conversions/month minimum, 50+ recommended - Target CPA: 15+ conversions/month minimum, 30+ recommended - Maximize Conversions/Value without target: 10+ conversions/month minimum 3. **Calculate appropriate target.** For tROAS, use the trailing 30 day actual ROAS as the starting point. For tCPA, use the trailing 30 day actual CPA. Do not set targets more than 10% more aggressive than current performance initially. 4. **Draft the change.** Use `update_campaign` with the new bidding strategy and target value. 5. **Present to Michael.** Show: current strategy, proposed strategy, current performance vs proposed target, data volume assessment, and expected learning phase duration (7 to 14 days). 6. **Wait for approval, execute, post check.** Follow CEP. ### Workflow 6: Pausing Underperforming Entities 1. **Identify candidates.** Use performance data to find campaigns, ad groups, ads, or keywords that meet pause criteria: - Keywords: high spend, zero conversions, 30+ days of data - Ads: statistically significant CTR or conversion rate below ad group average - Ad groups: zero conversions over 60+ days with meaningful spend - Campaigns: ROAS below 1.0 over 30+ days with no improvement trend 2. **Present the pause list to Michael.** Include: entity name, entity type, spend, conversions, ROAS/CPA, and the data period. 3. **Wait for approval.** Michael may want to modify the list. 4. **Execute pauses.** Use `pause_entity` for each entity. Execute one at a time to maintain control. 5. **Post check.** Verify each entity is now PAUSED via GAQL query. ### Workflow 7: Adding Extensions (Sitelinks, Callouts, Snippets) 1. **Audit existing extensions.** Query the account to see what extensions already exist. Do not create duplicates. 2. **Draft sitelinks.** Use `draft_sitelinks` with: - Link text (25 characters max) - Final URL (the destination page) - Description line 1 (35 characters max) - Description line 2 (35 characters max) - Aim for 4 to 8 sitelinks per campaign 3. **Draft callouts.** Use `draft_callouts` with callout text (25 characters max each). Aim for 4 to 10 callouts highlighting USPs, offers, and trust signals. 4. **Draft structured snippets.** Use `draft_structured_snippets` with: - Header (from Google predefined list: Brands, Courses, Destinations, Featured Hotels, Insurance Coverage, Models, Neighborhoods, Service Catalog, Shows, Styles, Types) - Values (at least 3, up to 10) 5. **Present all drafts to Michael.** Show the full text of each extension. 6. **Wait for approval, execute, post check.** Follow CEP for each extension type. ### Workflow 8: Budget Forecasting with Keyword Planner 1. **Gather inputs.** Confirm with Michael: target keywords, geo targets, language, and desired date range for the forecast. 2. **Run the forecast.** Use `estimate_budget` with the keywords, geo_target_ids, language_ids, and date_range. 3. **Present results.** Show: estimated impressions, clicks, cost, conversions, CPC, and CTR at various budget levels. Highlight the point of diminishing returns (where increasing budget no longer proportionally increases clicks/conversions). 4. **Recommend a budget.** Based on the forecast and the client goals, suggest a daily budget with rationale. 5. **This is advisory only.** No execution step. The forecast informs campaign creation or budget change decisions. ## Geo Target ID Reference Common geo target IDs for `draft_campaign`and`estimate_budget`: ### Countries | Location | ID | |---|---| | United States | 2840 | | Canada | 2124 | | United Kingdom | 2826 | | Australia | 2036 | | Germany | 2276 | | France | 2250 | ### US States (Selected) | Location | ID | |---|---| | California | 21137 | | Texas | 21176 | | New York | 21167 | | Florida | 21139 | | Illinois | 21149 | | Pennsylvania | 21172 | | Ohio | 21170 | | Georgia | 21142 | | North Carolina | 21168 | | Michigan | 21158 | | Tennessee | 21175 | | Indiana | 21150 | ### US Metro Areas (Selected) | Location | ID | |---|---| | New York, NY | 200501 | | Los Angeles, CA | 200203 | | Chicago, IL | 200602 | | Houston, TX | 200618 | | Dallas Fort Worth, TX | 200623 | | Atlanta, GA | 200524 | | Miami, FL | 200528 | | Phoenix, AZ | 200753 | | Nashville, TN | 200659 | | Indianapolis, IN | 200527 | For locations not listed here, use the Google Ads Geo Target Constant lookup via GAQL: ```sql SELECT geo_target_constant.name, geo_target_constant.id, geo_target_constant.canonical_name FROM geo_target_constant WHERE geo_target_constant.name LIKE '%[location name]%' LIMIT 10 ``` ## Language ID Reference | Language | ID | |---|---| | English | 1000 | | Spanish | 1003 | | French | 1002 | | German | 1001 | | Portuguese | 1014 | | Italian | 1004 | | Japanese | 1005 | | Chinese (Simplified) | 1017 | | Korean | 1012 | | Arabic | 1019 | | Dutch | 1010 | | Russian | 1031 | ## Bidding Strategy Selection Guide Use this when creating campaigns or updating bidding strategies: | Scenario | Recommended Strategy | Notes | |---|---|---| | New campaign, no conversion data | Maximize Clicks (with bid cap) or Manual CPC | Gather data first. Set a bid cap to prevent runaway CPCs. | | 10 to 30 conversions/month | Maximize Conversions (no target) | Let Smart Bidding learn. Do not set a tCPA yet. | | 30+ conversions/month, CPA focused | Target CPA | Set target at or slightly above trailing 30 day CPA. | | 30+ conversions/month, revenue focused | Target ROAS | Set target at or slightly below trailing 30 day ROAS. | | 50+ conversions/month, ecommerce | Maximize Conversion Value with tROAS | Best for ecommerce with variable order values. | | PMax campaign | Maximize Conversion Value (with or without tROAS) | PMax requires value based bidding. tROAS optional until 30+ conversions/month. | | Brand campaign, maximize impression share | Target Impression Share | Set position target (top, absolute top) and max CPC cap. | ## Error Handling ### Common adloop Errors and Resolutions | Error | Cause | Resolution | |---|---|---| | Authentication failure | OAuth token expired or invalid | Check adloop health with `health_check`. If auth is broken, flag to Michael for reauthorization. | | Invalid customer ID | Wrong account ID format or access not granted | Verify the customer ID (10 digits, no dashes). Confirm the account is accessible via adloop. | | Entity not found | The campaign/ad group/keyword ID does not exist or was removed | Re query the account to find the correct entity ID. IDs may differ between adloop and the read only MCP. | | Budget constraint | Attempting to set a budget below minimum or above maximum | Google Ads minimum daily budget varies by campaign type. Search minimum is typically $1/day. | | Duplicate entity | Trying to create something that already exists | Query existing entities first to avoid duplicates. Use unique names. | | Policy violation | Ad copy or keyword violates Google Ads policies | Review the policy violation details. Fix the content and redraft. Common issues: trademark terms, restricted categories, too many exclamation marks. | | Rate limit | Too many API calls in a short period | Wait 60 seconds and retry. If persistent, reduce the frequency of calls. | | dry_run mismatch | Called confirm_and_apply without a pending draft | Make sure you have called a `draft_*`or`update_*`tool in the same session before calling`confirm_and_apply`. | ### When adloop Is Unavailable If adloop is down or returning persistent errors: 1. Run `health_check` to diagnose. 2. Flag the issue to Michael immediately. 3. Do NOT attempt to make changes through the Chrome browser or any other path as a workaround. 4. Document what was planned so it can be executed once adloop is restored. 5. Switch to read only analysis using the Google Ads MCP until adloop is back. ## Audit Trail Requirements Every write operation must be logged in the client `history.md` with this format: ``` ### [Date] Google Ads Write Operation **Account:** [Customer ID] **Operation:** [What was done] **Tool:** [adloop tool name] **Entities affected:** [Campaign/Ad Group/Keyword names and IDs] **Approved by:** Michael (timestamp or reference to approval) **Post check result:** [Verified/Issue found] **Notes:** [Any relevant context] ``` Also create an Asana subtask under the client parent task documenting the write operation and its verification status. ## Integration with Read Only MCP The adloop MCP handles writes. The cohnen/mcp-google-ads MCP handles reads. Use them together: - **Before writing:** Use the read only MCP to understand current state, pull performance data, and verify account structure. - **After writing:** Use the read only MCP to verify changes took effect. The read only MCP may have slight propagation delay (up to a few minutes). - **During analysis:** Always use the read only MCP for audits and reporting. Never use adloop read tools as the primary data source for audits because adloop read tools are primarily there to support the write workflow. ## Dependencies - Requires adloop MCP server to be running and authenticated - Requires client context in `clients/{client-name}/`(profile, history, open items) - References`.claude/rules/gaql-field-reference.md`for GAQL query construction - References`.claude/rules/data-verification.md`for post check verification standards - References`.claude/frameworks/vertical-benchmarks.md` for bidding target recommendations - Uses cohnen/mcp-google-ads (read only) for verification queries - Asana integration for audit trail and task tracking