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 > '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
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 the 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":"2024-06-15"
}
},
{
"searchTermView":{
"resourceName":"customers/1234567890/searchTermViews/111111111~33333333333~Z29vZ2xlIHBob3RvcyBpb3M",
"searchTerm":"google photos"
},
"metrics":{
"impressions":"2"
},
"segments":{
"date":"2024-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 (2024-06-15).
Thus, we can conclude that the API worked as intended and didn't return
duplicate objects in this case.