Skip to main content
Glama

Draft campaign changes

update_campaign

Draft an update to an existing campaign — returns a PREVIEW, does NOT apply.

Only the parameters passed are changed; omitted ones stay as they are, and at least one change is required. Replacing geo targets keeps the campaign's negative geo exclusions (the preview lists them) unless geo_exclude_ids is passed too. A budget change shows the current amount; when the budget is shared with other campaigns, the preview names them and needs a double confirmation, because the new amount covers all of them. A bidding change on a campaign in a portfolio bid strategy takes it out of the portfolio, also with a double confirmation.

Returns a preview with a plan_id plus any warnings; nothing changes until confirm_and_apply applies it.

Google Ads API: https://developers.google.com/google-ads/api/docs/start

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "campaign_id": "<campaign_id>"
    },
    "name": "update_campaign"
  }
}

Input Schema

NameRequiredDescriptionDefault
max_cpcNoMaximize Clicks CPC cap in the account's currency when bidding_strategy is TARGET_SPEND, or when the existing campaign already uses TARGET_SPEND. Increases are limited by the config's max_bid_increase_pct. 0 leaves it unchanged.
target_cpaNoTarget CPA in the account's currency; required if bidding_strategy is TARGET_CPA. 0 leaves it unchanged.
ad_scheduleNoREPLACES the campaign's schedule windows (shape as in draft_campaign). Omitted leaves them unchanged; [] removes them, so the campaign serves at all hours. The preview shows the current ones (current_ad_schedule). A first schedule and clearing a schedule both need a double confirmation. Only windows that differ are removed or added, removals first. Apply refuses if the exclusions or windows changed after the preview.
campaign_idYesThe numeric ID of the campaign to update (required).
customer_idNoGoogle Ads customer ID (digits, e.g. "1234567890"). Empty uses the configured default account.
target_roasNoTarget ROAS as a ratio (e.g. 4.0 = 400%); required if bidding_strategy is TARGET_ROAS. 0 leaves it unchanged.
daily_budgetNoNew daily budget in the account's currency (not micros), at most the config's max_daily_budget. 0 leaves it unchanged. On a shared budget it is the amount for every campaign sharing it.
language_idsNoREPLACES all language targets; must not be empty when given. Common IDs: "1001" German, "1000" English, "1002" French, "1003" Spanish, "1004" Italian.
geo_target_idsNoREPLACES all positive geo targets; must not be empty when given. Common IDs: "2276" Germany, "2040" Austria, "2756" Switzerland, "2840" USA, "2826" UK.
geo_exclude_idsNoREPLACES the campaign's negative location criteria. Omitted leaves them unchanged; [] removes them. May not overlap geo_target_ids. The preview shows the current ones (current_geo_exclude_ids); dropping any needs a double confirmation, because the campaign can serve there again. A location can move between geo_target_ids and geo_exclude_ids in one call: its old criterion is removed before the new one is created.
location_optionNoPRESENCE | PRESENCE_OR_INTEREST | SEARCH_INTEREST. Who the geo targets reach; the preview shows the current value (current_location_option) and warns when the new one is anything but PRESENCE. Empty leaves it unchanged.
bidding_strategyNoMAXIMIZE_CONVERSIONS | TARGET_CPA | TARGET_ROAS | MAXIMIZE_CONVERSION_VALUE | TARGET_SPEND | MANUAL_CPC. Empty leaves the strategy unchanged.
final_url_suffixNoParameters appended to the landing page URL. Omitted leaves it unchanged; "" removes it.
keyword_match_typeNoCampaign-level broad match. BROAD turns it on and CONVERTS every existing phrase and exact keyword in the campaign to broad match (the originals show as Removed; turning it off does not restore them), and since September 2026 Google upgrades such campaigns to AI Max. Refused unless the campaign uses Smart Bidding (MAXIMIZE_CONVERSIONS, MAXIMIZE_CONVERSION_VALUE, TARGET_CPA, TARGET_ROAS), checked again at apply; needs a double confirmation. UNSPECIFIED turns it off: no further conversions, but converted keywords stay broad. Moving a campaign with broad match on to a non-Smart bidding_strategy is refused unless the same call passes UNSPECIFIED. The preview shows the current value. Empty leaves it unchanged.
tracking_url_templateNoCampaign tracking template; must contain {lpurl} or a variant. Omitted leaves it unchanged; "" removes it.
url_custom_parametersNoList of {"key", "value"}; REPLACES the campaign's custom parameters. Keys alphanumeric, max 8 characters. Omitted leaves them unchanged; [] removes them. The preview shows each current value (current_tracking_url_template etc.), names any removal, and gives example_click: one of the campaign's final URLs with the campaign's options applied. It is approximate: a template on the ad group, ad or keyword overrides the campaign's.
display_network_enabledNoEnable Search campaign display expansion. Omitted leaves the setting unchanged.
search_partners_enabledNoInclude ads on Search partners. Omitted leaves the setting unchanged.
negative_location_optionNoPRESENCE | PRESENCE_OR_INTEREST. Who the location exclusions exclude; the preview shows the current value. PRESENCE excludes fewer people (only those physically there), so it widens reach and the preview warns. Empty leaves it unchanged.
display_expansion_enabledNoAlias for display_network_enabled; both must match when both are given.

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / ad_schedule
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "REPLACES the campaign's schedule windows (shape as in\ndraft_campaign). Omitted leaves them unchanged; [] removes them, so\nthe campaign serves at all hours. The preview shows the current ones\n(current_ad_schedule). A first schedule and clearing a schedule both\nneed a double confirmation. Only windows that differ are removed or\nadded, removals first. Apply refuses if the exclusions or windows\nchanged after the preview."
      +}
    • addedInput schema / properties / geo_exclude_ids
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "REPLACES the campaign's negative location criteria.\nOmitted leaves them unchanged; [] removes them. May not overlap\ngeo_target_ids. The preview shows the current ones\n(current_geo_exclude_ids); dropping any needs a double confirmation,\nbecause the campaign can serve there again. A location can move\nbetween geo_target_ids and geo_exclude_ids in one call: its old\ncriterion is removed before the new one is created."
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / keyword_match_type
      Added value: +{
      +  "default": "",
      +  "description": "Campaign-level broad match. BROAD turns it on and\nCONVERTS every existing phrase and exact keyword in the campaign to\nbroad match (the originals show as Removed; turning it off does not\nrestore them), and since September 2026 Google upgrades such\ncampaigns to AI Max. Refused unless the campaign uses Smart Bidding\n(MAXIMIZE_CONVERSIONS, MAXIMIZE_CONVERSION_VALUE, TARGET_CPA,\nTARGET_ROAS), checked again at apply; needs a double confirmation.\nUNSPECIFIED turns it off: no further conversions, but converted\nkeywords stay broad. Moving a campaign with broad match on to a\nnon-Smart bidding_strategy is refused unless the same call passes\nUNSPECIFIED. The preview shows the current value. Empty leaves it\nunchanged.",
      +  "type": "string"
      +}
  3. Changed5 schema fields changed
    • addedInput schema / properties / final_url_suffix
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Parameters appended to the landing page URL. Omitted\nleaves it unchanged; \"\" removes it."
      +}
    • addedInput schema / properties / location_option
      Added value: +{
      +  "default": "",
      +  "description": "PRESENCE | PRESENCE_OR_INTEREST | SEARCH_INTEREST.\nWho the geo targets reach; the preview shows the current value\n(current_location_option) and warns when the new one is anything\nbut PRESENCE. Empty leaves it unchanged.",
      +  "type": "string"
      +}
    • addedInput schema / properties / negative_location_option
      Added value: +{
      +  "default": "",
      +  "description": "PRESENCE | PRESENCE_OR_INTEREST. Who the\nlocation exclusions exclude; the preview shows the current value.\nPRESENCE excludes fewer people (only those physically there), so\nit widens reach and the preview warns. Empty leaves it unchanged.",
      +  "type": "string"
      +}
    • addedInput schema / properties / tracking_url_template
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Campaign tracking template; must contain {lpurl}\nor a variant. Omitted leaves it unchanged; \"\" removes it."
      +}
    • addedInput schema / properties / url_custom_parameters
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "List of {\"key\", \"value\"}; REPLACES the\ncampaign's custom parameters. Keys alphanumeric, max 8 characters.\nOmitted leaves them unchanged; [] removes them. The preview shows\neach current value (current_tracking_url_template etc.), names any\nremoval, and gives example_click: one of the campaign's final URLs\nwith the campaign's options applied. It is approximate: a template\non the ad group, ad or keyword overrides the campaign's."
      +}
  4. Changed1 schema field changed
    • changedInput schema / properties / daily_budget / description
      Previous value: -"New daily budget in the account's currency (not micros),\nat most the config's max_daily_budget. 0 leaves it unchanged."New value: +"New daily budget in the account's currency (not micros),\nat most the config's max_daily_budget. 0 leaves it unchanged. On a\nshared budget it is the amount for every campaign sharing it."
  5. Changed12 schema fields changed
    • addedInput schema / properties / bidding_strategy / description
      Added value: +"MAXIMIZE_CONVERSIONS | TARGET_CPA | TARGET_ROAS |\nMAXIMIZE_CONVERSION_VALUE | TARGET_SPEND | MANUAL_CPC. Empty leaves\nthe strategy unchanged."
    • addedInput schema / properties / campaign_id / description
      Added value: +"The numeric ID of the campaign to update (required)."
    • addedInput schema / properties / customer_id / description
      Added value: +"Google Ads customer ID (digits, e.g. \"1234567890\"). Empty\nuses the configured default account."
    • addedInput schema / properties / daily_budget / description
      Added value: +"New daily budget in the account's currency (not micros),\nat most the config's max_daily_budget. 0 leaves it unchanged."
    • addedInput schema / properties / display_expansion_enabled / description
      Added value: +"Alias for display_network_enabled; both must\nmatch when both are given."
    • addedInput schema / properties / display_network_enabled / description
      Added value: +"Enable Search campaign display expansion.\nOmitted leaves the setting unchanged."
    • addedInput schema / properties / geo_target_ids / description
      Added value: +"REPLACES all positive geo targets; must not be empty\nwhen given. Common IDs: \"2276\" Germany, \"2040\" Austria, \"2756\"\nSwitzerland, \"2840\" USA, \"2826\" UK."
    • addedInput schema / properties / language_ids / description
      Added value: +"REPLACES all language targets; must not be empty when\ngiven. Common IDs: \"1001\" German, \"1000\" English, \"1002\" French,\n\"1003\" Spanish, \"1004\" Italian."
    • addedInput schema / properties / max_cpc / description
      Added value: +"Maximize Clicks CPC cap in the account's currency when\nbidding_strategy is TARGET_SPEND, or when the existing campaign\nalready uses TARGET_SPEND. Increases are limited by the config's\nmax_bid_increase_pct. 0 leaves it unchanged."
    • addedInput schema / properties / search_partners_enabled / description
      Added value: +"Include ads on Search partners. Omitted leaves\nthe setting unchanged."
    • addedInput schema / properties / target_cpa / description
      Added value: +"Target CPA in the account's currency; required if\nbidding_strategy is TARGET_CPA. 0 leaves it unchanged."
    • addedInput schema / properties / target_roas / description
      Added value: +"Target ROAS as a ratio (e.g. 4.0 = 400%); required if\nbidding_strategy is TARGET_ROAS. 0 leaves it unchanged."
  6. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnlyHint=false, destructiveHint=false and openWorldHint=true; the description goes far beyond that by disclosing the preview/plan_id contract, the four cases needing double confirmation (shared budget, portfolio bid strategy exit, first/cleared ad schedule, geo exclusion removal), and the irreversible nature of the broad-match conversion. Those are exactly the consequences an agent could not infer from the annotations — even the destructiveHint=false tension is explained by the fact that the call itself only drafts.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the highest-value fact (preview, does not apply) and then organized by consequence, so an agent can stop reading early. It is dense and long-winded in places — the shared-budget and portfolio-exit sentences could be tightened — but for a 20-parameter tool almost every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 20 parameters, one required field, zero enums and an output schema, the description supplies the missing glue: the preview-then-apply workflow, confirmation thresholds, and the inertia rule for omitted parameters. Return values are deliberately left to the output schema, so nothing material is unaccounted for.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so per-parameter meaning is already carried, yet the description adds cross-parameter rules the schema cannot express: only passed parameters change, at least one change is required, and replacing geo targets preserves negative geo exclusions unless geo_exclude_ids is passed too. That is genuine added semantics rather than restatement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb and resource plus the crucial qualifier: "Draft an update to an existing campaign — returns a PREVIEW, does NOT apply." That single line separates it from confirm_and_apply and from the draft_* creation siblings, which is exactly what an agent needs before choosing a tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly routes the agent: nothing changes until confirm_and_apply applies it, naming the alternative and the follow-up step. What's missing is explicit when-not guidance (for example, that an already-applied campaign shouldn't be re-previewed, or which sibling handles non-campaign updates); the workflow is implied rather than enumerated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.