Skip to content
Data

Offline conversions moved to the Data Manager API: a guide

Google Ads API offline conversion uploads closed to new users on 15 June 2026. How to move CRM conversion imports to the Data Manager API, step by step.

By Dimitris7 min read
From CRM outcome to conversion. Flat editorial diagram of the article’s measurement workflow.
Tracking Whisper
The short answer

Since 15 June 2026 the Google Ads API no longer accepts new users of offline conversion imports, including enhanced conversions for leads: only integrations that uploaded between 17 December 2025 and 15 June 2026 kept legacy access, and Google points everyone to the Data Manager API. Migrating means mapping UploadClickConversions fields to an IngestEventsRequest, switching to the datamanager OAuth scope, and adapting to an all-or-nothing validation model.

If you send CRM outcomes back to Google Ads, such as qualified leads, signed contracts or phone sales, the plumbing changed this year. Google has moved offline conversion imports and enhanced conversions for leads from the Google Ads API to the Data Manager API. Existing integrations were given a grace period, new ones were not. This guide covers what happened, who is affected and how to migrate an upload job without losing conversions.

What changed, and when?

Three dates matter.

  • Version 1.2 of the Data Manager API added support for sending offline conversions and enhanced conversions for leads to Google Ads through the IngestEvents method. The same release made an event source field required for these events, with values such as WEB, APP, IN_STORE, PHONE and OTHER.
  • 15 June 2026. According to the Google Ads Developer Blog post on changes to offline click conversion import support, the Google Ads API stopped accepting new adopters of offline conversion imports from this date, including enhanced conversions for leads. Integrations that sent no offline conversion upload requests between 17 December 2025 and 15 June 2026 lost access, and their UploadClickConversions requests return CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE. Integrations that did upload in that window kept legacy access.
  • 28 May 2026 (v1.7). The Data Manager API added offline conversions for Campaign Manager 360, Search Ads 360 and Display & Video 360, plus a conversion_count field on events. If you run conversions across Google Ads and Google Marketing Platform, one integration can now feed both.

The legacy allowlist was defined in terms of developer tokens. Developer tokens themselves were sunset on 9 September 2026 (see our article on the Google Ads API after developer tokens). Google has not, in the pages we checked, described how the offline conversion allowlist maps to Cloud projects after that change. Treat legacy access as temporary and plan the move now.

Who needs to migrate?

Your setupAffectedWhat to do
Custom script or warehouse job calling UploadClickConversionsYesMigrate to the Data Manager API
Custom job uploading enhanced conversions for leads via the Google Ads APIYesMigrate to the Data Manager API
Third-party tool (CRM connector, call tracking, lead platform)Through the vendorAsk which API it uses and its migration date
Google Ads Data Manager connection to Google Sheets, HubSpot or SalesforceNo API workCheck the connection is healthy
Manual file uploads in the Google Ads interfaceNo API workConsider a scheduled connection instead

If you only use the built-in Google Ads Data Manager connections, this migration is not yours to run. Google lists Google Sheets, HubSpot and Salesforce among the supported data sources for offline conversions and Customer Match.

Why move rather than ride legacy access?

Google's upgrade guide lists concrete differences in favour of the Data Manager API:

  • One data model. The same request shape covers all Google Ads conversion use cases, and since v1.7 also Google Marketing Platform. The Google Ads API used different models per use case.
  • Session attributes and IP addresses. Available to every Data Manager API user. In the Google Ads API they were limited to specific users.
  • Encryption. The Data Manager API supports encrypting user data in the request. The Google Ads API did not.
  • No developer token. Authentication is OAuth with the https://www.googleapis.com/auth/datamanager scope.

How do the fields map?

Google publishes a field-by-field mapping from UploadClickConversionsRequest to IngestEventsRequest. These are the mappings that cause most bugs in practice:

Google Ads APIData Manager APIWatch out for
customer_id, login-customer-id header, linked-customer-id headerdestinations (operatingAccount, loginAccount, linkedAccount)Accounts move from headers into the request body
conversion_action (resource name)productDestinationId on the destinationNumeric conversion action ID, not the resource name
conversion_date_timeeventTimestampRFC 3339 in JSON, a slightly different format from the Google Ads API
order_idtransactionIdKeep the same IDs so restatements and deduplication still line up
gclid, gbraid, wbraidadIdentifiersSame click IDs, new location
user_identifiersuserData.userIdentifiersEncoding declared once per request
partial_failureNoneFast-fail: one bad field rejects the whole request
job_idNoneUse the requestId in the response to retrieve diagnostics

