← BlogGuides · 8 min

What coding agents get wrong about the Google Ads API (and the review that catches it)

Seven Google Ads API mistakes I've watched coding agents make while building Lyra PPC, with Google's docs for each, and a skill file that stops them early.

On this page

Coding agents get the Google Ads API wrong in the same seven ways, over and over: a version Google has switched off, a spend field that doesn’t exist, a missing manager-account header, “yesterday” in the wrong time zone, days written once and never corrected, retries that hammer the API, and sample data where a real call should be. None of them is hard. They’re just easy to miss when you’re thinking about the happy path.

I know the list because I watched Claude Code make these mistakes while I built Lyra PPC, a tool that runs on the Google Ads API, and watched Codex catch them when it reviewed Claude’s plans. Below is each mistake with Google’s own documentation, why an agent falls into it, and at the end a skill file you can drop into your repository so the agent reads the rules before it plans.

Why agents keep getting this API wrong

On Lyra PPC the trouble came in three shapes. Wrong versions and fields: deprecated API versions, fields that don’t exist, old client library releases. Fake data: a function that returned sample numbers where the plan said “call the API”. And shortcuts I hadn’t agreed to: a step of the plan quietly simplified or skipped.

The first comes from how fast this API moves. Google’s version table shows a new major version roughly every quarter, minor releases in between, and each version switched off about a year after it ships. An agent learned from examples written against versions that may no longer answer.

The other two come from the happy path. Most examples use one account, one currency and a query that succeeds. Real agency work has a manager account, clients in different time zones and currencies, quotas, and data that changes after you’ve read it. An agent writing the plan in one go doesn’t see what isn’t in the example.

The seven mistakes, with Google’s docs

1. Pinning a version Google has already switched off

Google’s deprecation and sunset page lists every live version with its release and sunset date. Its own wording: deprecated versions still work, while “sunset versions are no longer functional and require an immediate upgrade”. A version missing from the table is gone.

An agent copying from an old example will happily pin one of those. The fix is boring: read the table when you plan, target the current version, use a client library release that supports it, and write the sunset date somewhere a human will see it, like the README.

2. Reading spend from a field that doesn’t exist

There is no metrics.cost. Spend is metrics.cost_micros, and amounts in micros are in the account’s own currency, where “one million micros is equivalent to one currency unit” (campaign_budget fields).

Forget to divide and a €40 day shows as €40,000,000. Divide, but forget that each client account has its own currency, and a total adds euros to dollars. Read customer.currency_code next to the cost and total per currency.

3. Forgetting the manager account

An agency reaches its clients’ accounts through a manager account. Say MB Adv manages the client accounts: every request for a client then needs the login-customer-id header. Google’s call structure page says it plainly: if your access goes through a manager account, “this header is required and must be set to the customer ID of the manager account”, without hyphens.

Plans rarely mention it, because the example they’re built from uses a single account. A call that works in testing on your own account can then fail on every client’s.

4. Treating “yesterday” as UTC

From Google’s date ranges page: “All date ranges and time periods are evaluated relative to the serving account’s time zone (customer.time_zone), rather than UTC or the API client’s local time zone.”

So YESTERDAY ends at a different hour for a client in Milan and one in New York. A sync that runs at one fixed time for every account will sometimes read a day that isn’t over yet. Schedule per time zone, or re-read recent days (see the next one).

5. Writing each day once, and never again

Google’s data freshness article says reporting metrics “may occasionally be updated one or more days after an event occurs”, for reasons like invalid traffic removed after the fact and late-arriving conversions.

A sync that inserts each day once drifts from what the Google Ads interface shows. Two runs that overlap make it worse: the same day twice. The fix has two parts. Write with an upsert keyed on account and date, so a day written twice stays one row. And re-read a recent window of days on every run. How far back depends on your conversion windows; in the scene below, the plan re-reads three days, as an example, not a rule.

6. Retrying in a way that makes the limit worse

The API limits requests per second per customer ID and developer token, and requests over the limit fail with RESOURCE_TEMPORARILY_EXHAUSTED (rate limits). Google’s error types page is specific about what to do with retryable errors: “use an exponential backoff policy with randomized jitter”, up to a maximum number of retries.

What agents write instead is a tight loop, or a fixed sleep, or no retry at all. Add to that an hourly job that can start while the previous one is still running, and you get two runs fighting for the same quota. One run at a time, backoff with jitter, a maximum, then a visible failure.

7. Sample data where the real call should be

This one isn’t in any documentation, and it’s the one I fought most on Lyra PPC. When the real call was hard (credentials not set up yet, a query that failed), the agent filled the gap with made-up numbers that looked real.

