LinkedIn Conversions API: How to Set It Up and Match Events
A technical guide to the LinkedIn Conversions API: why browser-side tracking loses conversions, the two setup paths, the identifiers that drive match rate, and how deduplication works.

Campaign Manager reports one conversion count for the month. The CRM shows a noticeably larger set of opportunities with LinkedIn sitting somewhere in the attribution path. Nobody in the room believes the smaller number. Everyone suspects it undercounts, nobody can prove by how much, and the budget conversation happens anyway.
That gap isn't a reporting bug. It's what you get when you ask a browser to carry a signal that browsers are steadily being redesigned to drop. The LinkedIn Conversions API is the way to send that signal differently: LinkedIn conversion tracking from your own server, straight to LinkedIn, with no browser in the middle.
I'm Louise Perrin, Executive Assistant at Moriah, a LinkedIn marketing agency and a LinkedIn Certified Marketing Partner. This page exists because the official documentation is scattered across a help center, a developer portal and a schema reference, each of which quietly assumes you've read the other two. What follows is the whole path in order: why browser-side tracking loses events, what has to be in place before you write a line of code, the two setup routes, the payload itself, how event matching decides whether any of it counts, and how deduplication against the Insight Tag actually behaves.
If you're the person who has to build this, the sections below run in implementation order.
What the LinkedIn Conversions API Is
LinkedIn gives you three ways to report a conversion: the Insight Tag (a JavaScript tag that fires in the visitor's browser), CSV uploads, and the Conversions API. The Conversions API, usually shortened to LinkedIn CAPI, lets your server stream conversion events straight to LinkedIn over HTTPS, wherever the conversion happened.
That last clause is the part that matters for B2B. A browser tag can only report what a browser witnessed. In a considered B2B purchase, the events worth counting often happen somewhere no browser goes: a sales development rep qualifies a lead three days later, a deal flips to closed-won in the CRM in week seven, a contract gets signed offline. A pixel sees none of that. The API can carry all of it.
Worth being precise about the goal, though. The Conversions API doesn't replace the Insight Tag, and LinkedIn doesn't recommend running it as a replacement. The documented recommendation is redundancy: send events through both and let LinkedIn throw out the duplicates. That only works if you build deduplication on purpose, which is the part most implementations get wrong, so it gets its own section below.
Why Browser-Side Tracking Loses Signal
Before deciding how much engineering time this deserves, it helps to know exactly what's eroding. The causes are structural, and none of them are reversing.
Cookie lifetime caps. Safari's Intelligent Tracking Prevention caps script-writable storage, which includes first-party cookies set through JavaScript, at seven days. If a visitor arrives from a link carrying tracking parameters and the cookie is then set client-side, that ceiling can fall to 24 hours. A B2B evaluation cycle runs for weeks or months. Seven days of identity doesn't cover it.
Ad blockers and tracking protection. Extensions and built-in protections can stop the tag loading at all, block the cookie it wants to write, or strip parameters off the landing page URL before your site ever sees them. The audience Moriah's clients care about, senior people in business services, manufacturing, transport and logistics, is often working on a managed corporate desktop, where protections like these may be switched on centrally rather than chosen by the person using the machine.
Consent management. If your banner is configured properly, a visitor who declines marketing cookies is a visitor the tag can't record. That's correct behavior, not a defect, and it means a portion of your traffic is structurally invisible to browser tracking.
Cross-device journeys. Someone taps your ad on a phone during a commute, researches you on a laptop two days later, then fills in the form there. To a cookie, that's two unrelated strangers. To your CRM, it's one contact with one email address.
Conversions that never touch a page. The single biggest one in B2B. Your real conversion isn't the form submission. It's the qualified lead, the booked meeting, the signed deal. Those are CRM state changes.
Add it up and the browser is reporting whichever slice of your funnel happens to be visible to it, and that slice shrinks every year. LinkedIn server-side tracking doesn't remove the constraints (a member still has to be matched, and members' privacy preferences still govern what's possible), but it does stop the loss being purely mechanical.
Prerequisites Before You Send Anything
Four prerequisites have to be in place before your first successful call. Get them wrong and you'll see errors that read like payload problems but are really permission or configuration problems.
1. Ad account access with a sufficient role. Whoever authorizes the integration needs one of these roles on the ad account: Account Billing Admin, Account Manager, Campaign Manager, or Creative Manager. A viewer-level role authenticates fine, then fails with a 403.
2. OAuth scopes. The access token needs `rwconversions` (read/write) to upload conversion data and manage conversion rules, plus `rads` (read) for ad account access. Standard three-legged OAuth authorization code flow.
3. A conversion rule per data source. Create it with `POST /rest/conversions`, setting `conversionMethod` to `CONVERSIONS_API`. Important: if you intend to send the same event through both the Insight Tag and the API, each source needs its own conversion rule, browser and server. One rule can't serve both.
4. Campaigns associated with the rule. Conversions are only attributed to campaigns the rule is associated with. Pass `autoAssociationType=ALLCAMPAIGNS` when you create the rule and it covers up to 200 campaigns in the account, active, paused and draft included. Pass `autoAssociationType=OBJECTIVEBASED` instead and it associates only campaigns whose objective maps to the conversion type, with no 200-campaign limit. Leave the parameter out and nothing is associated automatically, so you'll be associating campaigns yourself through the Campaign Conversions endpoint or directly in Campaign Manager.
Every request needs two headers: `X-Restli-Protocol-Version: 2.0.0` and `Linkedin-Version: {YYYYMM}`. The version header isn't optional, and LinkedIn sunsets old marketing API versions on a published schedule, so pin it somewhere you'll actually notice when it needs bumping.
A representative conversion rule looks like this:
```json { "name": "CAPI - Qualified Lead", "account": "urn:li:sponsoredAccount:5123456", "conversionMethod": "CONVERSIONSAPI", "postClickAttributionWindowSize": 90, "viewThroughAttributionWindowSize": 30, "attributionType": "LASTTOUCHBYCAMPAIGN", "type": "LEAD" } ```
A `201 Created` gives you back the rule ID. You'll need it in URN form, `urn:lla:llaPartnerConversion:{id}`, on every event you send.
The Two Setup Paths
Two routes get you to a working integration, and choosing between them is a resourcing decision more than a technical one.
Path 1: Direct API Integration
Your engineering team builds against the API itself. LinkedIn's own guidance says this needs developer resources and ongoing maintenance, and that implementation takes two to four weeks on average.
Go this way when the conversions you care about live in a system you control, when you need custom logic for which CRM state changes count as which conversion type, or when you want conversion values calculated from your own data rather than passed as flat numbers. It's also the only route that leaves you in full control of batching, retry behavior, and how identifiers get assembled per event.
The cost is real and it doesn't stop. Someone has to own the token refresh, the version header, the error handling, and the day a schema change breaks a field nobody has looked at in eight months.
Path 2: Partner Integration
LinkedIn maintains integrations that connect a source system without you building against the API at all. The named partners include Adobe, Dreamdata, Factors.ai, Funnel, Google Tag Manager, Hightouch, HubSpot, Make, Salesforce Data 360, Segment, Supermetrics, Tealium, Zapier, and Zoho Recruit. Zapier in turn opens connections to systems including HubSpot, Salesforce, Marketo, Active Campaign, Dynamics 365, Pipedrive, and Zoho Recruit.
LinkedIn describes this route as typically fast to implement, with fees potentially attached. For most established B2B companies it's the right answer: if your qualified leads already sit in HubSpot or Salesforce, and your definition of "qualified" is a stage value on a record, a partner connector will move that signal reliably without tying up an engineer for a month.
The honest trade-off is control. You inherit the connector's field mapping, its sync cadence, and its handling of identifiers. If your matching strategy depends on sending several identifiers per event, check what the connector actually passes before you assume it passes everything.
Whichever route you take, get the permissions you need from your customers before sharing their data with a third party, LinkedIn included. LinkedIn says this explicitly, and it's worth putting in front of legal counsel before launch rather than after.
The Payload: What You Actually Send
Events go to `POST https://api.linkedin.com/rest/conversionEvents`. A single event looks like this:
```json { "conversion": "urn:lla:llaPartnerConversion:123", "conversionHappenedAt": 1590739275000, "conversionValue": { "currencyCode": "USD", "amount": "50.0" }, "user": { "userIds": [ { "idType": "SHA256EMAIL", "idValue": "bad8677b6c86f5d308ee82786c183482a5995f066694246c58c4df37b0cc41f1" }, { "idType": "LINKEDINFIRSTPARTYADSTRACKINGUUID", "idValue": "df5gf5-gh6t7-ph4j7h-fgf6n1" } ], "userInfo": { "firstName": "john", "lastName": "mercer", "title": "operations director", "companyName": "example logistics", "countryCode": "US" } }, "eventId": "abc12345" } ```
The fields that cause the most trouble:
- `conversionHappenedAt` is a Unix timestamp in milliseconds, and it has to fall inside the past 90 days. Send anything older and you get a 400 with `INVALIDCONVERSIONTIMEFIELDVALUE`, telling you conversion time should be within 90 days. If your CRM sync backfills history on its first run, filter it.
- `user.userIds` is required, and this one trips people up. Even when you're identifying the person some other way, through `lead`, `externalIds` or `userInfo`, you still have to include `userIds` as an empty list (`[]`). Omit the key entirely and you get a 422.
- `conversionValue` is optional but worth populating. Without it you can report conversion counts; with it you can report return on ad spend. LinkedIn's own best-practice guidance is to pass a value, static or dynamic.
- `eventId` is what makes deduplication possible. More on that below.
- `lead`, if you use it, has to be a valid URN shaped like `urn:li:leadGenFormResponse:...`. A bare ID gets you a 422 about an invalid URN prefix.
A successful call returns `201 Created`.
Event Matching: The Part That Decides Everything
Sending an event is easy. Getting it matched to a LinkedIn member is the whole game, because only matched events can be used for attribution and optimization. An event LinkedIn receives but can't resolve to a profile is, as far as reporting goes, an event that never happened.
Your request has to contain at least one of: `SHA256EMAIL`, `LINKEDINFIRSTPARTYADSTRACKINGUUID`, `ACXIOMID`, `PLAINTEXTIPADDRESS`, `GOOGLEAID`, first name and last name together, `externalIds`, or `lead`. Miss all of them and you get a 400 with `INVALIDUSERIDENTIFICATIONFIELDVALUE`.
But that requirement is a floor, not a target. LinkedIn's guidance is blunt: send multiple user identifiers whenever you have them, because match rate climbs with the number of signals. Two of them carry most of the weight in B2B.
Hashed email (`SHA256_EMAIL`). The business email address you already hold in your CRM, hashed with SHA-256 before it leaves your systems. It's the strongest single identifier most companies own, and it's why CRM-sourced conversions match better than anything a browser can offer.
The LinkedIn first-party click ID (`LINKEDIN_FIRST_PARTY_ADS_TRACKING_UUID`). This is the `lifatid` value LinkedIn appends to your ad landing page URLs when enhanced conversion tracking is enabled on the Insight Tag. Capture it by parsing it out of the landing page URL, or read it from the cookie if the Insight Tag is installed, store it against the record, and send it with the event later. Paired with the hashed email, it gives LinkedIn two independent ways to resolve the same person instead of one.
Everything else is supporting evidence. `userInfo` (first name, last name, job title, company name, country code) helps LinkedIn settle ambiguous matches. `externalIds` carries your own identifier through for your own reconciliation. `PLAINTEXTIPADDRESS` and `GOOGLE_AID` are there for the cases where you have them.
So the practical instruction is this: build the event payload from the widest set of identifiers the record holds, not the minimum the API will accept. The gap between a one-identifier and a two-identifier implementation shows up directly in Campaign Manager, where a conversion rule flagged Low Match Rate underneath its Active status is telling you the events arrived and mostly failed to resolve.
Deduplication Against the Insight Tag
Run both the Insight Tag and the API, as LinkedIn recommends, and you'll send some conversions twice. LinkedIn Insight Tag deduplication is how the same event arriving from both sources gets counted once.
The rule is simple, and the direction surprises people:
If LinkedIn receives an Insight Tag event and a Conversions API event from the same account with the same `eventId`, it discards the Conversions API event and counts the Insight Tag event.
The browser event wins. Your server event is the safety net, not the primary record.
Three pieces make it work:
- A separate conversion rule for each data source. Browser and server each get their own. Both show up in reporting, named something like "Insight Tag demo request" and "CAPI demo request".
- A shared `eventId` that is genuinely unique. Generate the ID in the browser, then carry it through to the server so the matching server event goes out with the same value. Use something already unique in your system, an order ID or a form submission ID, rather than inventing a scheme.
- The ID passed correctly on the browser side. For page-load conversions with a manual Insight Tag install, assign it to the global window property before the base code runs:
```javascript window.linkedinevent_id = "very-unique-page-load-event-id"; ```
For event-specific conversions, pass it into the tracking call:
```javascript window.lintrk("track", { conversionid: 12345, eventid: "ABCDppSv6kBwg" }); ```
Running the Insight Tag through Google Tag Manager? The version 2 community template has an Event ID field. Push the ID to the data layer before the GTM script executes, then configure a variable to read it into that field:
```javascript window.dataLayer = window.dataLayer || []; window.dataLayer.push({ eventId: 'ABCDppSv6kBwg' }); ```
For event-specific conversions through GTM, push the event and the ID together on the user action:
```javascript window.dataLayer.push({ event: 'contact', eventId: 'ABCDppSv6kBwg' }); ```
The GTM version 2 template doesn't support image pixel conversions, but you can still pass an event ID by configuring a custom image tag with the value in the URL.
How to check it's working. Open the conversion breakdown in Campaign Manager and look at both rules. Both should be there, and the Insight Tag rule should carry the higher count. If the API count is higher, or the two look unrelated, your event IDs aren't lining up and you're double-counting.
Sending at Volume Without Getting Throttled
Once the integration is live and a CRM sync starts pushing history, volume becomes the next problem.
- Batch. Set the `X-RestLi-Method` header to `BATCH_CREATE` and send up to 5,000 events in one request, wrapped in an `elements` array. LinkedIn recommends batching specifically to avoid rate-limit throttling.
- Respect the limits. A member access token is capped at 600 requests per minute and 500,000 requests per day. Batching is what keeps a large backfill inside those numbers.
- Handle batch failures properly. One invalid record fails the whole batch. The 400 response includes a `batchIndex` pointing at the offending array element, and you have to correct the data and resubmit the entire payload. Build for that: validate locally before sending, and log the batch so you can replay it.
- Send in real time where you can. LinkedIn's best-practice guidance is to stream events as they happen, so they can be attributed and used while they still matter. A nightly job works. A real-time stream works better.
If a large batch keeps failing and nothing obvious explains it, LinkedIn's own suggestion is to shrink the batch and retry.
Errors You Will Actually See
| Status | What it means |
|---|---|
| 400 BAD_REQUEST | Syntax or validation failure. The message names the field. |
| 401 EMPTY_ACCESS_TOKEN | No OAuth token on the request. |
| 403 USER_NOT_AUTHORIZED | The authorizing user lacks access to the ad account, or the token is missing `rw_conversions` or `r_ads`. |
| 400 Invalid Conversion time | `conversionHappenedAt` is outside the past 90 days. |
| 400 Invalid user identification | No acceptable identifier in the payload, or one was sent as an empty string. |
| 400 Conversion marked as deleted | You are streaming to a disabled conversion rule. Check `enabled` is true. |
| 422 conversionHappenedAt required | The field is missing entirely. |
| 422 user/userIds required | `userIds` is absent. Send `[]` if identifying by other means. |
What a Working Integration Unlocks
Measurement is why most companies build this, but it isn't the only return.
Qualified leads optimization. Send qualified lead data through the API using conversion rules with the type `QUALIFIED_LEAD`, and LinkedIn can optimize delivery toward the prospects most likely to become qualified, subject to members' preferences. This works through both direct and partner integrations. The operational constraints matter: qualified lead data has to reach LinkedIn within 30 days to be included in optimization, the goal requires a two-week learning phase, and LinkedIn recommends sharing five or more qualified leads within two weeks to get through it. Sooner beats later in every case.
Retargeting audiences from conversion signal. Events that match a member can build a Matched Audience from your Conversions API data, usable for inclusion or exclusion once it reaches the minimum audience size of 300 members. Your CRM's definition of a serious buyer becomes a targetable audience.
Source data for predictive audiences. That same matched audience can seed a predictive audience, where LinkedIn's modelling looks for prospects likely to behave like the people already in it. Conversion is one of the selectable sources, alongside contact list, company list, lead gen form and retargeting, and you can pick only one source per predictive audience.
Where This Fits in a LinkedIn Business Engine
A short note on scope, because measurement infrastructure is easy to mistake for a strategy.
LinkedIn Ads is one of the three areas Moriah works in, alongside personal branding and targeted outreach. We run all three together, always, because that's how LinkedIn actually performs against a business objective beyond pure awareness. It isn't a menu. A client who publishes content but activates nothing around it gets no business. A client who runs targeted outreach with no content behind it gets no business either. Ads amplify an engine that already exists. They don't substitute for one.
The Conversions API sits underneath all of that as instrumentation. It tells you which campaigns produced qualified pipeline rather than which produced form fills, and it feeds LinkedIn a definition of success that comes from your CRM instead of from a page load. Both are worth having. Neither decides what you should be running, who you should be reaching, or what your executives ought to be saying in public.
Moriah is a LinkedIn Certified Marketing Partner, and we handle strategy, content production and execution in-house for established B2B companies, on a monthly retainer with no minimum term. If you want to talk through what your LinkedIn measurement should look like, and what it would tell you that your current reporting doesn't, book a call.
Frequently Asked Questions
What is the LinkedIn Conversions API? The LinkedIn Conversions API, sometimes called LinkedIn CAPI, lets you stream conversion events from your own server directly to LinkedIn instead of relying on a browser tag. You use it to measure campaign performance and improve attribution, data reliability and delivery, wherever the conversion happened.
Does the Conversions API replace the LinkedIn Insight Tag? No. LinkedIn recommends running both, for increased reliability and a fuller view of the customer journey, then using deduplication so events arriving from both sources are counted once. The Insight Tag also drives website retargeting audiences, which the API doesn't replace.
How does deduplication between the Insight Tag and the Conversions API work? You create a separate conversion rule for each data source and send the same unique `eventId` from the browser and from your server. When LinkedIn receives both events with the same event ID from the same account, it discards the Conversions API event and counts the Insight Tag event in campaign reporting.
What identifiers can I send with a conversion event? Each request needs at least one of: SHA256-hashed email, the LinkedIn first-party ads tracking UUID (`lifatid`), an Acxiom ID, a plaintext IP address, a Google advertising ID, first and last name together, external IDs, or a lead URN. Sending several identifiers per event raises your match rate.
How far back can I send conversion events? The `conversionHappenedAt` timestamp has to fall inside the past 90 days. Events with older timestamps get rejected with a validation error, so any historical backfill needs filtering before you send it.
What OAuth permissions does the Conversions API need? The access token needs `rwconversions` for read and write access to conversion data, and `rads` for read access to the ad account. The authorizing user must hold an Account Billing Admin, Account Manager, Campaign Manager, or Creative Manager role on the ad account.
How many conversion events can I send in one request? Up to 5,000 events in a single batch request, using the `X-RestLi-Method: BATCH_CREATE` header. A member access token is limited to 600 requests per minute and 500,000 requests per day, so batching is how you stay inside those limits during a large sync.
Do I need a developer to set up the LinkedIn Conversions API? Not necessarily. A direct API integration needs developer resources and ongoing maintenance, and takes two to four weeks on average. A partner integration through tools such as HubSpot, Salesforce Data 360, Segment, Zapier or Google Tag Manager is typically faster to implement, though fees may apply.
Why is my conversion rule showing a low match rate? A Low Match Rate flag beneath the Active status means your events are arriving but aren't resolving to LinkedIn profiles reliably. The usual cause is too few identifiers per event. Adding the hashed email and the `lifatid` click ID together is the most direct fix.
Can I use Conversions API data for targeting, not just reporting? Yes. Matched conversion events can build a Matched Audience once it reaches the minimum size of 300 members, usable for inclusion or exclusion in campaigns. That audience can also serve as the source for a predictive audience, and qualified lead events can drive the qualified leads optimization goal.