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`](https://developers.google.com/google-ads/api/fields/v26/segments#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](https://developers.google.com/google-ads/api/docs/query/grammar), 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`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/SearchStream) 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.

> [!CAUTION]
> **Caution:** For each additional segment field included in your report query, the number of rows can increase exponentially.

## 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`](https://developers.google.com/google-ads/api/fields/v26/ad_group) as the resource in the `FROM` clause, then
[`ad_group.resource_name`](https://developers.google.com/google-ads/api/fields/v26/ad_group#ad_group.resource_name) is
automatically returned and metrics implicitly segment against it at the
`ad_group` level.

So for this query:

    SELECT metrics.impressions
    FROM ad_group

You 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.

### search_term_view

The [`search_term_view`](https://developers.google.com/google-ads/api/fields/v26/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](https://developers.google.com/google-ads/api/fields/v26/search_term_view#search_term_view.resource_name), which also includes the ad group.
Therefore, you may receive seemingly duplicate rows with the same search terms
appearing in your results when those rows belong to different ad groups:

    {
      "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 appear to be duplicates, their
resource names are actually different, particularly in the ad group ID portion.
This means that the search term `"google photos"` is attributed to two ad groups
(ID `2222222222` and `33333333333`) on the same date (`2024-06-15`). Thus, the
API worked as intended and didn't return duplicate objects in this case.

> [!IMPORTANT]
> **Key Point:** Technically, the `search_term_view` resource is also implicitly segmented by a campaign. However, an ad group must always belong to a campaign, so using only the ad group to deduplicate data rows is sufficient because an ad group is the most granular unit.

## 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`](https://developers.google.com/google-ads/api/fields/v26/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`](https://developers.google.com/google-ads/api/fields/v26/ad_group) resource's metadata page.

> [!NOTE]
> **Note:** Segment availability on specific resources can vary by API version. Use the version selector in the [Google Ads Field Service reference](https://developers.google.com/google-ads/api/fields/v26/overview) to verify compatibility for your target version (`v23`, `v24`, `v25`, or `v26`). For example, in **v24
> and later** , `segments.click_type` isn't selectable with `ad_group_asset`, `campaign_asset`, or `customer_asset`, and `segments.ad_sub_network_type` isn't selectable with `campaign_budget` (these combinations are only supported in **v23**).

## 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`](https://developers.google.com/google-ads/api/fields/v26/ad_group) resource, you'll see
that you can also select fields from the [`campaign`](https://developers.google.com/google-ads/api/fields/v26/campaign)
resource. The `resource_name` field of any `Attributed Resources` with at least
one field in the `SELECT` clause is automatically 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 causes the query to be further segmented by the returned
`resource_name` of that `Segmenting Resource`. As an example, you'll find that
the [`campaign`](https://developers.google.com/google-ads/api/fields/v26/campaign) resource is listed as a `Segmenting
Resource` for the [`campaign_budget`](https://developers.google.com/google-ads/api/fields/v26/campaign_budget) resource.
Selecting any campaign field, like
[`campaign.name`](https://developers.google.com/google-ads/api/fields/v26/campaign#campaign.name), from the `campaign_budget`
resource not only causes the `campaign.name` field to be returned, but causes
the [`campaign.resource_name`](https://developers.google.com/google-ads/api/fields/v26/campaign#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`](https://developers.google.com/google-ads/api/fields/v26/ad_group) resource, there are 50+
available segments that you can select. However, the `selectable_with` list for
[`segments.hotel_check_in_date`](https://developers.google.com/google-ads/api/fields/v26/ad_group#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 limit the available segments you have left
to select to the intersection of these two lists.

### Joint segment constraints

Some segment fields have explicit selection constraints requiring them to be
requested alongside a parent segment in the `SELECT` clause:

- Selecting [`segments.ad_sub_network_type`](https://developers.google.com/google-ads/api/fields/v26/segments#segments.ad_sub_network_type) (which breaks down YouTube ad sub-networks such as In-stream, In-feed, and Shorts) requires you to also select [`segments.ad_network_type`](https://developers.google.com/google-ads/api/fields/v26/segments#segments.ad_network_type).
- In **v25 and later** , selecting [`segments.ad_sub_format_type`](https://developers.google.com/google-ads/api/fields/v26/segments#segments.ad_sub_format_type) (which breaks down YouTube in-stream non-skippable ads by duration) requires you to also select [`segments.ad_format_type`](https://developers.google.com/google-ads/api/fields/v26/segments#segments.ad_format_type).

### Implicit filtering by segment selection

When you select certain segment fields in your query, the Google Ads API may implicitly
filter the results to include only rows where that segment is applicable and has
a value.

#### Impact of `segments.keyword.*`

A common and important example of this behavior occurs when selecting any field
under `segments.keyword` (such as `segments.keyword.info.text` and
`segments.keyword.ad_group_criterion`):

- **Exclusion of Non-Keyword Traffic:** If you include any `segments.keyword.*` field in your `SELECT` clause, that restricts the results to only those rows directly associated with a Search Network keyword ad group criterion.
- **Campaign Types Affected:** Consequently, data from campaign types or ad groups that don't rely on Search keywords are **excluded** from the results. This includes, but is not limited to:
  - **Dynamic Search Ads (DSA):** Because DSA targets are based on website content rather than keywords.
  - **Shopping campaigns:** Which use product groups instead of keywords.
  - **Performance Max campaigns:** While Performance Max may serve on Search, its reporting is not typically segmented by the same keyword criteria.
- **Display Network:** The `segments.keyword.*` fields pertain to keywords used on the **Search Network**. They do not segment by Display Network keywords or other display targeting methods.

> [!TIP]
> **Tip:** If your analysis needs to include performance data from DSA, Shopping, or other non-search-keyword sources, don't include fields from `segments.keyword.*` in your query. Analyze data across all campaign types first, and apply keyword segmentation only when focusing on Search keyword performance.

## 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:

> [!IMPORTANT]
> **Key Point:** Granular date segments (`segments.date`, `segments.week`, and `segments.hour`) support a lookback window of up to **37 months** . Queries exceeding this range return `DateRangeError.REQUESTED_DATE_GRANULARITY_NOT_SUPPORTED` in v24 and later (or `DateRangeError.UNKNOWN` in v23). Use `segments.month`, `segments.quarter`, or `segments.year` for older historical data.

- These segments can be filtered in the `WHERE` clause without appearing in the `SELECT` clause.
- If any of these segments are in the `SELECT` clause, a finite date range composed of *core date segments* must be specified in the `WHERE` clause. The date segments don't need to be the same ones specified in the `SELECT`.

### 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`. | ```sql SELECT campaign.name, metrics.clicks, segments.date FROM campaign ``` |
| Valid: This query returns campaign names and clicks accrued during the inclusive date range. Note that `segments.date` doesn't need to appear in the `SELECT` clause. | ```sql SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date >= '2024-01-01' AND segments.date <= '2024-01-31' ``` |
| Valid: This query returns campaign names and clicks segmented by date for all days in the inclusive date range. | ```sql SELECT campaign.name, metrics.clicks, segments.date FROM campaign WHERE segments.date >= '2024-01-01' AND segments.date <= '2024-01-31' ``` |
| Valid: This query returns campaign names and clicks segmented by month for all days in the inclusive date range. | ```sql SELECT campaign.name, metrics.clicks, segments.month FROM campaign WHERE segments.date >= '2024-01-01' AND segments.date <= '2024-01-31' ``` |
| Valid: This query returns campaign names and clicks segmented by quarter and then by month for all months in the inclusive year range. | ```sql SELECT campaign.name, metrics.clicks, segments.quarter, segments.month FROM campaign WHERE segments.year >= 2020 AND segments.year <= 2024 ``` |