Sample data in a reporting tool is worse than an error. Nobody notices it. The rule I use now: no sample, mock or placeholder data outside tests. If the real call can’t be made, stop and say so, and the dashboard says when it last synced.

Why a second reader catches them

What fixed this for me wasn’t switching agents. It was having a second agent read the plan before any code existed: Claude Code writes the plan, Codex reads it read-only and says what’s missing or wasn’t foreseen, Claude revises, and only then does the build start. Here’s the kind of plan review that produces, on a sync job like the ones above:

A reconstruction of the kind of gaps a second review finds in a plan, not a log from a real project. The Google Ads API facts in the findings were checked against Google's documentation on October 4, 2026.

In words: the card asks for yesterday’s Google Ads spend for each MB Adv client account. Claude’s first plan pins a retired API version, reads a field that doesn’t exist, keeps the token in the repo, inserts rows a second run can duplicate, and falls back to sample data. Codex critiques the plan in two rounds, adding five points under the steps they concern; Claude revises; you press Use this plan, and the build starts.

Updated for Plyloft 1.168.1 on October 23, 2026: the scene shows Plan with two AIs, the way the app plans a card since 1.165.

A finding on a plan costs a sentence. The same finding on finished code costs a rebuild, and sometimes a schema change. And the shortcuts, the step quietly skipped or simplified, are much easier to see in a six-line plan than in a diff of four hundred lines.

You can do this by hand: two terminals, copy the plan across, ask “find what’s missing or wasn’t foreseen, change nothing”, and copy the findings back. That’s how I started. Now Plyloft, the app I build, does the copying: each job is a card, one agent builds, the other reviews the plan and then the diff, read-only, round after round.

A skill that stops them before the build

A review catches mistakes. A skill stops most of them from being written. Skills are short written instructions the agent loads before it starts: Claude Code reads them from .claude/skills/<name>/SKILL.md (skills), Codex from .agents/skills/<name>/SKILL.md (build skills). Both use the same file format.

This is the shape of the one I’d put in any repository that talks to the Google Ads API. It’s written for the author and the reviewer alike: each rule broken is a finding.

---
name: google-ads-api-rules
description: Rules for planning, writing or reviewing any code that calls the Google Ads API. Use before planning a Google Ads API change, while building it, and when reviewing its plan or diff.
---
# Google Ads API rules
Each rule below is a finding when a plan or a diff breaks it.
## Versions and fields
- Before planning, open https://developers.google.com/google-ads/api/docs/sunset-dates.
Target the current version. Never use a version that is not in that table.
- Use a client library release that supports that version. Write the version and its
sunset date in the README.
- Check every field name against the field reference for that version. There is no
metrics.cost: spend is metrics.cost_micros.
## Money
- Micros are millionths of the account's currency: divide by 1,000,000.
- Read customer.currency_code with every amount. Never add amounts in different currencies.
## Accounts and credentials
- When access goes through a manager account, every request sends login-customer-id set to
the manager's customer ID, digits only.
- Refresh tokens and developer tokens never go in the repository.
## Dates
- Date ranges, YESTERDAY included, are in each account's time zone (customer.time_zone),
not UTC and not the server's time zone.
## Writing data
- Metrics change after the fact. Write with an upsert keyed on account and date, and
re-read a recent window of days on every run.
- One sync run at a time.
## Errors
- RESOURCE_TEMPORARILY_EXHAUSTED and other retryable errors: retry with exponential backoff
and random jitter, up to a maximum number of retries. Then fail visibly.
## Never
- No sample, mock or placeholder data outside tests. If the real call can't be made,
stop and say so.
- Don't skip or simplify a step of the agreed plan. If a step can't be done as written,
stop and say why.

Two notes from using rules like these. Keep the file short: a long skill gets skimmed by agents as much as by people. And when an agent makes a mistake that isn’t on the list, the fix goes into the file, so it doesn’t come back next week. That habit changed my results more than any model release.

What this list doesn’t cover

These are the mistakes I saw while reading data: reporting, spend, a dashboard. I haven’t covered changes that write to accounts (mutates, partial failures, validate-only requests), policy errors, or the developer token’s access levels. They have their own traps, and I’d rather not list ones I haven’t hit.

The API facts here are as of October 4, 2026. The rules are written to stay true when versions change; the links go to Google’s pages, which are the place to check.

For how the plan-review loop compares across the two agents, and where each one is better, see Codex vs Claude Code: what 18 months of AI coding agents taught me.

Try it on your own repo.

Free for one card at a time.

Get Pro

Seats, you included (2–50)
3
VAT included. Businesses in the EU can add a VAT number on the payment page.Founding price, kept for as long as your subscription runs.

Checking your sign-in…