Segmentation, available in the Google Ads UI as a separate menu, can be implemented in the Google Ads API by just adding the proper field to a query. For example, adding segments.device
to a query, 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.
While in the Google Ads UI only one segment at a time can be used, 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
would look something like 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"
}
},
...
]
}
Note that in the above 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"
}
}
]
}
Note that the resource_name
field of adGroup
is always returned because ad_group
was 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, we'll 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 1 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 selecting fields from one of those listed resources 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 will not only cause the campaign.name field to be returned, but will cause 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, you can 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 adding some segments, the metrics in the summary row may decrease
-
When
segments.keyword.info.match_type
is added to a query withFROM ad_group_ad
, that segment is telling the query to only get the rows of data that have keywords, and remove any row that is not associated with a keyword. In this case, the metrics would be lower because it would 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 > '2020-01-01' AND segments.date < '2020-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 > '2020-01-01' AND segments.date < '2020-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 > '2020-01-01' AND segments.date < '2020-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 > 2015 AND segments.year < 2020 |
search_term_view
Note that for the search_term_view
resource, it's also implicitly segmented by ad group, not just a search term, as reflected by the structure of its resource name, which also includes ad group as well. Therefore, you will get some seemingly duplicate rows with the same search terms appearing in your results when in actuality, the rows would belong to a different ad group:
{
"results":[
{
"searchTermView":{
"resourceName":"customers/1234567890/searchTermViews/111111111~2222222222~Z29vZ2xlIHBob3RvcyBpb3M",
"searchTerm":"google photos"
},
"metrics":{
"impressions":"3"
},
"segments":{
"date":"2015-06-15"
}
},
{
"searchTermView":{
"resourceName":"customers/1234567890/searchTermViews/111111111~33333333333~Z29vZ2xlIHBob3RvcyBpb3M",
"searchTerm":"google photos"
},
"metrics":{
"impressions":"2"
},
"segments":{
"date":"2015-06-15"
}
}
]
}
Although the two returned objects in this example seem 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 (2015-06-15). Thus, we can conclude that the API worked as intended and didn't return duplicate objects in this case.