Conversions
Offline and enhanced conversions via the Data Manager API
Conversions API
Import offline conversions (deal closed, lead qualified, subscription renewed) into Google Ads via the Data Manager API ingestEvents method, the endpoint Google recommends for all new integrations as of December 2025 (replacing the legacy uploadClickConversions). Zernio uses the Google Ads account you already connected; no additional OAuth, no developer token to apply for.
The same endpoint handles both attribution paths:
- Click attribution, include a
gclid,gbraid, orwbraidfrom the originating ad click - Enhanced Conversions for Leads, include hashed email / phone when no click ID is available
PII is SHA-256 hashed server-side. For @gmail.com / @googlemail.com addresses, we strip dots and +suffix from the local part before hashing per Google's spec so john.doe+promo@gmail.com matches johndoe@gmail.com.
Discover available conversion actions
const { data } = await zernio.conversions.listConversionDestinations({
path: { accountId: 'ACCOUNT_ID' },
});data = client.conversions.list_conversion_destinations(account_id="ACCOUNT_ID")curl "https://zernio.com/api/v1/accounts/ACCOUNT_ID/conversion-destinations" \
-H "Authorization: Bearer YOUR_API_KEY"Returns every enabled conversion action across accessible customers. The id is the conversion action resource name (customers/{customerId}/conversionActions/{id}). The type field reflects the action's category (PURCHASE, LEAD, SIGN_UP, etc.), Google locks the event type to the conversion action, not the per-event eventName.
Send a conversion event
const result = await zernio.conversions.sendConversions({ body: {
accountId: 'ACCOUNT_ID',
destinationId: 'customers/1234567890/conversionActions/987654321',
consent: { adUserData: 'GRANTED', adPersonalization: 'GRANTED' }, // required for EEA/UK
events: [{
eventName: 'Purchase',
eventTime: Math.floor(Date.now() / 1000),
eventId: 'order_abc_123', // dedup, mapped to transactionId
value: 129.99,
currency: 'USD',
user: {
email: 'customer@example.com',
phone: '+14155551234',
clickIds: { gclid: 'EAIaIQobChMI...' },
},
}],
}});result = client.conversions.send_conversions(
account_id="ACCOUNT_ID",
destination_id="customers/1234567890/conversionActions/987654321",
consent={"adUserData": "GRANTED", "adPersonalization": "GRANTED"},
events=[{
"eventName": "Purchase",
"eventTime": int(time.time()),
"eventId": "order_abc_123",
"value": 129.99,
"currency": "USD",
"user": {
"email": "customer@example.com",
"phone": "+14155551234",
"clickIds": {"gclid": "EAIaIQobChMI..."},
},
}],
)curl -X POST "https://zernio.com/api/v1/ads/conversions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "ACCOUNT_ID",
"destinationId": "customers/1234567890/conversionActions/987654321",
"consent": { "adUserData": "GRANTED", "adPersonalization": "GRANTED" },
"events": [{
"eventName": "Purchase",
"eventTime": 1744732800,
"eventId": "order_abc_123",
"value": 129.99,
"currency": "USD",
"user": {
"email": "customer@example.com",
"phone": "+14155551234",
"clickIds": { "gclid": "EAIaIQobChMI..." }
}
}]
}'EEA / UK consent
Google enforces strict consent signaling for European users under the February 2026 Data Manager restrictions. Pass consent at the request root with adUserData and adPersonalization set to GRANTED or DENIED. Omit the field for non-EEA requests where you don't have consent data; Google applies region defaults.
Deduplication
Pass a stable eventId on every event, Zernio maps it to Google's transactionId so repeated uploads of the same conversion are deduped.
Batching + reporting
Up to 2,000 events per request (Zernio chunks larger batches automatically). Conversions take up to 3 hours to appear in Google Ads reports. The response carries a requestId you can reference if conversions don't appear as expected.