The loss of partial failure is the change that bites hardest. A nightly job that used to upload 5,000 rows and log 12 failures will, unchanged, upload nothing when one row has a malformed timestamp. Validate before sending, and split large uploads into batches so one bad row costs you one batch rather than the night.

Map the conversion before uploading: Map the source, destination, identity and event fields explicitly.
Tracking Whisper
Map the source, destination, identity and event fields explicitly.

What does a request look like?

The endpoint is POST https://datamanager.googleapis.com/v1/events:ingest. A request carries destinations, events, request-level consent, the encoding of user identifiers and an optional validateOnly flag. Each event needs at least one identifier: a click ID in adIdentifiers, session attributes, userData, or an IP address.

{
  "destinations": [
    {
      "operatingAccount": { "accountType": "GOOGLE_ADS", "accountId": "1234567890" },
      "loginAccount": { "accountType": "GOOGLE_ADS", "accountId": "9876543210" },
      "productDestinationId": "555123456"
    }
  ],
  "encoding": "HEX",
  "consent": {
    "adUserData": "CONSENT_GRANTED",
    "adPersonalization": "CONSENT_GRANTED"
  },
  "validateOnly": true,
  "events": [
    {
      "transactionId": "CRM-10482",
      "eventTimestamp": "2026-09-28T14:05:00+02:00",
      "eventSource": "WEB",
      "conversionValue": 1250.0,
      "currency": "EUR",
      "adIdentifiers": { "gclid": "EAIaIQobChMI-example" },
      "userData": {
        "userIdentifiers": [
          { "emailAddress": "223ebda6f6889b1494551ba902d9d381daf2f642bae055888e96343d53e9f9c4" }
        ]
      }
    }
  ]
}

Notes on this example:

  • operatingAccount is the Google Ads account that owns the conversion action. loginAccount is the manager account you authenticate through, if any.
  • productDestinationId is the numeric conversion action ID.
  • Request-level consent applies to every event. You can set consent on an individual event instead, and event-level consent overrides the request level. Send the consent you actually collected: if a user denied ad_user_data, do not upload their hashed email as granted. Our Consent Mode v2 checklist covers how to carry consent state from the website into your CRM.
  • Keep validateOnly set to true until the payload passes, then remove it.
CRM mapping preview: Qualified lead payload. Illustrative interface with synthetic example data.
Tracking Whisper
Validate a small mapped batch and reconcile accepted rows before migrating the pipeline. Illustrative interface; synthetic data, not a live report.

How should user data be normalised and hashed?

Google's formatting guide for the Data Manager API is specific. For email addresses: trim whitespace, lowercase, and for gmail.com and googlemail.com only, remove dots before the @ and drop a plus sign and everything after it in the local part. Phone numbers go to E.164 format, for example +18005550100. Hash with SHA-256 and encode as hex or Base64, matching the request's encoding value.

import hashlib

def normalise_email(raw: str) -> str:
    email = "".join(raw.split()).lower()
    local, _, domain = email.partition("@")
    if domain in ("gmail.com", "googlemail.com"):
        local = local.split("+", 1)[0].replace(".", "")
    return f"{local}@{domain}"

def hash_hex(value: str) -> str:
    return hashlib.sha256(value.encode("utf-8")).hexdigest()

print(hash_hex(normalise_email(" Cloudy.SanFrancisco+shopping@gmail.com ")))

Hash in the system that holds the raw data, not in a spreadsheet halfway through the pipeline. Mixed normalisation between two jobs is a common reason for match rates that fall after a migration.

What is the migration plan?

  1. Inventory every upload path. Scripts, warehouse jobs, CRM workflows, call tracking and any vendor that posts conversions. Note which conversion actions each one feeds.
  2. Set up OAuth for the Data Manager API. Enable the API in your Google Cloud project and request the datamanager scope. The user or service account must have access to the Google Ads account, directly or through a manager account.
  3. Map fields using Google's table. Pay attention to the numeric productDestinationId, RFC 3339 timestamps and the request-level encoding.
  4. Add pre-flight validation. Check timestamps, currency codes, non-negative values and at least one identifier per event before building the request, because one bad row fails the batch.
  5. Run with validateOnly: true. Fix every error until the whole batch passes.
  6. Run both paths in parallel for a short period, if you have legacy access. Send each conversion through only one path per conversion action to avoid double counting, for example by moving one low-volume action first.
  7. Switch over and keep transactionId values identical. This keeps later adjustments and restatements consistent.
  8. Check diagnostics. Store the requestId from each response and use it to retrieve request status, since there is no job_id any more.
  9. Compare imported conversions in Google Ads against your CRM counts for the same dates for two to four weeks.
  10. Retire the old upload code and document the new job, its Cloud project and its owner, so the next person knows where conversions come from.
