bidsmith plan
plan is the dry run. It parses your .bid files, fetches live
state via the Google Ads API, diffs the two, and shows you what
would change — without changing anything. Safe to run any number of
times.
If plan is empty, your .bid files and the live account already
match. If plan has rows, apply is
the next step.
Synopsis
bidsmith plan [PATH] [--refresh-state] [--offline] [--whoami] [--read-live] [--verbose]Arguments
| Argument | Default | Description |
|---|---|---|
PATH | . | File or directory containing .bid files. |
Flags
| Flag | Description |
|---|---|
--refresh-state | Ignore any cached live state and refetch from the API. The fresh fetch is then written back to the cache. Use when you suspect the cache is out of date. |
--offline | Diff against the cached live state without contacting Google Ads at all — no OAuth, no SearchStream, no validateOnly mutate. Errors if no fresh cache exists. See Cut Google Ads API quota usage. |
--whoami | Exchange the refresh token for an access token and print the result. Doesn’t touch Google Ads. Useful for confirming credentials. |
--read-live | Print a summary of the live account state (resource counts per type). Doesn’t require .bid files. Useful for debugging. |
--verbose | Print the outgoing API request envelope and the raw response. Useful when something looks wrong. |
Environment variables
| Variable | Required? | Notes |
|---|---|---|
GOOGLE_ADS_DEVELOPER_TOKEN | yes | |
GOOGLE_ADS_CLIENT_ID | yes | |
GOOGLE_ADS_CLIENT_SECRET | yes | |
GOOGLE_ADS_REFRESH_TOKEN | yes | |
GOOGLE_ADS_CUSTOMER_ID | yes | The account to plan against. |
GOOGLE_ADS_LOGIN_CUSTOMER_ID | no | Set if you’re managing a sub-account via an MCC. |
BIDSMITH_API_VERSION | no | Defaults to v22. Bump if you hit a “retired version” error. |
See Connect to Google Ads for how to obtain these.
Exit codes
| Code | Meaning |
|---|---|
0 | Plan completed (whether or not changes are pending). |
1 | Local validation failed, authentication failed, Google rejected the validate-only request, or any other error. |
Examples
Standard plan
bidsmith plan .Validates .bid files, fetches live state, diffs, prints the plan.
Confirm credentials work
bidsmith plan --whoamiPrints a short summary like:
Refresh token exchanged successfully.Access token expires in 3599 seconds.Customer ID: 1234567890Useful as the first command to run after setting env vars.
See what’s in the live account
bidsmith plan --read-liveSkips the diff and just prints a per-type count. Helpful when you’re
new to an account and want to know what’s already there before
writing .bid files.
Debug a confusing diff
bidsmith plan . --verbosePrints the request body bidsmith sent and the response Google returned. Useful when bidsmith’s interpretation of the diff doesn’t match yours.
How the diff is computed
- Resources are matched between
.bidand live by name. - For each matched pair, bidsmith compares scalar attributes
field-by-field; any difference becomes a
~ updaterow with the before/after values. - Resources in
.bidwith no live match become+ createrows. - Resources in the live account with no
.bidmatch are not shown today — they’re “stuff bidsmith doesn’t manage.” Label-based matching (and- destroyrows) is on the roadmap.
After producing the diff, bidsmith sends the create/update operations
to Google’s googleAds:mutate endpoint with validateOnly=true.
Google checks them without committing. Any rejection
(“headline too long,” “bid below minimum”) shows up inline in the
plan output.
See also
bidsmith apply— what to run when the plan is what you want.bidsmith validate— local checks without the API.- Plan and apply — the conceptual model.
- Drift — interpreting
~ updaterows.