Skip to content

bidsmith import

Accounts have history. Sitelinks added in the Google Ads UI three years ago, callouts somebody attached to the account rather than to a campaign, a negative keyword nobody remembers adding — none of it is in your .bid files, so plan can’t see it, and writing it out by hand risks creating a second copy of something that is already running.

import closes that gap. Point it at one live resource and the address you want it to live at, and it writes the matching block into your .bid files. Nothing is changed in Google Ads: the next plan simply recognizes the resource and reports it as unchanged instead of proposing to create it.

Synopsis

Terminal window
bidsmith import <ADDRESS> <RESOURCE> [--path PATH] [--check]
[--refresh-state | --offline] [--var NAME=VALUE] [--verbose]
  • <ADDRESS> — where the block should go: <type>.<name>, or <module>.<type>.<name> to say which file.
  • <RESOURCE> — the Google Ads resource name (customers/1234567890/customerAssets/4001~SITELINK) or just its id.

Flags

FlagDescription
--path PATHThe .bid file or directory to write into. Default ..
--checkPrint the block(s) that would be added and write nothing.
--refresh-stateIgnore the cached account snapshot and refetch.
--offlineRead the account from the cache instead of calling the API. Errors if no fresh cache exists — run bidsmith pull first.
--var NAME=VALUESet a variable value. Repeatable.
--verbosePrint the outgoing API request envelope.

Exit codes

CodeMeaning
0The block was written (or printed, with --check).
1Nothing was written: the resource isn’t there, the address is taken, it’s already managed, or the result wouldn’t validate.
2The address or the resource type isn’t one import accepts.

What you can import

import covers the resource types Google Ads refuses to label:

  • Assets — sitelink, callout, structured snippet, call, YouTube video.
  • Asset linkscustomer_asset, campaign_asset, ad_group_asset (the blocks that attach an asset to the account, a campaign, or an ad group).
  • Criteria — campaign and ad-group criteria: keywords, negatives, audiences, placements.

Campaigns, ad groups, and ads need no import. They carry a bidsmith label, so the first apply after you write them adopts the matching live one — see Adopt a campaign from the UI. And if you’re starting from nothing, bidsmith refresh -d writes the whole account out at once; import is for picking one thing out of an account you already manage.

Examples

Terminal window
bidsmith import account.google_ads_customer_asset.shop_link \
customers/1234567890/customerAssets/4001~SITELINK
resource "google_ads_customer_asset" "shop_link" {
asset = google_ads_sitelink_asset.shop.id
}

The link points at the sitelink your file already declares. If it didn’t, the sitelink would be written alongside it:

resource "google_ads_sitelink_asset" "sitelink_support" {
link_text = "Support"
final_urls = ["https://example.com/help"]
}
resource "google_ads_customer_asset" "support_link" {
asset = google_ads_sitelink_asset.sitelink_support.id
}

A link can’t exist without its asset, so import brings the asset with it and names it the way refresh would. Rename it afterwards with bidsmith mv if you’d rather call it something else.

Look before you write

Terminal window
bidsmith import --check google_ads_callout_asset.free_delivery 4002

Prints the block to stdout and touches nothing. The bare id works because the collection is implied by the type.

Pick the file

Files are modules, so the module segment of the address is the file the block is written into:

Terminal window
bidsmith import account.google_ads_customer_asset.shop_link 4001~SITELINK
bidsmith import campaigns.google_ads_campaign_asset.sale_link 100~4004~SITELINK

When your project is a single .bid file you can leave the module off. With more than one file, import asks you to say which — it won’t guess.

What it refuses

import stops rather than write something misleading:

  • The address is taken. Pick a free name, or move the existing block out of the way with bidsmith mv.
  • plan already manages the resource. It names the address that claims it. Importing it again would be a duplicate declaration.
  • The resource name is from the wrong collection. Passing an assets/... name for a customer_asset is a mistake worth catching before you go looking for a resource that was never missing.
  • A criterion’s parent isn’t declared. A criterion has to reference a campaign or ad group in your files; declare the parent first.

After writing, import re-checks the whole project and refuses to save if the result wouldn’t validate — the same guard refresh --in-place uses.

Duplicates

Assets have no id you can write down in a .bid file — bidsmith matches them by their content, so two live sitelinks with the same text and URL are indistinguishable to it. When that happens, plan says so:

plan: warning: account.google_ads_sitelink_asset.shop: 2 live resources
are identical to it (4001, 4009) — adopted 4001, the rest stay
unmanaged.

Nothing is broken and nothing is duplicated, but one of the two is outside bidsmith’s view. Remove the extra one in the Google Ads UI, or declare it too so both are managed.

See also