Validate the pipeline in stages: Build the mapping, verify a small batch and then monitor the migration.
Tracking Whisper
Build the mapping, verify a small batch and then monitor the migration.

What about conversion adjustments and GA4?

Restatements and retractions also move. The Data Manager API documentation has a separate guide for conversion adjustments using IngestEvents. Plan them in the same project so your transactionId strategy covers both uploads and adjustments.

The Data Manager API is also growing beyond Google Ads. In 2026 Google added store sales for Google Ads and more event ingestion use cases for Google Analytics, and a Measurement Protocol upgrade guide sits in the same documentation. If you also send server-side events to GA4 through the Measurement Protocol, keep an eye on that path, but there is no migration deadline for it in the pages we reviewed.

Key takeaways

  • Since 15 June 2026, new offline conversion and enhanced conversions for leads integrations cannot use the Google Ads API. Integrations without uploads between 17 December 2025 and 15 June 2026 receive CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE.
  • The Data Manager API's events:ingest replaces UploadClickConversions, authenticates with the datamanager OAuth scope and needs no developer token.
  • The biggest behavioural change is fast-fail validation: one invalid field rejects the whole request, so validate and batch.
  • Map conversion_action to a numeric productDestinationId, use RFC 3339 timestamps and keep transactionId values unchanged.
  • Built-in Google Ads Data Manager connections to Google Sheets, HubSpot and Salesforce need no API migration.

Offline conversions are a frequent blind spot in tracking checks because nothing on the website changes when an upload job fails. Tracking Whisper's monitoring watches conversion volumes in Google Ads and GA4 and alerts when they stop, which is often the first sign that a nightly import has broken. The Google Ads integration page describes what it reads.

Frequently asked questions

Can I still upload offline conversions through the Google Ads API?

Only if your integration had legacy access. Integrations with no offline conversion uploads between 17 December 2025 and 15 June 2026 get a CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE error from UploadClickConversions. Everyone else can continue for now, but Google directs all offline conversion work to the Data Manager API.

Does the Data Manager API need a developer token?

No. The Data Manager API authenticates with OAuth using the https://www.googleapis.com/auth/datamanager scope and never required a developer token. Since 9 September 2026 the Google Ads API no longer uses developer tokens either.

What replaces partial failure in the Data Manager API?

Nothing directly. The Data Manager API uses a fast-fail model: if any field in an IngestEventsRequest fails validation, the whole request is rejected. Validate rows before you send them, and use validateOnly while testing.

Do I need the Data Manager API if I import conversions from Salesforce, HubSpot or Google Sheets?

Not if you use the built-in connections in Google Ads Data Manager, which Google supports for Google Sheets, HubSpot and Salesforce. The API migration matters for custom scripts, warehouse jobs and third-party tools that called the Google Ads API's UploadClickConversions.

How do I hash email addresses for the Data Manager API?

Trim whitespace and convert to lowercase. For gmail.com and googlemail.com addresses, also remove dots before the @ and anything from a plus sign onwards. Hash with SHA-256 and encode as hex or Base64, then declare that encoding in the request's encoding field.

Sources

  1. Changes to Offline Click Conversion Import Support in the Google Ads API, Google Ads Developer Blog
  2. Upgrade from the Google Ads API, Data Manager API documentation
  3. Field mappings, Data Manager API documentation
  4. Send events (Google Ads offline conversions), Data Manager API documentation
  5. Method: events.ingest, Data Manager API reference
  6. Format user data, Data Manager API documentation
  7. Release notes, Data Manager API
  8. Supported data sources, Google Ads Data Manager Help
Written byDimitrisTracking Whisper

Dimitris builds Tracking Whisper and writes about tracking, analytics and data from the work the agent does every day: GTM containers, GA4 properties, ad platforms and the numbers in between.

Give Whisper its first job.

The free plan covers one site. Start with a setup, an audit or a question about your numbers. No card needed.