Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
Data Manager API Event Ingestion
Implementation Workflow
Prerequisites
- Authentication & Library Installation: If you need to set up access to
the Data Manager API or install the client and utility libraries, refer to the data-manager-api-setup skill.
Step 1: Identify Use Case & Read Documentation
- Determine Destination Account Type: [CRITICAL] If it's not
explicitly stated, STOP and CLARIFY with the user where the data is being sent (e.g., Google Ads, Floodlight, Google Analytics) BEFORE generating any code. Do not assume Google Ads by default. This maps to the account_type field of the operating_account in the Destination, and also determines valid event identifiers and requirements.
- Read Documentation: [CRITICAL] Follow the
Send events guide to implement the integration, as steps for configuring and sending the request may vary between destinations.
Step 2: Retrieve Code Sample
[!IMPORTANT] If writing or updating an ingestion script, ALWAYS retrieve the relevant code sample to use as a reference:
| Language | Sample |
|---|---|
| Python | `ingest_events.py` |
| Java | `IngestEvents.java` |
| PHP | `ingest_events.php` |
| Node | `ingest_events.ts` |
| .NET | `IngestEvents.cs` |
Step 3: Retrieve Migration Guides
[!IMPORTANT] If refactoring code to upgrade from another Google API, ALWAYS extract the full contents of the relevant field mapping guide.
Google Ads
- Google Ads API Offline Conversions:
Google Ads Offline Conversions Migration Field Mappings
- Google Ads API Store Sales:
Google Ads Store Sales Migration Field Mappings
Google Analytics
- Measurement Protocol (Google Analytics):
Google Analytics Measurement Protocol Migration Field Mappings
Campaign Manager 360 (CM360)
- Campaign Manager 360 API Offline Conversions:
Campaign Manager 360 Offline Conversions Migration Field Mappings
Step 4: Implementation
Implement the ingestion logic using the following checkpoints:
- [ ] Initialize Client: Instantiate the Data Manager client
(IngestionServiceClient).
- [ ] Define Destinations: Build the
Destinationobject using the
product_destination_id and the appropriate account configurations: operating_account (target account receiving data), login_account (if authenticating using a manager account or a data partner account), and linked_account (if you're a data partner accessing the account via a partner link to a manager account). STRONGLY RECOMMENDED: Refer to the Configure destinations and headers guide for more details on configuring destinations.
- [ ] Prepare Event Data: Use the utility library helpers to format and
normalize user identifiers correctly.
- [ ] Construct Payload: Build the request payload
(IngestEventsRequest) containing the destinations, event records, and consent permissions.
- [ ] Support Validation: Support sending the
validate_onlyboolean
option on the IngestEventsRequest to allow developers to validate schemas without actually uploading data.
- [ ] Send Request: Execute
ingest_eventsand record the returned
request_id for later diagnostics.
- [ ] Check for Ingestion Warnings: If any non-required field had a
validation failure, the response from ingest_events will also include field_warnings, a list of FieldWarning objects detailing the issues.
- [ ] Retrieve Request Status: Check the status of the ingestion request
using diagnostics. Since request processing is asynchronous, a successful ingestion response (HTTP 200 OK returning a request_id) only indicates the payload was received. To check if the records actually succeeded, partially succeeded, or failed to process, query the client.retrieve_request_status endpoint using the request_id. Skipping this step is a common user mistake.
Formatting
- Fetch the Format user data
guide and use that as the source of truth for formatting and normalization rules.
- Use the utility library to format, hash, and encrypt user data
(emails, phone numbers, addresses).
Python Example:
from google.ads.datamanager_util import Formatter
from google.ads.datamanager_util.format import Encoding
formatter: Formatter = Formatter()
processed_email: str = formatter.process_email_address(
email, Encoding.HEX
)Critical Gotchas
- Format
product_destination_idas a numeric string. It is NOT a resource
name path.
- Format
event_timestampstrictly in RFC 3339 format. Use the SDK's typed
timestamp object instead of a raw string where available.
- Nest click identifiers (
gclid,gbraid,wbraid) inside the
ad_identifiers block, not directly on the base event payload.
- The enum values for
ConsentStatusareCONSENT_GRANTEDand
CONSENT_DENIED. Do not use the values GRANTED and DENIED.
- Note that
consentcan be set globally on theIngestEventsRequestor on
individual Events.
- Verify that
UserIdentifierusesemail_addressandphone_number.
Do not use the Google Ads API fields hashed_email and hashed_phone_number.
- Ensure the currency field on the event is named
currency, not
currency_code.
- Do not call the diagnostics endpoint (
retrieve_request_status) if
validate_only is set to true.
Error Handling & Troubleshooting
Inspecting Error Payloads & Ingestion Warnings
[!IMPORTANT] Refer to Understand API Errors for a detailed guide on how to understand the structure of errors and warnings returned by the API.
Retrieving Request Status (Diagnostics)
Periodically poll for status using exponential backoff, starting at least 30 minutes after sending the IngestEventsRequest.
- Call
client.retrieve_request_statususing
RetrieveRequestStatusRequest(request_id=...).
- Loop through
request_status_per_destinationin the response to inspect
each target's request_status.
- If processing is complete and
request_statusisSUCCESS,
PARTIAL_SUCCESS, or FAILED, inspect diagnostic values:
- Event Record Counts: Check
events_ingestion_status.record_count
(includes both success and failure).
- Error Details: If status is
FAILEDorPARTIAL_SUCCESS, inspect
each error's reason and record_count under error_info.error_counts.
- Warning Details: Inspect each warning's
reasonandrecord_count
under warning_info.warning_counts (even if the destination status is SUCCESS).

