Skip to main content
Each campaign in Adjar lives in a TOML file under your google/campaigns/ directory (or wherever your account root points via imports). A single file can contain multiple [[campaigns]] entries. Adjar reads these files to understand your current campaign setup and writes changes back in the same format — making your entire campaign structure readable and editable by both humans and AI agents.

Full Example

[[campaigns]]
name = "DB Access Control | SEARCH | 2026-Q2"
status = "ENABLED"
channel_type = "SEARCH"
bid_strategy = "TARGET_SPEND"
max_cpc_ceiling_usd = 10
daily_budget_usd = 200
sitelinks = [ "sl-pricing", "sl-data-masking" ]

[campaigns.targeting]
include_geos = [ "US" ]
include_languages = [ "en" ]
include_devices = [ "DESKTOP" ]

[[campaigns.negative_keywords]]
text = "cybersecurity"
match_type = "BROAD"

[[campaigns.ad_groups]]
name = "JIT DB Access"
status = "ENABLED"

[[campaigns]] Fields

name
string
required
The display name of the campaign as it appears in Google Ads. Names must be unique within the account.A clear naming convention helps AI agents identify campaigns without ambiguity. A common pattern is:
<Topic> | <Channel> | <Period>
name = "DB Access Control | SEARCH | 2026-Q2"
status
string
required
Controls whether the campaign is actively serving ads.
ValueBehaviour
"ENABLED"Campaign is live and eligible to serve
"PAUSED"Campaign is suspended but retains all settings
status = "ENABLED"
ENABLED and PAUSED are the only values you set in config. To remove a campaign, delete its block from TOML — the next apply archives the live campaign. (Internally Adjar writes Google’s REMOVED state during that archive; it is never something you author.)
channel_type
string
required
The Google Ads channel this campaign runs on.
ValueDescription
"SEARCH"Text ads on Google Search results pages
channel_type = "SEARCH"
Additional channel types (e.g. DISPLAY, PERFORMANCE_MAX) will be documented as Adjar adds support for them.
bid_strategy
string
required
The automated bidding strategy Google uses to set bids for this campaign.
ValueDescription
"MANUAL_CPC"You set bids manually (per ad group / keyword); the simplest baseline
"TARGET_SPEND"Maximises clicks within the daily budget (Google’s “Maximize Clicks”)
"MAXIMIZE_CONVERSIONS"Maximises conversions within the budget
"MAXIMIZE_CONVERSION_VALUE"Maximises total conversion value within the budget
"TARGET_CPA"Sets bids to achieve a target cost per acquisition
"TARGET_ROAS"Sets bids to achieve a target return on ad spend
bid_strategy = "TARGET_SPEND"
Only the strategy kind is modeled here. TARGET_CPA / TARGET_ROAS targets, and the conversion tracking the conversion-driven strategies require, are configured in the Google Ads UI — switching to one in TOML seeds an empty target that Google may reject until you set it (apply’s server-side validation will surface this).
max_cpc_ceiling_usd
number
An optional maximum cost-per-click cap in US dollars applied on top of the automated bid strategy. Google will not bid above this amount for any single click.Only valid when bid_strategy is "TARGET_SPEND".
max_cpc_ceiling_usd = 10
daily_budget_usd
number
required
The average daily spend limit for this campaign in US dollars. Google may spend up to twice this amount on a given day, but will not exceed the monthly equivalent (daily × 30.4) over a calendar month.
daily_budget_usd = 200
budget_delivery
string
default:"STANDARD"
How the daily budget is paced.
ValueBehaviour
"STANDARD"Spends the budget evenly throughout the day (recommended)
"ACCELERATED"Front-loads spend; deprecated by Google for most campaign types and accepted mainly for round-trip on import
budget_delivery = "STANDARD"
start_date
string
The date the campaign begins serving, YYYY-MM-DD. Omit to let Google use the campaign’s existing/created start date.
start_date = "2026-04-01"
end_date
string
The date the campaign stops serving, YYYY-MM-DD. Omit for an open-ended campaign — Adjar leaves the end date unset rather than writing a phantom value.
end_date = "2026-06-30"
A list of sitelink asset IDs to attach at the campaign level. These IDs must be defined in your assets.toml.Attachment resolves at the most specific level — Google never merges. Omitting the field (or setting it empty) inherits the account-level sitelinks; a non-empty list replaces the account set for this campaign. To keep an account-wide sitelink showing on a campaign that adds its own, re-list its ID here.
sitelinks = [ "sl-pricing", "sl-data-masking" ]
callouts
array of strings
Campaign-level callout asset IDs, with the same inherit-or-override semantics as sitelinks.
callouts = [ "co-soc2", "co-free-trial" ]
structured_snippets
array of strings
Campaign-level structured-snippet asset IDs, with the same inherit-or-override semantics as sitelinks.
structured_snippets = [ "ss-product-types" ]

