Skip to content

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 to google_ads_ad_group )

Optional

  • status ( String ) One of: ENABLED, PAUSED, REMOVED . Default "ENABLED"; omit to manage at the default.
  • negative ( Boolean ) Default false; 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