> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datalyr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Google Ads

> Connect a Google Ads customer account and upload conversions.

When you finish, one Datalyr event uploads to a Google Ads conversion action and reports a terminal state.

## Before you start

| Requirement | Detail |
| - | - |
| Google user | Has direct or manager access to the customer account |
| Google Ads customer ID | The 10-digit ID at the top right of Google Ads |
| Conversion action | Type **Import from clicks**. Google Ads: **Goals → Conversions → New → Import → Manual import using the API** |
| A click ID or an email | Google rejects an upload that carries neither |

<Warning>
  Create the conversion action as **Import from clicks**. A GA4, website, or call action accepts no API upload, and every conversion you send to it fails.
</Warning>

## Connect Google Ads

<Steps>
  <Step title="Open Sources">
    Open **Sources**. Find the **Google Ads** card.
  </Step>

  <Step title="Authorize">
    Select **connect**. Sign in with the Google user. Approve every requested scope.
  </Step>

  <Step title="Pick the customer account">
    Choose the customer account, not the manager account. Select **set as primary**.
  </Step>
</Steps>

The card reads `needs primary account` until you finish step 3.

## Create the rule

<Steps>
  <Step title="Open the editor">
    Open **Conversions**. Select **manage rules**. Select **new rule**.
  </Step>

  <Step title="Set the trigger">
    Fill **rule name**. Pick the **trigger event**. Pick **Google** as **target platform**.
  </Step>

  <Step title="Pick the conversion action">
    Pick the action under **Google Conversion Action**. Select **next**.
  </Step>

  <Step title="Map the value">
    Set **value** to `dynamic`. Pick the numeric path. Set **currency**. Select **save**.
  </Step>
</Steps>

The editor blocks a save when the action cannot receive API uploads. It also blocks any trigger event whose name contains `refund` or `chargeback`, because Google rejects negative conversion values.

## Reference

| Transport | Endpoint | When we use it |
| - | - | - |
| Data Manager API | `POST https://datamanager.googleapis.com/v1/events:ingest` | Default. Needs the OAuth scope `https://www.googleapis.com/auth/datamanager` |
| Legacy click upload | `POST /v24/customers/{customer_id}:uploadClickConversions` | Only after Google returns `ACCESS_TOKEN_SCOPE_INSUFFICIENT` on the call above |

Reconnect Google Ads to move a grandfathered connection onto the Data Manager API.

### Request body

| Field | Value |
| - | - |
| `destinations[].operatingAccount` | `{ accountType: "GOOGLE_ADS", accountId: <customer id> }` |
| `destinations[].productDestinationId` | The conversion action ID from the rule |
| `encoding` | `HEX` |
| `events[].eventTimestamp` | ISO-8601 with an explicit `+00:00` offset |
| `events[].transactionId` | The event's `order_id`, else the Datalyr `event_id` |
| `events[].conversionValue` | The rule's `value_path`, else `value_static`, else `value` / `revenue` / `total` / `amount` |
| `events[].currency` | The rule's currency |
| `events[].eventSource` | `WEB`, or `APP` when the click ID is `gbraid` or `wbraid` |
| `consent.adUserData`, `consent.adPersonalization` | `CONSENT_GRANTED`, or `CONSENT_DENIED` after a marketing denial |
| `validateOnly` | `true` during a test send |

### Click identifiers

We send exactly one, in this order: `gclid`, then `gbraid`, then `wbraid`. The attribution lookup window is 90 days.

### `userIdentifiers`

| Identifier | Normalization | Hashed |
| - | - | - |
| `emailAddress` | lowercase, trim. Gmail dots are kept | SHA-256, hex |
| `phoneNumber` | E.164 with the leading `+` kept | SHA-256, hex |
| `address.givenName` | lowercase, trim | SHA-256, hex |
| `address.familyName` | lowercase, trim | SHA-256, hex |
| `address.regionCode` | ISO alpha-2, uppercase | plaintext |
| `address.postalCode` | as-is | plaintext |

We add the address identifier only when first name, last name, country, and postal code are all present. The Data Manager API accepts no city or state field.

### Delivery gate

We upload only when the event carries a click ID, an email, or a phone number. Without all three, the delivery row reads `failed` with `missing gclid/gbraid/wbraid and no enhanced conversion data available`.

### Status timeline

Google accepts the upload at once and validates it later, so a Datalyr row moves through two states.

| Row status | Meaning |
| - | - |
| `processing` | Google returned HTTP 2xx and a `requestId`. Nothing is confirmed yet |
| `sent` | A later poll of `requestStatus:retrieve` returned `SUCCESS` for every destination |
| `failed` | The poll returned `FAILED` or `PARTIAL_SUCCESS` |

We poll 30 minutes after the upload. Google conversions are never retried through the dead-letter queue.

## Verify

1. Open **Sources**. Confirm the **Google Ads** card shows the customer ID you intended.
2. Open **Conversions**. Select **manage rules**. Open your rule.
3. Select **send test event**. The request carries `validateOnly: true`.
4. Confirm the rule's `sent` count went up by 1.
5. Trigger one real event. Confirm its row reaches `sent` within 40 minutes.

## When it does not work

| Symptom | Cause | Check | Fix |
| - | - | - | - |
| Editor says the action cannot receive API uploads | The conversion action is GA4, website, or call type | The action type in Google Ads | Create an **Import from clicks** action. Repick it |
| Editor blocks the save on a refund event | Google rejects negative conversion values | The trigger event name | Handle refunds outside conversion rules |
| Delivery `failed`, `missing gclid/gbraid/wbraid and no enhanced conversion data` | No click ID and no email reached the conversion | The event payload in **Events** | Collect email at checkout. Confirm the landing page keeps `gclid` |
| Delivery `failed`, `PERMISSION_DENIED` | The token lost access to the customer account | The card state in **Sources** | Select **disconnect**, then reconnect |
| Delivery `failed`, HTTP 400 | Wrong customer ID or conversion action ID | The response body on the delivery row | Repick the conversion action in the rule |
| Row stays `processing` past an hour | The diagnostics poll returned no terminal state | The row's response body | Wait one more poll cycle. Then contact support |
| Rows are `sent`, Google Ads shows nothing | Google is still attributing, or the click is outside 90 days | The conversion action's own diagnostics in Google Ads | Compare the click date to the conversion date |
| Card reads `needs primary account` | Authorization finished, no customer account chosen | The **Google Ads** card | Select **select account** |

## Next

* [Conversion delivery](/advanced/conversion-delivery): how a rule resolves value, identity, and status.
* [Conversions](/product/conversions): read the delivery row and its response body.
* [Attribution](/attribution/index): how `gclid` survives to a server-side purchase.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.