google_ads_ad_group_criterion
An ad-group criterion is targeting scoped to one ad group: a keyword (positive or negative) on a search campaign, or — on a video campaign — the audience, channels, and demographics that decide who sees the ad.
Each resource targets exactly one thing. Keywords are the exception: one resource can carry a list of them, because they all say the same kind of thing.
Keywords
A positive phrase-match keyword:
resource "google_ads_ad_group_criterion" "kw_summer_deals" { ad_group = google_ads_ad_group.summer_default.id status = "ENABLED"
keyword { text = "summer deals" match_type = "PHRASE" }}A positive exact-match keyword with a custom bid:
resource "google_ads_ad_group_criterion" "kw_summer_sale" { ad_group = google_ads_ad_group.summer_default.id status = "ENABLED" cpc_bid_micros = 3500000
keyword { text = "summer sale" match_type = "EXACT" }}A bulk list of negative keywords:
resource "google_ads_ad_group_criterion" "summer_negatives" { ad_group = google_ads_ad_group.summer_default.id status = "ENABLED"
negative_keyword { text = "free" match_type = "BROAD" }
negative_keyword { text = "diy" match_type = "BROAD" }}Bidsmith accepts two ways to mark a keyword as negative: either set the
negative = true attribute and use a keyword block, or use a
negative_keyword block (which sets negative for you). The
negative_keyword form is more readable and is the default in
bidsmith’s own examples.
Compact form
When a list of keywords all share the same settings, a keywords
block carries the texts as one list instead of a block per keyword:
resource "google_ads_ad_group_criterion" "summer_phrases" { ad_group = google_ads_ad_group.summer_default.id status = "ENABLED"
keywords { match_type = "PHRASE" texts = ["summer deals", "summer sale", "end of summer sale"] }}Set match_types (plural) instead of match_type to fan one list out
across several match types. The block below is the same as writing the
three texts twice — once as EXACT, once as PHRASE:
resource "google_ads_ad_group_criterion" "summer" { ad_group = google_ads_ad_group.summer_default.id status = "ENABLED"
keywords { match_types = ["EXACT", "PHRASE"] texts = ["summer deals", "summer sale", "end of summer sale"] }}negative_keywords is the negative counterpart — same shape, marks the
criteria negative for you:
resource "google_ads_ad_group_criterion" "summer_negatives" { ad_group = google_ads_ad_group.summer_default.id status = "ENABLED"
negative_keywords { match_type = "BROAD" texts = ["free", "diy", "used"] }}Each (text, match type) pair still becomes its own keyword on Google
Ads, so plan and apply see no difference between the compact and
the per-keyword forms — they are purely an authoring convenience. Both
forms can coexist in the same resource.
A cohort per ad group
On a video campaign, who sees the ad is usually an ad-group decision. Two cohorts of the same creative are two ad groups in one campaign — one budget, one name, one set of results to compare:
resource "google_ads_ad_group" "instream_35_up" { name = "In-stream — 35+" campaign = google_ads_campaign.preroll.id type = "VIDEO_TRUE_VIEW_IN_STREAM" cpv_bid_micros = 35000}
resource "google_ads_ad_group_criterion" "cohort_35_44" { ad_group = google_ads_ad_group.instream_35_up.id
age_range { type = "AGE_RANGE_35_44" }}
resource "google_ads_ad_group_criterion" "cohort_privacy_intent" { ad_group = google_ads_ad_group.instream_35_up.id
audience { custom_audience = google_ads_custom_audience.privacy_searchers.id }}Any of these can be an exclusion instead — set negative = true and
the ad group stops showing to that slice:
resource "google_ads_ad_group_criterion" "exclude_kids_channel" { ad_group = google_ads_ad_group.instream_35_up.id negative = true
youtube_channel { channel_id = "UCXuqSBlHAE6Xw-yeJA0Tunw" }}bid_modifier nudges the bid for a slice rather than including or
excluding it — 1.2 bids 20% more, 0.7 bids 30% less:
resource "google_ads_ad_group_criterion" "bid_up_35_44" { ad_group = google_ads_ad_group.instream_35_up.id bid_modifier = 1.2
age_range { type = "AGE_RANGE_35_44" }}A market per ad group
Ad-group location and language intersect with the campaign’s
own targeting — a viewer has to match both. That makes one localized
ad group per market possible inside a single campaign, instead of one
campaign per market:
resource "google_ads_ad_group_criterion" "singapore" { ad_group = google_ads_ad_group.instream_sg.id
location { geo_target_constant = "geoTargetConstants/2702" }}Because the two levels intersect, an ad-group location that the
campaign does not target reaches nobody. Keep the campaign’s
locations list
as the wide net and use ad-group locations to split it.
Schema
Required
-
ad_group( Reference togoogle_ads_ad_group)
Optional
-
status( String ) One of:ENABLED,PAUSED,REMOVED. Default"ENABLED"; omit to manage at the default. -
negative( Boolean ) Defaultfalse; omit to manage at the default. -
cpc_bid_micros( Integer ) -
bid_modifier( Number )
Nested blocks documented below: keyword, keywords, negative_keyword, negative_keywords, youtube_channel, youtube_video, topic, user_interest, age_range, gender, audience, placement, parental_status, income_range, location, language.
Nested blocks
keyword
A positive keyword. Repeat the block to add several keywords to one resource.
Required
-
text( String ) -
match_type( String ) One of:EXACT,PHRASE,BROAD.
keywords
The compact form: a list of texts fanned out across a single
match_type or a list of match_types. One block stands in for many
keyword blocks. Set exactly one of match_type or match_types.
Required
-
texts( List of String )
Optional
-
match_type( String ) One of:EXACT,PHRASE,BROAD. -
match_types( List of String )
negative_keyword
A negative keyword for this ad group. Same shape as keyword. Using
this block implicitly marks the criterion as negative.
Required
-
text( String ) -
match_type( String ) One of:EXACT,PHRASE,BROAD.
negative_keywords
The compact form for negatives — same shape as keywords, and marks
every resulting criterion negative for you.
Required
-
texts( List of String )
Optional
-
match_type( String ) One of:EXACT,PHRASE,BROAD. -
match_types( List of String )
audience
A cohort to narrow the ad group to. Set exactly one of the four:
custom_audience (a
google_ads_custom_audience you
declare, or a resource name), user_list (a remarketing list built in
the Google Ads UI), combined_audience, or audience (a
google_ads_audience — segments and
demographics gathered into one reusable definition).
Optional
-
custom_audience( reference_or_resource_name ) -
user_list( String ) -
combined_audience( String ) -
audience( reference_or_resource_name )
user_interest
An affinity or in-market interest category, named by its constant
(customers/{customer_id}/userInterests/<id>).
Required
-
user_interest_category( String )
youtube_channel
A YouTube channel to run on — the id from the channel URL.
Required
-
channel_id( String )
youtube_video
A single YouTube video to run on.
Required
-
video_id( String )
topic
A content topic, named by its constant (topicConstants/<id>).
Required
-
topic_constant( String )
placement
One site, app, or channel URL to run on — a managed placement.
Required
-
url( String )
age_range
An age bracket. Google reports AGE_RANGE_UNDETERMINED for a large
share of viewers, so excluding it cuts far more reach than it looks —
bidsmith warns when you do.
Required
-
type( String ) One of:AGE_RANGE_18_24,AGE_RANGE_25_34,AGE_RANGE_35_44,AGE_RANGE_45_54,AGE_RANGE_55_64,AGE_RANGE_65_UP,AGE_RANGE_UNDETERMINED.
gender
Required
-
type( String ) One of:MALE,FEMALE,UNDETERMINED.
parental_status
Required
-
type( String ) One of:PARENT,NOT_A_PARENT,UNDETERMINED.
income_range
A household income band, top-down: INCOME_RANGE_90_UP is the top 10%,
INCOME_RANGE_0_50 the lower half.
Required
-
type( String ) One of:INCOME_RANGE_0_50,INCOME_RANGE_50_60,INCOME_RANGE_60_70,INCOME_RANGE_70_80,INCOME_RANGE_80_90,INCOME_RANGE_90_UP,INCOME_RANGE_UNDETERMINED.
location
A geo target for this ad group, intersected with the campaign’s own.
Required
-
geo_target_constant( String )
language
A language target for this ad group, intersected with the campaign’s own.
Required
-
language_constant( String )
See also
google_ads_ad_group— required parent.google_ads_campaign_criterion— the same targeting applied to a whole campaign.google_ads_custom_audience— build a search-intent segment to target here.google_ads_audience— segments and demographics in one resource, and the only targeting a Demand Gen ad group accepts.google_ads_shared_set— reusable negative lists across campaigns.