Adopt a campaign you built in the Google Ads UI
Some campaigns can’t be created by bidsmith. Video campaigns are the big one: the Google Ads API is read-only for that channel, so they have to be built in the Google Ads UI and then handed over. Others you simply built in the UI before you started using bidsmith.
Either way the move is the same — write the .bid block, mark it
adopt-only, and let bidsmith take over the live campaign instead of
making a second one.
The block
resource "google_ads_campaign" "gh_video_fr" { name = "GH_YouTube_FR Instream 11.08.2026" advertising_channel_type = "VIDEO" campaign_budget = google_ads_campaign_budget.video_fr.id
lifecycle { create = false }}create = false says: this campaign already exists — find it, don’t
make it.
What bidsmith matches on
-
The bidsmith label, if the campaign has one. Once a campaign has been adopted it carries a
bidsmith:addresslabel, and from then on the match is by label — you can rename the campaign freely. -
The name, for a campaign bidsmith has never seen. It has to be exactly the live name, spaces and dates included.
So the first adoption is the fragile one, and only the first. Copy the name out of the Google Ads UI rather than retyping it.
When it can’t find a match
Without lifecycle, a name that doesn’t match is silently a new
campaign. For a Video campaign Google then rejects the create — and
since the batch is all-or-nothing, that rejection takes every unrelated
change in the same plan down with it.
With lifecycle { create = false }, the plan stops and tells you what
it was looking for:
plan: error: video_fr.google_ads_campaign.gh_video_fr is declared adopt-only (lifecycle { create = false }) but no live campaign matched it, so there is nothing to adopt. bidsmith looks for its bidsmith:address label first, then by name "GH_YouTube_FR Instream 11.08.2026". Create it in the Google Ads UI to match, or drop the lifecycle block to let bidsmith create itNothing is sent. Fix the name (in the file or in the UI), re-plan, and the campaign adopts.
Confirming the adoption
A successful adoption shows up as an adopt row, not a create:
google_ads_campaign.gh_video_fr ~ adopt (label only)
Plan: 0 to create, 0 to update, 0 to destroy, 1 to adopt, 1 unchanged.~ adopt (label only) means bidsmith found the live campaign and will
write its bidsmith:address label — and nothing else. Every field the
file declares already matches the live campaign, which is why the row
is an adoption rather than an update: no budget, targeting, or status
is written. After that apply, the campaign is bidsmith’s to manage —
drift in any field you declared shows up as a ~ update row on every
plan, spelling out what the value is now and what it would become.
An adoption may also list the criterion categories it starts managing, which is still a label write and still changes nothing about the live campaign:
google_ads_campaign.gh_video_fr ~ adopt (label only; claims frequency caps, languages, locations)What it doesn’t do
create = false only governs creation. It does not stop updates or
removals — an adopted Video campaign that drifts still reports the
drift, and the API still refuses to apply it:
plan: error: video_fr.google_ads_campaign.gh_video_fr has drift on status. Nothing in the batch can be sent while it is there, because the Google Ads API cannot create or update VIDEO campaignsMake that change in the Google Ads UI and let bidsmith read it back.
Where you can use it
lifecycle works on any resource except keywords and targeting
criteria (google_ads_ad_group_criterion,
google_ads_campaign_criterion, google_ads_shared_criterion) —
Google creates those freely, so there is no adopt-only workflow to
declare and bidsmith rejects the block rather than ignoring it.
See also
- The
.bidfile — wherelifecyclefits among the other block types. bidsmith plan— the other reasons a plan refuses to send a batch.- Rename a resource without recreating it — the label-based identity that takes over after adoption.