[campaigns.network]

Controls which networks the campaign serves on — Google’s network_settings. All fields default to a Google-Search-only campaign, so omitting the block keeps the campaign off Search partners and the Display Network. This is deliberate: Display spend inside a Search campaign produces no search terms and is easy to miss. The block is always compared against the live campaign, so a Display opt-in flipped on in the UI shows up as drift on the next plan.
Serve on the main Google Search results pages. search_partners requires this to be true.
network.search_partners
boolean
default:"false"
Also serve on Google’s Search-partner sites.
network.display
boolean
default:"false"
Also serve on the Display (“Content”) Network.
[campaigns.network]
google_search = true
search_partners = false
display = false

[campaigns.targeting]

The [campaigns.targeting] table controls who sees ads from this campaign. All fields are optional — omitting a field leaves that dimension unrestricted.
targeting.include_geos
array of strings
List of country codes (ISO 3166-1 alpha-2) to target. Ads will only be eligible to show to users in these locations.Adjar maps each code to Google’s numeric geo-target constant from a built-in whitelist. Currently supported: US, CA, GB, DE, FR, NL, AU, JP, IN, SG. An unrecognised code is rejected — extend the map in the CLI to add a new market.
[campaigns.targeting]
include_geos = [ "US", "CA", "GB" ]
targeting.include_languages
array of strings
List of language codes to target. Ads will only show on Google properties using one of these languages.As with geos, codes map to Google’s numeric language constants from a built-in whitelist. Currently supported: en, de, fr, es, ja, zh. An unrecognised code is rejected.
[campaigns.targeting]
include_languages = [ "en" ]
targeting.include_devices
array of strings
List of device types to target. Ads will only be eligible to serve on the specified devices.
ValueDevice
"DESKTOP"Desktop and laptop computers
"MOBILE"Smartphones
"TABLET"Tablet devices
[campaigns.targeting]
include_devices = [ "DESKTOP", "MOBILE" ]

[[campaigns.negative_keywords]]

Campaign-level negative keywords prevent ads in this campaign from showing on searches that match. They apply to every ad group within the campaign.
negative_keywords.text
string
required
The keyword text to exclude. Do not include match type syntax characters (e.g. quotes or brackets) — use the match_type field instead.
[[campaigns.negative_keywords]]
text = "cybersecurity"
negative_keywords.match_type
string
required
How broadly the negative keyword blocks traffic.
ValueBlocks
"BROAD"Any search containing all words in any order
"PHRASE"Searches containing the exact phrase
"EXACT"Searches that match the keyword exactly
[[campaigns.negative_keywords]]
text = "cybersecurity"
match_type = "BROAD"
See the Keywords reference for a full explanation of match type behaviour, including ad-group-level negatives.

[[campaigns.ad_groups]]

Ad groups sit inside a campaign and contain keywords and ads. Each [[campaigns.ad_groups]] entry must appear after the [[campaigns]] entry it belongs to.
ad_groups.name
string
required
The display name of the ad group as it appears in Google Ads. Names must be unique within the parent campaign.A clear name reflects the keyword theme the ad group targets, making it easy for both humans and AI agents to identify which ad group to edit.
[[campaigns.ad_groups]]
name = "JIT DB Access"
ad_groups.status
string
required
Controls whether the ad group is eligible to serve ads.
ValueBehaviour
"ENABLED"Ad group is active and its keywords can trigger ads
"PAUSED"Ad group is suspended but retains all settings
[[campaigns.ad_groups]]
name = "JIT DB Access"
status = "ENABLED"
As with campaigns, ENABLED and PAUSED are the only values you set; remove the ad-group block to archive it.
ad_groups.cpc_bid_usd
number
The ad group’s default maximum cost-per-click bid in US dollars. Used when the campaign’s bid_strategy is "MANUAL_CPC"; automated strategies set bids at the campaign level and ignore this.
[[campaigns.ad_groups]]
name = "JIT DB Access"
cpc_bid_usd = 2.50
An ad group holds its keywords and ads as nested arrays — [[campaigns.ad_groups.keywords]] and [[campaigns.ad_groups.ads]]. See Keywords and Creatives for those fields.
  • Account Root — how campaigns are imported via google.toml
  • Keywords — keyword entries, match types, and negatives at the ad group level
  • Creatives — ads, headlines, and descriptions nested inside ad groups
  • Assets — the sitelinks, callouts, and structured snippets that campaign attachments reference
  • Conversions — the conversion actions that conversion-based bid_strategy values feed