Conversions API
Conversion rules, server-side events, and attribution read-back
Conversions API
Stream offline conversion events (deal closed, lead qualified, trial converted, purchase) back to LinkedIn through the same unified /v1/ads/conversions endpoint you already use for Meta and Google. Zernio uses the LinkedIn account you already connected, no separate Conversions API access token to generate from Campaign Manager. PII is SHA-256 hashed server-side per LinkedIn's spec before anything leaves your server (externalIds are passed through as plaintext per LinkedIn's requirement).
Reconnect required for LinkedIn accounts connected before Zernio shipped Conversions API support. LinkedIn does not silently upgrade existing OAuth grants with the new rw_conversions scope. Accounts that lack it return 403 with code linkedin_reconnect_required; pass the user back through the LinkedIn connect flow once and they're set.
Discover available conversion rules
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 CONVERSIONS_API rule across every sponsored ad account the connected token can access. Each destination carries an adAccountId you'll pass back on subsequent CRUD calls.
Create a new conversion rule
LinkedIn's conversion rule binds an event type (LEAD, PURCHASE, ADD_TO_CART, etc.) to the destination. By default the new rule is auto-associated with every campaign in the ad account; pass autoAssociationType: "NONE" to opt out and manage associations explicitly via /associations.
const dest = await zernio.conversions.createConversionDestination({
path: { accountId: 'ACCOUNT_ID' },
body: {
adAccountId: '517258773', // numeric or "urn:li:sponsoredAccount:..."
name: 'Trial activation',
type: 'Lead', // unified name OR LinkedIn enum (e.g. "QUALIFIED_LEAD")
attributionType: 'LAST_TOUCH_BY_CAMPAIGN',
postClickAttributionWindowSize: 30,
viewThroughAttributionWindowSize: 7,
},
});dest = client.conversions.create_conversion_destination(
account_id="ACCOUNT_ID",
ad_account_id="517258773",
name="Trial activation",
type="Lead",
attribution_type="LAST_TOUCH_BY_CAMPAIGN",
post_click_attribution_window_size=30,
view_through_attribution_window_size=7,
)curl -X POST "https://zernio.com/api/v1/accounts/ACCOUNT_ID/conversion-destinations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"adAccountId": "517258773",
"name": "Trial activation",
"type": "Lead",
"attributionType": "LAST_TOUCH_BY_CAMPAIGN",
"postClickAttributionWindowSize": 30,
"viewThroughAttributionWindowSize": 7
}'Send a conversion event
const result = await zernio.conversions.sendConversions({ body: {
accountId: 'ACCOUNT_ID',
destinationId: '25639412', // conversion rule id from listConversionDestinations
events: [{
eventName: 'Lead', // informational only — rule type is bound to destination
eventTime: Math.floor(Date.now() / 1000),
eventId: 'order_abc_123',
value: 42.50,
currency: 'USD',
user: {
email: 'customer@example.com',
firstName: 'Jane',
lastName: 'Doe',
country: 'US',
clickIds: {
// Optional: improves match rate. Capture from li_fat_id on landing-page URLs
// after enabling enhanced conversion tracking on the LinkedIn Insight Tag.
li_fat_id: 'AQH...',
},
},
}],
}});result = client.conversions.send_conversions(
account_id="ACCOUNT_ID",
destination_id="25639412",
events=[{
"eventName": "Lead",
"eventTime": int(time.time()),
"eventId": "order_abc_123",
"value": 42.50,
"currency": "USD",
"user": {
"email": "customer@example.com",
"firstName": "Jane",
"lastName": "Doe",
"country": "US",
"clickIds": {"li_fat_id": "AQH..."},
},
}],
)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": "25639412",
"events": [{
"eventName": "Lead",
"eventTime": 1744732800,
"eventId": "order_abc_123",
"value": 42.50,
"currency": "USD",
"user": {
"email": "customer@example.com",
"firstName": "Jane",
"lastName": "Doe",
"country": "US",
"clickIds": { "li_fat_id": "AQH..." }
}
}]
}'Standard event names
Purchase, Lead, CompleteRegistration, AddToCart, InitiateCheckout, AddPaymentInfo, Subscribe, StartTrial, ViewContent, Search, Contact, SubmitApplication, Schedule. The unified name is informational on LinkedIn — the rule's type (set at create time) is what determines the LinkedIn-side conversion category.
Mapping unified names → LinkedIn type enum
| Unified | |
|---|---|
Purchase | PURCHASE |
Lead | LEAD |
CompleteRegistration | COMPLETE_SIGNUP |
AddToCart | ADD_TO_CART |
InitiateCheckout | START_CHECKOUT |
AddPaymentInfo | ADD_BILLING_INFO |
Subscribe | SUBSCRIBE |
StartTrial | START_TRIAL |
ViewContent | VIEW_CONTENT |
Search | SEARCH |
Contact | CONTACT |
SubmitApplication | SUBMIT_APPLICATION |
Schedule | SCHEDULE |
You can also pass a LinkedIn enum value directly (e.g. "QUALIFIED_LEAD", "OUTBOUND_CLICK") for types not in the unified set.
User identifiers
LinkedIn requires at least one of: SHA-256-hashed email, a LinkedIn first-party click ID (li_fat_id), an Acxiom or Oracle MOAT identifier, OR userInfo containing both firstName and lastName. Send as many as you have, hashed identifiers materially improve match rate.
Deduplication
Pass a stable eventId on every event. If you also fire the LinkedIn Insight Tag with the same event ID, LinkedIn discards the Conversions API copy and counts only the Insight Tag event. Aligns with LinkedIn's documented dedup behavior.
Campaign associations
By default createConversionDestination auto-associates the new rule with every active, paused, and draft campaign in the ad account (autoAssociationType: "ALL_CAMPAIGNS"). Auto-association is one-shot at create time, campaigns added later need explicit association:
const result = await zernio.conversions.addConversionAssociations({
path: { accountId: 'ACCOUNT_ID', destinationId: '25639412' },
body: {
adAccountId: '517258773',
campaignIds: ['337643194', '345396555'],
},
});result = client.conversions.add_conversion_associations(
account_id="ACCOUNT_ID",
destination_id="25639412",
ad_account_id="517258773",
campaign_ids=["337643194", "345396555"],
)curl -X POST "https://zernio.com/api/v1/accounts/ACCOUNT_ID/conversion-destinations/25639412/associations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "adAccountId": "517258773", "campaignIds": ["337643194", "345396555"] }'Returns a per-campaign succeeded / failed map so you can retry only the rows that didn't take.
Attribution metrics
Read conversion attribution back from LinkedIn's adAnalytics endpoint, pivoted by date:
const { data } = await zernio.conversions.getConversionMetrics({
path: { accountId: 'ACCOUNT_ID', destinationId: '25639412' },
query: {
adAccountId: '517258773',
startDate: '2026-04-01',
endDate: '2026-04-30',
granularity: 'DAILY',
},
});data = client.conversions.get_conversion_metrics(
account_id="ACCOUNT_ID",
destination_id="25639412",
ad_account_id="517258773",
start_date="2026-04-01",
end_date="2026-04-30",
granularity="DAILY",
)curl "https://zernio.com/api/v1/accounts/ACCOUNT_ID/conversion-destinations/25639412/metrics?adAccountId=517258773&startDate=2026-04-01&endDate=2026-04-30&granularity=DAILY" \
-H "Authorization: Bearer YOUR_API_KEY"Returns externalWebsiteConversions, externalWebsitePostClickConversions, externalWebsitePostViewConversions, conversionValueInLocalCurrency, qualifiedLeads, costInLocalCurrency per date bucket.
LinkedIn's retention rules apply: granularity=DAILY covers the last ~6 months only; MONTHLY/YEARLY extends to 24 months; granularity=ALL with a range > 6 months auto-rounds to month boundaries.
Soft-delete
LinkedIn doesn't expose a hard-delete on conversion rules. DELETE /v1/accounts/{accountId}/conversion-destinations/{destinationId}?adAccountId=... flips enabled: false (the same operation Campaign Manager's UI delete performs); the rule remains fetchable as status: 'inactive'.
Limits
- 5,000 events per
sendConversionscall (LinkedIn'sBATCH_CREATEcap) - 600 requests/min and 300,000 requests/day per token (LinkedIn-side)
conversionHappenedAtmust be within the last 90 days- 365-day attribution windows are only valid for
LEAD,PURCHASE,ADD_TO_CART,QUALIFIED_LEAD,SUBMIT_APPLICATION