# Google Ads

CLItrail uploads each attributed install as an offline click conversion through Google’s Data Manager API, with a Google Cloud service account you create and paste, so Google Ads can optimise campaigns for installs.

## Before you start

- A conversion action in the Google Ads account that owns it, with the source **Import from clicks** (type `UPLOAD_CLICKS`). Its ID is the `ctId` value in its page URL, or the number next to **Conversion type ID** on its Details tab. For Smart Bidding to optimise for installs, make it a primary action.
- A Google Cloud project where you can create service account keys. Organisations created on or after 3 May 2024 block key creation by default (the `iam.disableServiceAccountKeyCreation` policy): an organisation policy administrator must allow it for this project.
- A Standard or Enterprise plan.

## Set it up

1. Enable the Data Manager API
  In the Google Cloud console, choose or create a project and enable the **Data Manager API**. Requests are counted against this project’s own Data Manager quota.
2. Create a service account
  Open **IAM & Admin → Service accounts**, create a service account and grant it the **Service Usage Consumer** role (`roles/serviceusage.serviceUsageConsumer`) on the project.
3. Create a JSON key
  On the service account, open **Keys → Add key → Create new key → JSON**. The key file downloads once. Keep it only until you have pasted it into CLItrail.
4. Give it access to Google Ads
  In Google Ads, open **Admin → Access and security**, choose **+** under **Users**, enter the service account’s email address, choose an access level that can edit (such as Standard) and choose **Add account**. One email can be added to at most 20 Google Ads accounts; beyond that, add it to a manager account above them.
5. Add the destination
  In CLItrail, open **Destinations → Add destination → Google Ads**. Paste the key file’s contents, then enter the customer ID, the conversion action ID and your consent choices.
6. Test, then go live
  **Send test** sends a validate-only request, which checks access to the account and conversion action without recording anything. Going live needs the terms confirmation and a [verified domain](https://clitrail.com/docs/domain-verification).

## How the key is used

- Only the fields needed to sign are kept (the type, project ID, key ID, private key and client email), [sealed in the separate secret store](https://clitrail.com/docs/secrets) and write-only: the dashboard shows only that a key is set, a fingerprint and when it was updated.
- CLItrail uses Google’s OAuth 2.0 flow for server-to-server applications: it signs a short JWT with the key (RS256), exchanges it at `https://oauth2.googleapis.com/token` for an access token with the single scope `https://www.googleapis.com/auth/datamanager`, and keeps that token in memory until shortly before it expires. Tokens are never stored or logged.
- No Google sign-in, consent screen, developer token or domain-wide delegation is involved. To revoke CLItrail’s access, delete the key in Google Cloud or remove the service account from your Google Ads users.

## Data partner link

When this service is an approved Google Data Manager data partner, the form also offers **I linked CLItrail as a data partner in Google Ads**. You create that link yourself in Google Ads (**Tools → Data manager**) and confirm it in the destination; CLItrail then sends with its own credentials, as the data partner. If you created the partner link on a manager account above this one, enter that manager’s ID as **Linked manager account ID**. If the option is not in your form, use your own service account key as above.

## Settings

| Field | Format |
| --- | --- |
| Service account key | The JSON key file’s contents, with `"type": "service_account"`, the client email and the private key. |
| Customer ID | The 10 digits of the Google Ads account that owns the conversion action; dashes are fine. |
| Conversion action ID | Digits. |
| Manager account ID | Optional, 10 digits: only when you added the service account to a manager account above the Google Ads account. |
| Linked manager account ID | Data partner link only, optional, 10 digits: the manager account the partner link was created on. |
| Ad user data, Ad personalization | Granted, Denied or Not specified. Required: choose what matches the consent you collect. |
| Value and currency | Optional. A value from 0 to 1,000,000,000 and a 3-letter currency code. |

Consent choices become `CONSENT_GRANTED` or `CONSENT_DENIED`; Not specified leaves the field out. With ad user data denied, CLItrail sends nothing to Google at all. Follow Google’s EU user consent policy for your visitors.

## What is sent

```json
{
  "destinations": [{
    "operatingAccount": {
      "accountType": "GOOGLE_ADS",
      "accountId": "1234567890"
    },
    "productDestinationId": "987654321"
  }],
  "events": [{
    "transactionId": "clt_f399d6357f61bcf15f9370c69a41662457de8a05",
    "eventTimestamp": "2026-09-23T14:02:11.000Z",
    "eventSource": "OTHER",
    "adIdentifiers": {
      "gclid": "YOUR_GCLID",
      "sessionAttributes": "eyJnYWRfc291cmNlIjoiMSIsIn…"
    },
    "consent": {
      "adUserData": "CONSENT_GRANTED",
      "adPersonalization": "CONSENT_DENIED"
    },
    "conversionValue": 1,
    "currency": "USD"
  }]
}
```

- **The account.** `operatingAccount` is the Google Ads account that owns the conversion action, as Google requires for offline conversions. With a manager account ID, `loginAccount` names the manager. Through a data partner link, `loginAccount` is CLItrail’s `DATA_PARTNER` account, and `linkedAccount` names the linked manager account when you entered one.
- **One click ID per event.** `gclid` from the landing URL or the `_gcl_aw` cookie, otherwise `wbraid`, otherwise `gbraid`, plus Google’s session attributes of the session that click landed in. Each is dated by its own evidence: a URL click by its visit, the cookie by its click time, session attributes by their session start. Attributes that later visits merely reused stay with their own click. The policy picks the most recent (latest visit) or earliest (first visit) of the clicks still importable.
- **90-day rule.** Google does not import conversions more than 90 days after the click, counted from the click itself. Older clicks are never sent, and queued events expire 90 days after their click.
- **`eventSource` is `OTHER`.** The install happened in a terminal, not a web browser.
- **Deduplication.** `transactionId` is stable for each install, so retries are safe. Up to 2,000 events go in one request.

## Common errors

| Google says | What to check |
| --- | --- |
| `PERMISSION_DENIED`, Data Manager API has not been used in project … | Enable the Data Manager API in the service account’s own project. |
| `PERMISSION_DENIED` | The service account is not a user of the Google Ads account (or of the manager you named), or its access level cannot edit. |
| `INVALID_CONVERSION_ACTION_ID`, `INVALID_CONVERSION_ACTION_TYPE` | Use the ID of an “Import from clicks” action owned by that customer ID. |
| `CONVERSION_ACTION_TOO_RECENTLY_CREATED` | Wait, then send a test again. |

When Google answers `403` for a pasted key, the destination’s error names the service account’s email and the account it needs access to. A refused credential keeps the queue and is tried about once an hour; pasting a new key resumes delivery at once.
