Server-side events · Platform reference
Google Ads API offline click conversion import (UploadClickConversions): events, fields and dedup rules
Offline conversion import uploads ClickConversion rows (a click ID such as gclid, gbraid or wbraid, or hashed user data for enhanced conversions for leads) to an UPLOAD_CLICKS conversion action, usually from a CRM. Uploads 'succeed' but don't attribute when the click can't be found (CLICK_NOT_FOUND), the upload is past the 90-day limit (63 days for enhanced conversions for leads), conversion_date_time is earlier than the click or has no timezone, or consent isn't set. Since 15 June 2026 the method is closed to new adopters, who must use the Data Manager API instead.
Read from the official documentation on 9 November 2026. Sources are listed at the end.
Endpoint and authentication
ConversionUploadService.UploadClickConversions (Google Ads API); new integrations: Data Manager API
Google Ads API developer token and OAuth credentials for the conversion customer. Since 15 June 2026, developer tokens that sent no offline conversion uploads between 17 Dec 2025 and 15 Jun 2026 get CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE
Calls and objects
Google Ads has no standard event list: every conversion action is one you create. These are the upload types and API objects an offline import works through.
| Name | What it is |
|---|---|
| UPLOAD_CLICKS | required conversion action type for click conversion imports (INVALID_CONVERSION_ACTION_TYPE otherwise) |
| ClickConversion | one imported conversion: click ID and/or user_identifiers, conversion_action, conversion_date_time, value |
| Enhanced conversions for leads | ClickConversion with hashed user_identifiers (email/phone only); the account must have it enabled or you get CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS |
Required and recommended fields
| Field | What it needs |
|---|---|
| conversion_action | Resource name of a conversion action with type UPLOAD_CLICKS in the conversion customer |
| conversion_date_time | Format yyyy-mm-dd HH:mm:ss+|-HH:mm with a timezone; must be after the click time |
| gclid / gbraid / wbraid | Include every identifier you captured; any combination is accepted on one ClickConversion |
| conversion_value + currency_code | Numeric (double) value plus a 3-character ISO 4217 currency code |
| order_id | Unique transaction ID per conversion action. Stops duplicate imports and must be reused for later adjustments |
| consent | If not set, conversions may not be attributable |
| partial_failure | Must be true when importing conversions |
| user_identifiers | Required for enhanced conversions for leads: 1 to 5 normalised and hashed identifiers (hashed_email, hashed_phone_number only) |
Match keys and hashing
| Key | Normalise and hash |
|---|---|
| hashed_email | Trim and lowercase. For gmail.com/googlemail.com also remove periods and any +suffix from the username. SHA-256 as a 64-character lowercase hex string |
| hashed_phone_number | Format to E.164, then SHA-256 |
Click ids
| Click id | Where it comes from |
|---|---|
| gclid | Google click ID. Takes priority when several IDs are present (gclid, then wbraid, then gbraid). Google keeps the GCLID for 90 days |
| wbraid | Accepted alongside other IDs. If sent without a gclid, any user_identifiers are ignored |
| gbraid | Accepted alongside other IDs. If sent without a gclid, any user_identifiers are ignored |
Deduplication
- order_id should be unique per conversion action; it stops duplicate imports and is required for any later adjustment.
- Several conversions in one request sharing an order_id fail with DUPLICATE_ORDER_ID and aren't processed.
- Google won't import the same conversion more than once; duplicate uploads get an error and are counted once.
- One GCLID can carry several conversions if they have different conversion times and the action counts 'every' conversion.
Time limits and batch sizes
- Offline conversions uploaded more than 90 days after the associated last click aren't imported.
- Enhanced conversions for leads uploaded more than 63 days after the associated last click aren't imported.
- conversion_date_time must be after the click time and include a timezone offset.
- Up to 2,000 click conversions per request (TOO_MANY_CONVERSIONS_IN_REQUEST otherwise).
- Imported conversion stats take about 3 hours to show up in Google Ads.
How to test before you trust it
- validate_only: Set validate_only=true to validate the request without importing any conversions.
- partial_failure_error: With partial_failure=true, row-level errors (CLICK_NOT_FOUND, EXPIRED_EVENT and so on) come back per row while valid rows are imported.
- job_id: Give related requests a job_id (1 to 2^31-1) to group them in offline conversion job summaries.
Why events arrive but don't attribute
- CLICK_NOT_FOUND: no matching click. Google says to treat it as a warning unless it affects most of your conversions. It's often a gclid captured from the wrong account or mangled in the CRM.
- EXPIRED_EVENT: the click happened before the conversion action's click-through window, so it can't be credited.
- Uploaded too late: past 90 days after the last click (63 for enhanced conversions for leads), so the row is never imported.
- conversion_date_time earlier than the click, often a timezone mismatch. The format needs an explicit +/-HH:mm offset.
- consent not set on the ClickConversion. Google says those conversions may not be attributable.
- Enhanced conversions for leads sent with wbraid/gbraid but no gclid, or with custom_variables or external_attribution_data set. In both cases Google ignores the user_identifiers.
- Conversion action isn't type UPLOAD_CLICKS, or is disabled or lives in a different customer (INVALID_CONVERSION_ACTION_TYPE / NO_CONVERSION_ACTION_FOUND).
- A new integration built on UploadClickConversions after 15 June 2026 is rejected with CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE. Use the Data Manager API.
Sources
- Google Ads API: Upload click conversions
- Google Ads API: Enhanced conversions for leads
- Google Ads Help: Guidelines for importing offline conversions
- Google Ads API: Quotas and limits
Platforms change these rules without notice. If a source says something different from this page, the source wins.