GAQL promises all the data; reality imposes limits: on time, on quota, on privacy, on freshness and on versions. A process that does not know them fails on a Tuesday at 3am with nobody watching. This lesson is the list of limits and the design that survives them.
Google Ads scripts limits
| Limit | Value | Consequence |
|---|---|---|
| Time per run | 30 min (60 for some parallel manager-account runs) | Long jobs get cut off: you have to split them into batches and resume |
| Frequency | One scheduled run per hour per script | There is no "every 10 minutes" |
| Calls to external services (UrlFetch) | A daily quota per user: ~20,000 on Gmail, ~100,000 on Workspace | Scripts that call an AI or a server burn quota; whoever runs them on Workspace has five times as much |
| Spreadsheets | Cell limits and Sheets call limits | Write in blocks, not cell by cell |
| A daily sending quota | Grouped alerts, not one per event | |
| Concurrent runs | Limited per account | Several scripts at the same hour tread on each other |
API limits
- Operations and rows per request: large but finite; queries are paged.
- Daily quotas per developer token (basic vs standard access): a high volume of queries requires standard access.
- Mutations: limits per request and strict validation (budgets in micros as multiples, targets within ranges).
Data that does not exist, or arrives late
- Privacy threshold: low-volume search terms (and AI Max combinations) do not appear; the sum of what you can see is not the total.
- Metric lag: today's metrics are incomplete; conversions arrive late; some metrics (IS, quality) update hours or a day behind. The rule: query up to yesterday and re-query the last few days on every run (incremental re-download with overlap).
- QS history: it does not exist in the API; only the current value.
- Auction insights: limited access.
- PMax: placements with impressions only; search terms by category.
API versions
The Google Ads API ships new versions several times a year and retires old ones after a while; fields and resources get renamed or disappear. For example, v22 will be retired on October 7, 2026, and from that date all requests using it will fail. Google Ads scripts use a version managed by Google (less maintenance), but fields still change. The design answer: queries with the minimum fields, and a compatibility check (preview) after every version notice.
Designing processes that survive
- Batches and resuming: split the work (by account, by campaign, by date range), store a cursor (where it got to) in the sheet or in the script's properties, and resume on the next run. Heavy work once a day per account; light work every hour.
- Frozen date windows: work out the range once at the start of the job and store it; if the job spans several runs, all of them use the same range (otherwise the batches will not reconcile).
- Incremental download with overlap: every day, the last N days (3-7) are downloaded again and replace what was stored: that is how late conversions get in.
- Retries with a wait on transient API errors; and if it fails, it does not touch anything on writes.
- Block writes to sheets; block reads of configuration.
- A consumption meter: count external calls per run and per account, and report them (so you do not hit the quota at the end of the month).
- Diagnostics: a tab with the trace of the last run and errors highlighted; without it, the 3am failure is invisible.
- Large accounts: sampling or pre-aggregation (GAQL lets you sort and limit: the 2,000 highest-spending search terms instead of 50,000).
Specific traps
- Querying
segments.datewith no range → error. - Selecting ten segments "just in case" → millions of rows → time runs out.
- IDs stored as numbers in Sheets → rounded → broken joins.
- Micros added up as if they were euros.
- Forgetting the account's time zone (
customer.time_zone) when working out "yesterday". - A script that calls the AI once per row → UrlFetch quota exhausted by midday: batch them.
💡 Ninja trick: several of these designs are standard in the Suite today precisely because they hit the limit first: the Agent has a daily gate (heavy work once a day per account, pending items first, light KPIs every hour) and a rotating cursor for resuming; the Shield's Smart Mode downloads RAW data incrementally with a frozen window; every script carries a UrlFetch meter per account and a Diagnostics tab with the trace. And the analyses that do not fit into 30 minutes (Site Analyzer across thousands of domains) moved to a server of our own.
What you should remember
- Scripts: 30 min, one per hour, a UrlFetch quota (Workspace ×5), Sheets and email in blocks.
- Data: privacy threshold, lag (query up to yesterday with overlap), no QS history, PMax limits.
- API versions change: minimum fields and a compatibility check.
- Design: batches with a cursor, frozen windows, incremental with overlap, retries, if it fails it does not touch, a meter, diagnostics.