Skip to content

google_ads_audience

An audience is one named description of who you want to reach, with every axis in the same place: in-market and affinity segments, life events, detailed demographics, a custom audience you built yourself, plus age, gender, parental status, and household income.

Elsewhere in Google Ads each of those is a separate criterion hung off a campaign or an ad group. An audience gathers them into a single reusable resource — and for Demand Gen campaigns it is not optional. Those ad groups run in grouped-audience mode, where a segment attached directly is rejected:

Audience segment attachment is not allowed when use audience grouped bit is set to true.

Example

resource "google_ads_audience" "home_battery_shoppers" {
name = "Home battery shoppers"
description = "In-market for energy storage, homeowners with budget"
segment { user_interest = "customers/1234567890/userInterests/80277" }
segment { life_event = "customers/1234567890/lifeEvents/80111" }
segment { custom_audience = google_ads_custom_audience.solar_researchers.id }
age_ranges = ["AGE_RANGE_35_44", "AGE_RANGE_45_54", "AGE_RANGE_55_64"]
income_ranges = ["INCOME_RANGE_80_90", "INCOME_RANGE_90_UP"]
excluded_user_lists = ["customers/1234567890/userLists/778899"]
}

Then point an ad group at it:

resource "google_ads_ad_group" "home_battery" {
name = "Home battery"
campaign = google_ads_campaign.demand_gen.id
audience_setting {
use_audience_grouped = true
}
}
resource "google_ads_ad_group_criterion" "home_battery_audience" {
ad_group = google_ads_ad_group.home_battery.id
audience {
audience = google_ads_audience.home_battery_shoppers.id
}
}

How the axes combine

The axes intersect, and the values within one axis are alternatives. The example above reaches someone who is

  • in at least one of the three segments, and
  • aged 35–64, and
  • in the top 20% of household income,

and who is not on the excluded user list. Leave an axis out entirely and it does not narrow anything.

Schema

Required

  • name ( String )

Optional

  • description ( String )
  • age_ranges ( List of String )
  • genders ( List of String )
  • parental_statuses ( List of String )
  • income_ranges ( List of String )
  • excluded_user_lists ( List of String )

Nested blocks documented below: segment.

Demographics use the enum, not years

Google’s API states an audience’s age dimension in years and every other age field as an enum. .bid files use the enum in both places, so AGE_RANGE_35_44 means the same thing wherever you write it.

Google also merges bands that sit next to each other into one stretch of years — the three bands above are stored as “35 to 64”. bidsmith reads that back as the bands it covers, so listing adjacent bands is not drift and plan stays clean after apply.

AGE_RANGE_UNDETERMINED — and UNDETERMINED on genders / parental_statuses, INCOME_RANGE_UNDETERMINED on income_ranges — means “include people Google could not classify”. That is a large share of viewers on most accounts, so leaving it out of a list is a real narrowing, not a rounding error.

excluded_user_lists

Google only lets an audience exclude user lists — there is no way to exclude an interest or a demographic here. Each entry is a user-list resource name; bidsmith has no resource that builds user lists, so these are always names of lists that already exist.

Nested blocks

segment

One segment. Repeat the block to list many — the axis is the union of them. Set exactly one attribute per block:

  • user_interest — an affinity or in-market segment (customers/{customer_id}/userInterests/…).
  • user_list — a remarketing or customer-match list you already have.
  • life_event — people around a moment like moving or graduating (customers/{customer_id}/lifeEvents/…).
  • detailed_demographic — a long-term trait like homeownership or education (customers/{customer_id}/detailedDemographics/…).
  • custom_audience — a google_ads_custom_audience you built from search terms, sites, or apps. Takes a reference or a resource name.

Optional

  • user_interest ( String )
  • user_list ( String )
  • life_event ( String )
  • detailed_demographic ( String )
  • custom_audience ( reference_or_resource_name )

Matching an audience that already exists

bidsmith matches a declared audience to a live one by name, the same way custom audiences and shared sets work. Declaring one whose name already exists in the account adopts it rather than creating a duplicate — which is how you bring a UI-built audience under management: run bidsmith refresh, keep the block it writes, and edit from there.

If you’d rather leave an audience unmanaged, don’t declare it — point the criterion at its resource name instead:

audience {
audience = "customers/1234567890/audiences/9876543210"
}

How it applies

Unlike a custom audience, an audience goes in the same atomic request as everything else. A new audience and the ad-group criterion attaching it commit together or not at all, so there is no half-applied state to clean up and no deferred row in plan.

Google has no remove operation for an audience, so dropping the block from your files leaves the audience alone rather than destroying it. Archive it in the Google Ads website if you want it gone.

See also