Google Ads Change History
Answer "what changed on this client's Google Ads account, and who changed it?" for up to 90 days, as a read-only timeline grouped by day and by user with budget, bid and status changes highlighted and a draft escalation summary for…
At a glance
Google Ads Change History is an AI skill that you can use in Claude Code, Codex, or type.com. It works with Google Ads.
- Works with
- Google Ads
- Updated
See an example
Example output from a sample run. Company names and figures are sample data.
Google Ads change history: Harbor & Vine (123-456-7890), 2026-06-23 to 2026-09-20 (USD)
14 changes with user and old/new values between 2026-08-22 and 2026-09-20 (budget 2, bid 4, status 4, setting 1, other 3). 11 were made by named users and 3 came from Google Ads automation, including an auto-applied recommendation that turned the Display Network on for Brand - Search on a Saturday.
Budget, bid and setting changes
| When | Who | Item | Change |
|---|---|---|---|
| 2026-08-25 10:12 | [email protected] | Budget "Brand - Search Budget" | 50.00 USD → 75.00 USD |
| 2026-08-25 10:15 | [email protected] | Campaign "Brand - Search" | target ROAS 400% → 350% |
| 2026-09-02 09:05 | [email protected] | Keyword "washed linen sheets" | max CPC 1.10 USD → 1.30 USD |
| 2026-09-02 09:05 | [email protected] | Keyword "linen duvet cover" | max CPC 1.20 USD → 1.45 USD |
| 2026-09-10 02:00 | Automated rule | Budget "PMax - All Products Budget" | 120.00 USD → 100.00 USD |
| 2026-09-18 13:05 | [email protected] | Campaign "PMax - All Products" | target ROAS (none) → 500% |
| 2026-09-19 10:00 | Auto-applied recommendation | Campaign "Brand - Search" | Display Network off → on |
By user
| User | Changes | Breakdown | Via |
|---|---|---|---|
| [email protected] | 5 | budget 1, bid 1, status 1, other 2 | Web UI |
| [email protected] | 5 | bid 3, status 2 | API, Google Ads Editor, Web UI |
| Auto-applied recommendation | 2 | setting 1, other 1 | no user email |
| Automated rule | 1 | budget 1 | no user email |
| [email protected] | 1 | status 1 | Web UI |
Next actions
- Check the automated changes (Auto-applied recommendation 2, Automated rule 1) were intended before attributing them to a person.
- Raise the client-side edit: [email protected] paused Non-brand - Bedding on Sat 2026-09-05 at 22:14; [email protected] re-enabled it on 2026-09-07 at 08:30.
- Review weekend activity on 2026-08-29, 2026-09-05 and 2026-09-19.
- For 2026-06-23 to 2026-08-21, 7 resources changed but Google Ads does not record who. The drafted client reply says so and waits for account lead review before sending.
- Portfolio view (14 days) covers every client: 7 changes for Harbor & Vine, 3 for Ledgerline Software, and Copper Kettle Coffee SKIPPED because accounts.google_ads_customer_id is missing.
Inputs: change_event for 2026-08-22 to 2026-09-20 (who, which tool, old → new values) and change_status for 2026-06-23 to 2026-08-21 (which resources changed). Read-only: nothing in any account was changed.
Produced by running bash examples/run.sh on the sample data bundled with this skill.
How to use Google Ads Change History
- type.com: Choose Use Skill to add Google Ads Change History to your type.com workspace.
- Claude Code: Download the skill and extract it into
~/.claude/skills/google-ads-change-history/(or.claude/skills/google-ads-change-history/in a project). Then ask Claude to use Google Ads Change History. - Codex: Download the skill and extract it into
~/.agents/skills/google-ads-change-history/(or.agents/skills/google-ads-change-history/in a repository). Then ask Codex to use Google Ads Change History.
AI agents can read this page as Markdown or fetch the raw SKILL.md.
Frequently asked questions
What is Google Ads Change History?
Google Ads Change History is an AI skill that you can use in Claude Code, Codex, or type.com. It works with Google Ads.
What does Google Ads Change History do?
Answer "what changed on this client's Google Ads account, and who changed it?" for up to 90 days, as a read-only timeline grouped by day and by user with budget, bid and status changes highlighted and a draft escalation summary for…
Can I use Google Ads Change History in Claude Code or Codex?
Yes. Google Ads Change History is a standard Agent Skills folder with a SKILL.md file. Download it and extract it into ~/.claude/skills/ for Claude Code or ~/.agents/skills/ for Codex.
Who created Google Ads Change History?
Kurt Henninger (fourteenwm) created Google Ads Change History, and the type.com team adapted it for the Skills Library. The type.com team reviews every skill before it is published in the Skills Library.
Related guide
Browse the technical files
---
name: google-ads-change-history
description: Answer "what changed on this client's Google Ads account, and who changed it?" for up to 90 days, as a read-only timeline grouped by day and by user with budget, bid, status and campaign-setting changes highlighted and a draft escalation summary for replying to the client.
---
# Google Ads change history
Use this skill when an account lead asks what changed on a client's Google Ads
account, who changed it, or needs to answer a client question such as "why did
our budget go down last week?" or "who paused the bedding campaign?". It also
gives a portfolio view across every client profile, with each row labelled by
client.
**Read-only.** The script only runs GAQL `SELECT` queries. It never changes a
campaign, budget, bid, status or any other setting, and it writes nothing to
disk. Output goes to the terminal.
## Get the skill's files first
This skill ships scripts and sample data alongside this SKILL.md. Before running any command:
1. **Get the files.** Make sure the skill's other files (`scripts/`, `examples/` and anything else listed with this skill) are in your working folder at the same relative paths. Some environments load only SKILL.md; if yours did, fetch each file from this skill's published files and write it to the matching path. In Type, read them with the skill-file tools. Anywhere else, the Type Skills Library API lists every file with its path, content and `sha256`: GET `https://api.type.com/api/public/library/skills` and take the entry with slug `google-ads-change-history`.
2. **Check the copies are exact.** Compare each file's size in bytes, not characters (and its hash, where your tools report one), with the published version before running. A copy written out from the published file is fine once its byte size and hash match; never run a script you summarised or reconstructed from memory.
3. **Run from the skill's folder**, calling interpreters explicitly: `python3 scripts/…` and `bash examples/run.sh`.
4. **Try the sample first.** If the skill ships `examples/run.sh` and `examples/expected_output.txt`, run `bash examples/run.sh`; its output should match the expected file exactly. If it doesn't, stop and report the first differing line rather than running on real data.
## Before you run it
1. **Client profile.** Resolve the client from `clients/<slug>/client.json`
(see [CLIENTS.md](CLIENTS.md)). The skill needs
`accounts.google_ads_customer_id`. If you reach the account through a
manager (MCC) account, also set `accounts.google_ads_login_customer_id`.
If a field is missing, the script names it, explains how to add it and
stops. It does not guess.
2. **Credentials.** Use a standard `google-ads.yaml` or `GOOGLE_ADS_*`
environment variables. See [DATA_CONTRACT.md](DATA_CONTRACT.md). Never paste
credentials into the conversation.
3. **Install** (live mode only): `pip install -r requirements.txt`. This pins
`google-ads==32.0.0`, and the script pins Google Ads API `v25`.
## Run
Run from the directory that contains `clients/`. You can also pass
`--clients-dir`.
```bash
# One client, last 30 days (the default window)
python3 scripts/change_history.py --client harbor-and-vine
# One client, full 90 days: days 1-30 include who changed what; days 31-90 show only which items changed
python3 scripts/change_history.py --client "Harbor & Vine" --days 90
# A specific range (must be inside the last 90 days)
python3 scripts/change_history.py --client harbor-and-vine --start 2026-09-01 --end 2026-09-15
# Portfolio view across every client profile, every row labelled [client-slug]
python3 scripts/change_history.py --all-clients --days 7
# Explicit credentials file
python3 scripts/change_history.py --client harbor-and-vine --google-ads-config ~/secure/google-ads.yaml
# Offline: recorded rows, no API, no credentials (see examples/)
bash examples/run.sh
```
`--fixture <json>` reads recorded `change_event`/`change_status` rows instead
of calling the API. Use it to test the formatting and aggregation or to replay
an export. `--as-of` sets "today" for fixture runs only.
## What the output contains
1. **Header:** client, customer ID, window, and which data source covers which
dates. It is always marked read-only and draft.
2. **Timeline by day** (oldest first, in the account's time zone). Each line
shows time, a tag (`[BUDGET]`, `[BID]`, `[STATUS]`, `[SETTING]`, or `[other]`), who made
the change and which tool they used (Web UI, Editor, API, scripts,
automated rule, or auto-applied recommendation), what changed, and old and
new values. Money values use the account currency. Target ROAS appears as a
percentage, and on/off settings appear as `on` / `off`.
- `BUDGET`: campaign budget changes, or a campaign moved to another budget.
- `BID`: bid strategy, target CPA/ROAS, max CPC/CPM/CPV, and bid
adjustments.
- `STATUS`: status updates such as pause or enable, and removals.
- `SETTING`: material campaign settings — networks (Search partners,
Display Network, YouTube), locations and location targeting options,
languages, ad schedule, start/end dates and campaign type. Bid strategy
changes are tagged `BID`.
3. **By user:** change count per person or automated source, broken down by
category, with the date span and tools used.
4. **Older changes** (only when the window goes past 30 days). This section
comes from `change_status` and counts which resources changed per day and
type. It has **no user and no old/new values**.
5. **Escalation summary** (one per client). It lists every budget, bid and
campaign-setting change (up to 10, then a pointer to the timeline), status outcomes, who made changes, automated sources, changes made
from the client's own email domain (from `website` in client.json), weekend
activity, row-cap warnings, and a neutral **suggested reply**. The reply
only states what the history shows; it does not promise any follow-up, so
add one yourself if the account lead agrees to it.
6. **Portfolio summary** (`--all-clients` only): per client, change counts by
category, then how many distinct people (user emails) and how many distinct
automated sources made them, counted separately.
## How to use the result
- Present the summary to the account lead as a **draft**. Do not send anything
to the client automatically (CLIENTS.md rule 2).
- Before you attribute a change to a person, check automated sources:
auto-applied recommendations, automated rules, and scripts explain many
"nobody did this" questions.
- If a change came from an unknown email address, flag it to the account lead
as an access question. Do not conclude that the account was compromised.
The Google Ads UI shows who has access.
- Never mix clients. A single-client run reads only that client's customer ID.
The portfolio view labels every row.
- This skill does not make fixes. If the lead wants something changed back,
that is a separate write action. It needs explicit approval in the
conversation that names the client and the change (CLIENTS.md rule 3).
## Limits
- **30 days of "who".** Google Ads `change_event` only returns changes from
the last 30 days. That is the only API source that includes user email,
tool, and old/new values. The query must also include a date range and a
`LIMIT` of 10,000 or less. The script pages past the limit by timestamp, up
to 100,000 rows.
- **90 days of "what".** For days 31 to 90, the script uses `change_status`.
It returns one row per resource, dated by that resource's latest change. It
has no user, no tool, and no old/new values. If a resource changed again
later, it drops out of the older part of the window.
- **Nothing older than 90 days** is available through the API. Older changes
(about 2 years) are in the Google Ads UI under Tools > Change history, which
can export CSV.
- **change_event is not the full UI log.** Google says it may omit some rows
shown in the UI's Change History. Not every client type records events. It
can also lag by up to about 3 minutes.
- **Not captured:** who accepted a manager-account link or changed user
access; billing and payment changes; many changes Google makes on its own
(for example automated bidding adjustments inside a Smart Bidding strategy,
and Performance Max asset serving). Some resource types come back as
`UNKNOWN`. Performance data is not included, so this skill does not explain
*why* results moved.
- **Automated changes** from rules, scripts, or auto-applied recommendations
often have no user email. The report labels the tool instead.
- **Time zone:** timestamps are in the account's time zone. The window is
calculated from the local date where the script runs, so edge days can be
off by one across time zones.
- **Currency:** `*_micros` values are divided by 1,000,000 and labelled with
the account currency. Budget amounts are shown as stored and are not
converted to a period.
## Files
| File | Purpose |
|---|---|
| `scripts/change_history.py` | Read-only GAQL queries, normalization, and report |
| `requirements.txt` | Pinned `google-ads` client library (live mode only) |
| `examples/` | Synthetic fixture, sample client profiles, `run.sh`, `expected_output.txt` |
| `CLIENTS.md` | Shared client-profile contract |
| `DATA_CONTRACT.md` | Credentials, API version, fields read, outputs |
| `NOTICE.md`, `LICENSE.txt` | Upstream attribution (MIT) and list of modifications |