For automated or large-scale data pulls for GeoX experiments, you must use the
Google Ads API to pull cost and spend data. You then combine this data with raw,
unfiltered, and unattributed conversion or revenue data from your internal CRM,
a Point of Sale (POS), or internal sales databases.

## Recommended API workflow architecture

To accurately pull campaign and cost data by geographic segments, follow this
architecture:

- **Service:** Use `GoogleAdsService`, specifically the [`Search`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/Search) or [`SearchStream`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/SearchStream) methods.
- **Resource:** Query [`geographic_view`](https://developers.google.com/google-ads/api/fields/v26/geographic_view) to see
  where the user was physically located or interested in, which is typically
  the standard for GeoX experiments. Alternatively, query
  [`location_view`](https://developers.google.com/google-ads/api/fields/v26/location_view) to see performance based on
  specific locations targeted by the campaign.

  > [!NOTE]
  > **Note:** Don't use `campaign_location_target_report`, as this legacy AdWords API report has been sunset.

- **Fields to include:**

  - [`campaign.id`](https://developers.google.com/google-ads/api/fields/v26/campaign#campaign.id)
  - [`segments.date`](https://developers.google.com/google-ads/api/fields/v26/segments#segments.date)
  - [`segments.geo_target_city`](https://developers.google.com/google-ads/api/fields/v26/segments#segments.geo_target_city) (or region or country depending on the GeoX granularity)
  - [`metrics.cost_micros`](https://developers.google.com/google-ads/api/fields/v26/metrics#metrics.cost_micros)
- **Sample GAQL query:** For GeoX, advertisers pull cost metrics using the
  Google Ads API rather than attributed conversions (which should come from internal
  CRM or third-party systems). You can use the following query:

      SELECT
        campaign.id,
        segments.date,
        segments.geo_target_city,
        metrics.cost_micros
      FROM geographic_view
      WHERE segments.date DURING LAST_30_DAYS

  > [!NOTE]
  > **Note:** `geographic_view` only returns rows for geographic segments that recorded impressions or spend on a given date. To include zero-spend days and regions in your GeoX time series, perform a left outer join in your data pipeline against the complete Cartesian product of dates and target regions.

> [!NOTE]
> **Note:** If you pull conversion metrics from Google Ads, you are pulling *attributed* conversions---meaning you are only looking at the sales that Google's algorithm has already claimed credit for. Using attributed data is strongly discouraged in GeoX because attribution logic biases the causal measurement.

## Post-processing and data extraction

- **Geographic segment mapping:** The API doesn't return plain text names
  (like "New York") or short codes (like "501" or "ES") in reporting views.
  Fields like `segments.geo_target_city` or `segments.geo_target_country`
  return a resource name string pointing to a `GeoTargetConstant` (for
  example, `geoTargetConstants/1023191`). Extract the numeric ID (`1023191`)
  and query the [`geo_target_constant`](https://developers.google.com/google-ads/api/fields/v26/geo_target_constant)
  resource:

      SELECT
        geo_target_constant.id,
        geo_target_constant.name,
        geo_target_constant.canonical_name
      FROM geo_target_constant
      WHERE geo_target_constant.id = 1023191

  Alternatively, to perform the join locally in code, download the static geo
  targets CSV at [Geo targets](https://developers.google.com/google-ads/api/data/geotargets).
- **Cost conversion:** The API returns cost values in micros. You must divide
  `metrics.cost_micros` by 1,000,000 to output the standard currency value
  required in your upload file.

## Geo location IDs for targeting mutations

When executing campaign or ad group location targeting mutations, advertisers
must look up and pass the exact `GeoTargetConstant` ID (`geoTargetConstants/ID`)
for their selected regions. You cannot pass raw ISO or Nielsen codes.

| Region Type | Required API ID (`GeoTargetConstant`) | Legacy Format (Do Not Use) |
|---|---|---|
| **DMA Region** | ID `200501` (for New York) | Nielsen Code (for example, `501` for New York) |
| **Country** | ID `2724` (for Spain) | ISO Code (for example, `"ES"` for Spain) |

## Best practices and common formatting errors

- **Date formatting:** The `segments.date` field returns ISO-8601 date strings in the `YYYY-MM-DD` format. In your ETL pipeline, serialize date fields explicitly as `YYYY-MM-DD` strings and avoid opening exported CSV files in spreadsheet applications that automatically reformat date columns.
- **Leading zeros in postal codes:** Treat postal and ZIP codes (for example, `01234`) as string types (`VARCHAR` or `STRING`) throughout your data pipeline rather than integers so that leading zeros are never stripped.
- **Aggregation:** If running a multi-cell study, you must provide separate spend metrics for each treatment arm.
- **Joining conversion data:** When joining with conversion data from an internal CRM system or internal sales databases, ensure that the conversion data has the following properties to ensure seamless data processing with Google Ads API data and GeoX:
  - **Daily time series:** The data must be aggregated by day.
  - **Geographic level:** Every conversion must be mapped to the exact geographic units you are testing (for example, matching the customer's shipping ZIP code to the DMA or postal cluster used in the design).
  - **Gross values:** The data must be non-negative, absolute values like Gross Revenue or Gross Conversion Counts. If your CRM tracks Net Revenue with negative values for refunds, you must use the gross numbers for the experiment and apply a refund ratio later.