Docs

Google Ads conversions

Google needs a click id (gclid, gbraid or wbraid) – or, with enhanced conversions for leads, a hashed e-mail. 3x copies the click ids from the session. Two ways to deliver:

CSV feed (recommended start)Google Ads API
Developer tokennot neededneeded (Basic or Standard access)
LatencyGoogle pulls on its schedule (daily or every 6 h)seconds
Status in 3xfeeduploaded
Test modepreview in Google AdsvalidateOnly

Both can run together – Google deduplicates on click id + action + time (the API sends the event id as orderId).

Conversion actions

Google Ads → Goals → Conversions → Summary → New conversion action → Import → Other data sources or CRMs → Track conversions from clicks. Create one action per definition (category Submit lead form, Book appointment, Contact, …; count One). If browser-side gtag actions exist for the same events, make only one of them primary to avoid double counting in bidding.

Put the action's exact name into providers.google_ads.feedName (feed) and its id or resource name customers/<id>/conversionActions/<id> (ctId in the action's URL) into providers.google_ads.conversionAction (API).

Option A – scheduled CSV feed

PUT /v1/projects/{project}/destinations/google_ads
{
  "enabled": true,
  "mode": "live",
  "transport": "feed",
  "settings": {
    "customerId": "1234567890",
    "loginCustomerId": null,
    "apiVersion": "v23",
    "enhancedConversionsForLeads": false,
    "feed": { "enabled": true, "username": "google-ads-feed", "timezone": "Europe/Berlin" }
  },
  "secrets": { "feedPassword": "<openssl rand -base64 32>" }
}

Feed URL (HTTP Basic auth with username / feedPassword):

https://<api-host>/v1/projects/<project id>/feeds/google-ads.csv

It lists conversions of the last 60 days in the format Google expects:

Parameters:TimeZone=Europe/Berlin
Google Click ID,GBRAID,WBRAID,Conversion Name,Conversion Time,Conversion Value,Conversion Currency
Cj0KCQ…,,,Demo booked (Server),2026-10-14 15:02:11,500.00,EUR

?definition=<key> or ?source=<source> narrows the feed – useful when Google's data manager wants one connection per conversion action. With enhancedConversionsForLeads: true an Email column with the normalized SHA-256 hash is added (only after accepting the customer data terms in Google Ads).

Then in Google Ads: Goals → Conversions → Uploads → Schedules → New schedule → source HTTPS → the URL above → user name and password → daily (or every 6 h) → save, then Run now once and check the upload diagnostics. Use a host that answers without redirect (curl -I it first): redirects can drop the credentials.

Option B – Google Ads API

Settings as above with "transport": "direct" and these secrets:

SecretWhere to get it
developerTokenmanager account → Tools → API Center
clientId, clientSecretGoogle Cloud console → enable Google Ads API → Credentials → OAuth client
refreshTokenOAuth consent with scope https://www.googleapis.com/auth/adwords (e.g. OAuth Playground with your client)

Set loginCustomerId to the MCC id when access goes through a manager account. 3x calls customers/{customerId}:uploadClickConversions with partialFailure: true; in test mode with validateOnly: true. Access tokens are cached until a minute before they expire.

With "transport": "composio" (and adConnectionId of your Google connection) the same call goes through the Composio proxy using the connection's OAuth – no developer token or refresh token in 3x.

  • Click conversions older than 90 days are rejected (3x skips them after 89 days).
  • No consent signal (adUserData) is sent by default. In the EEA Google may restrict conversions without a consent signal; check the upload diagnostics.
  • X3_GOOGLE_ADS_API_VERSION (default v23) and settings.apiVersion pin the API version; Google sunsets versions roughly yearly.