# Edit budgets and statuses of many campaigns from a sheet

> Tier: recipe. Operating recipe: real tool sequence, core rules, known traps.

Lays out campaigns, ad sets and ads of one or more accounts of a workspace in a sheet with their current status, budget and results, lets the person type the new values, then reads the edited rows back, previews every change in one message with change_campaigns (changes) and applies them after the person confirms, writing the outcome of each row back into the sheet.

**Intent.** The person types new budgets and statuses in a sheet; Claude previews every edit at once and applies them only after one confirmation.

## When to use

- Someone asks to change many budgets or statuses at once, to edit campaigns in a spreadsheet, or for a bulk editor.
- A weekly budget review where the media buyer wants to see every line before deciding.

## When not to use

- One or two changes: preview them with change_campaigns in the conversation, no sheet needed.
- Creating campaigns, ads or targeting: that is a campaign launch, not an edit.
- Google Ads budgets: change_campaigns changes Google Ads statuses only; list those budget moves for the person to make in Google Ads.
- Hosts without a sheet Claude can write (no Claude Sheets, no spreadsheet connector): show the same rows as a table in the conversation and take the edits there.

## Sources

Required: any connected source

## Preconditions

- The account is among the chosen accounts, confirmed via list_accounts.

## Inputs

- `workspace` (required): The client workspace whose accounts the sheet covers.
- `accounts` (required): The ad accounts to include, one or more per platform.
- `level`: campaign, ad set or ad; a sheet can hold several levels on separate tabs. Default: ad set.
- `window`: The period of the results shown next to each row. Default: last 7 complete days.

## Procedure

1. Resolve the workspace and its accounts by name with list_accounts, and read the client's rules there (a maximum budget increase, protected campaigns).
2. Read each account's rows with get_account_entities, one level at a time: name, ID, status, budget and its kind (daily, lifetime, the campaign's), spend and results over the window.
3. Write the sheet: one row per campaign, ad set or ad, the read-only columns first (platform, account, name, ID, status now, budget now, spend, results, cost per result), then the editable columns New status (Keep, Activate, Pause, as a dropdown) and New daily budget, and a header line that says when the rows were read.
   Leave the budget cell of a row whose budget belongs to its campaign, or has no limit, read-only with a note: the change would be refused.
4. When the person says the edits are ready, read the sheet again, including the rows they selected if they point at a selection, and keep only rows whose New status or New daily budget differs from now.
5. Group the edits into changes (one platform, account, level, action and value each: the same new budget on several rows is one change) and call change_campaigns with changes and no confirm token. Show every change of the preview in one message: each row's before and after, the daily totals and the largest increase, then its warnings.
6. Only after the person confirms that preview, call change_campaigns again with the same changes, the confirm token and the reason in the person's words.
7. Write the outcome back into the sheet: Status now and Budget now take the new values on applied rows, their New columns are cleared, and a refused row keeps what was typed with the refusal next to it.

## Decision rules

- **When** The preview refuses a change before any write (an ad budget, a lifetime budget given as daily, a budget held by the campaign) → **conclude** Nothing was changed: say which row and why, fix the grouping or the value with the person, and preview again.
- **When** The largest increase goes past the client's maximum budget increase rule → **conclude** Say so before the person confirms: the rule will refuse that row at apply time unless they explicitly ask for an exception with a reason.
- **When** Some rows were applied and others refused → **conclude** Report the applied count first, then each refused row with the platform's own words, without attributing a reason the platform did not give.
- **When** The preview token expired (30 minutes) or the sheet changed after the preview → **conclude** Read the sheet again and preview again; never confirm a preview the person did not see.
- **When** More than 100 rows or 12 changes are edited → **conclude** Split them into batches of one workspace each and preview them one after the other.

## Evidence requirements

- Every row carries its platform, account, ID and the time it was read.
- The preview's before values come from the platform at preview time, not from the sheet.

## Human approval boundary

- The sheet changes nothing on the platforms. Only the second change_campaigns call, with the token of a preview the person confirmed, does.

## Failure modes

- Reading the sheet as live data: its cells are what was read at the time written in its header, never a link to the platform. Read the platform again before any preview.
- Applying from the sheet without showing the preview in the conversation: the preview is where the person sees the before and after the platform will apply.
- Mixing workspaces in one batch: every account of a batch must belong to the same client workspace.
- Writing a row back as applied when the result says it was refused.

## Output

- **Sheet**: The rows with their current values, the editable columns, and after applying, each row's outcome.
- **Preview**: One message with every change, before and after, totals, the largest increase and the warnings.
- **Result**: Applied and refused counts, each refused row named, and the reason recorded in the client journal.

## Related

- Skill: [media-plan-in-a-sheet](https://www.getmcpads.com/skills/media-plan-in-a-sheet.md)
- Skill: [naming-audit-in-a-sheet](https://www.getmcpads.com/skills/naming-audit-in-a-sheet.md)
