Segmentation is available in the Google Ads UI as a separate menu. You can implement segmentation in the Google Ads API by adding the proper field to a query. For example, suppose you add segments.device
to a query. That results in a report with a row for each combination of device and the specified resource in the FROM
clause, and the statistical values (impressions, clicks, conversions, etc.) split between them.
In the Google Ads UI, only one segment at a time can be used, but with the API you can specify multiple segments in the same query.
SELECT
campaign.name,
campaign.status,
segments.device,
metrics.impressions
FROM campaign
The results from sending this query to GoogleAdsService.SearchStream
will resemble this JSON string:
{
"results":[
{
"campaign":{
"resourceName":"customers/1234567890/campaigns/111111111",
"name":"Test campaign",
"status":"ENABLED"
},
"metrics":{
"impressions":"10922"
},
"segments":{
"device":"MOBILE"
}
},
{
"campaign":{
"resourceName":"customers/1234567890/campaigns/111111111",
"name":"Test campaign",
"status":"ENABLED"
},
"metrics":{
"impressions":"28297"
},
"segments":{
"device":"DESKTOP"
}
},
...
]
}
In this sample result, attributes for the first and second objects, including the resource name, are the same. The impressions are segmented by device, and thus two or more objects can be returned for the same campaign.
Implicit segmentation
Every report is initially segmented by the resource specified in the FROM
clause. The resource_name
field of the resource in the FROM
clause is returned and metrics are segmented by it, even when the resource_name field is not explicitly included in the query. For example, when you specify ad_group
as the resource in the FROM
clause, then ad_group.resource_name
will automatically be returned and metrics will implicitly segment against it at the ad_group level.
So for this query,
SELECT metrics.impressions
FROM ad_group
you would get a JSON string like this:
{
"results":[
{
"adGroup":{
"resourceName":"customers/1234567890/adGroups/2222222222"
},
"metrics":{
"impressions":"237"
}
},
{
"adGroup":{
"resourceName":"customers/1234567890/adGroups/33333333333"
},
"metrics":{
"impressions":"15"
}
},
{
"adGroup":{
"resourceName":"customers/1234567890/adGroups/44444444444"
},
"metrics":{
"impressions":"0"
}
}
]
}
The resource_name
field of adGroup
is always returned because ad_group
is specified as a resource in the FROM
clause.
Selectable segment fields
Not all segment fields are selectable for a given resource in the FROM
clause. As an example, suppose you continue to query from the ad_group
resource. For a segment field to be selectable from the ad_group
resource, that field needs to exist in the Segments
list for ad_group. The Segments
list is the yellow portion of the available fields table on the ad_group
resource's metadata page.
Segment resources
When selecting from some resources, you may have the option to implicitly join on related resources by selecting their fields alongside the fields of the resource in the FROM
clause. These related resources can be found in the Attributed Resources
list on the resource in the FROM
clause's metadata page. In the case of the ad_group
resource, you'll see that you can also select fields from the campaign
resource. The resource_name
field of any Attributed Resources
with at least one field in the SELECT
clause will automatically be returned, even when the resource_name field is not explicitly included in the query.
Similar to selecting Attributed Resource
fields, you can also select Segmenting Resource
fields. If a given resource has a Segmenting Resources
list on its metadata page, then if you select fields from one of those listed resources, that will cause the query to be further segmented by the returned resource_name
of that Segmenting Resource
. As an example, you'll find that the campaign
resource is listed as a Segmenting Resource
for the campaign_budget
resource. Selecting any campaign field, like campaign.name
, from the campaign_budget
resource not only causes the campaign.name
field to be returned, but causes the campaign.resource_name
field to be returned and segmented on.
Selectability between segments and metrics
A given segment field may not be compatible with some of the other segment fields, or with some of the metrics fields. To identify which segment fields are compatible with each other, review the selectable_with
list of the segments in the SELECT
clause.
In the case of the ad_group
resource, there are 50+ available segments that you can select. However, the selectable_with
list for segments.hotel_check_in_date
is a much smaller set of compatible segments. This means if you add the segments.hotel_check_in_date
field into the SELECT
clause, you will limit the available segments you have left to select to the intersection of these two lists.
When you add certain segments, the metrics in the summary row may decrease. When segments.keyword.info.match_type
is added to a query with FROM ad_group_ad
, that segment is telling the query to only get the rows of data that have keywords, and to remove any row that is not associated with a keyword. In this case, the metrics will be lower because they exclude any non-keyword metrics.
Rules for segments in the WHERE clause
When a segment is in the WHERE
clause, it must also be in the SELECT
clause. The exception to this rule are the following date segments, which are referred to as core date segments:
segments.date
segments.week
segments.month
segments.quarter
segments.year
Rules for core date segment fields
The segments segments.date
, segments.week
, segments.month
, segments.quarter
, and segments.year
function as follows:
These segments can be filtered in the
WHERE
clause without appearing in theSELECT
clause.If any of these segments are in the
SELECT
clause, a finite date range composed of core date segments must be specified in theWHERE
clause. The date segments don't need to be the same ones specified in theSELECT
.
Examples
Invalid: Since segments.date is in the SELECT clause, you need to specify a finite date range in the WHERE clause for a segments.date , segments.week , segments.month , segments.quarter , or segments.year . | SELECT campaign.name, metrics.clicks, segments.date FROM campaign |
Valid: This query returns campaign names and clicks accrued during the date range. Note that segments.date doesn't need to appear in the SELECT clause. | SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date > '2024-01-01' AND segments.date < '2024-02-01' |
Valid: This query returns campaign names and clicks segmented by date for all days in the date range. | SELECT campaign.name, metrics.clicks, segments.date FROM campaign WHERE segments.date > '2024-01-01' AND segments.date < '2024-02-01' |
Valid: This query returns campaign names and clicks segmented by month for all days in the date range. | SELECT campaign.name, metrics.clicks, segments.month FROM campaign WHERE segments.date > '2024-01-01' AND segments.date < '2024-02-01' |
Valid: This query returns campaign names and clicks segmented by quarter and then by month for all months in the year range. | SELECT campaign.name, metrics.clicks, segments.quarter, segments.month FROM campaign WHERE segments.year > 2019 AND segments.year < 2024 |
search_term_view
The search_term_view
resource is also implicitly segmented by ad group, not just a search term, as reflected by the structure of its resource name, which also includes the ad group. Therefore, you will get some seemingly duplicate rows with the same search terms appearing in your results, but these rows belong to a different ad group.
{
"results":[
{
"searchTermView":{
"resourceName":"customers/1234567890/searchTermViews/111111111~2222222222~Z29vZ2xlIb3RvcyBpb3M",
"searchTerm":"google photos"
},
"metrics":{
"impressions":"3"
},
"segments":{
"date":"2024-06-15"
}
},
{
"searchTermView":{
"resourceName":"customers/1234567890/searchTermViews/111111111~33333333333~Z29vZ2xlIb3RvcyBpb3M",
"searchTerm":"google photos"
},
"metrics":{
"impressions":"2"
},
"segments":{
"date":"2024-06-15"
}
}
]
}
Although the two returned objects in this example appear to be duplicates, their resource names are actually different, particularly in the "ad group" part. This means that the search term "google photos" is attributed to the two ad groups (ID 2222222222
and 33333333333
) on the same date (2024-06-15). Thus, we can conclude that the API worked as intended and didn't return duplicate objects in this case.