LinkedIn Conversions API for B2B SaaS: signup, demo, qualified and closed-won events
By Marc Stevens · October 14, 2026
Status, honestly: server-track-lab does not forward events to LinkedIn today. Meta Conversions API delivery is live. Google is coming soon. LinkedIn is on the roadmap. Nothing you send to /api/v1/track reaches LinkedIn. This guide shows how to call LinkedIn's Conversions API yourself, while sending the same event_id and user data to server-track-lab for Meta, so your B2B event model stays the same everywhere.
LinkedIn is where a lot of B2B SaaS budget goes, and most of the conversions that matter (qualified, closed won) happen in a CRM, not a browser. LinkedIn's Conversions API lets you "stream conversion events from their server to LinkedIn". Background: server-side vs browser pixels, Meta CAPI dedup with event_id, and sending form and CRM conversions server-side.
How LinkedIn's model differs from Meta's
Meta takes an event name per event. LinkedIn takes a conversion rule URN per event. Per LinkedIn's docs you must:
- Create a conversion rule (
POST /rest/conversions) withconversionMethod: "CONVERSIONS_API"for each conversion type you want to track. - Associate campaigns with the rule. Only associated campaigns can be credited.
- Stream events to
POST https://api.linkedin.com/rest/conversionEvents.
Calls need an OAuth token with rw_conversions and r_ads, plus the headers Linkedin-Version: YYYYMM and X-Restli-Protocol-Version: 2.0.0. LinkedIn notes Marketing version 202511 sunsets on November 16, 2026, so pin a current version.
Map B2B stages to conversion rules
Keep sending the same event_name values you send us (from our src/eventMap.ts). Create one LinkedIn rule per stage and keep a lookup from our name to the rule URN.
Our event_name | Meta receives (live) | LinkedIn rule type (you create) |
|---|---|---|
signup | CompleteRegistration | SIGN_UP |
demo_booked | Schedule | LEAD or OTHER (our choice: no demo/appointment type in the docs we checked) |
qualified | Lead + event_stage: "qualified" | QUALIFIED_LEAD, or MARKETING_QUALIFIED_LEAD / SALES_QUALIFIED_LEAD (version 202608+) |
closed_won | Purchase (value + currency) | PURCHASE, with conversionValue |
The types above are the ones named on LinkedIn's conversion tracking and Conversions API pages. Creating a rule looks like this (from LinkedIn's sample, with our names):
curl -X POST 'https://api.linkedin.com/rest/conversions?autoAssociationType=ALL_CAMPAIGNS' \
-H "Authorization: Bearer $LI_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Linkedin-Version: 202609' \
-H 'X-Restli-Protocol-Version: 2.0.0' \
--data '{
"name": "CAPI closed_won",
"account": "urn:li:sponsoredAccount:5123456",
"conversionMethod": "CONVERSIONS_API",
"postClickAttributionWindowSize": 90,
"viewThroughAttributionWindowSize": 30,
"attributionType": "LAST_TOUCH_BY_CAMPAIGN",
"type": "PURCHASE"
}'
The new rule ID comes back in the id field and the x-restli-id header; your events reference it as urn:lla:llaPartnerConversion:{id}. Linkedin-Version: 202609 is just an example value.
User identifiers LinkedIn accepts
From LinkedIn's Conversions API schema, user.userIds takes {idType, idValue} pairs:
SHA256_EMAIL: the email "converted to lower case, without any whitespaces and then hashed in SHA256 format", HEX-encoded.LINKEDIN_FIRST_PARTY_ADS_TRACKING_UUID: theli_fat_idclick ID (see below).PLAINTEXT_IP_ADDRESSorSHA256_IP_ADDRESS: IPv4 only.ACXIOM_ID(LiveRamp) andGOOGLE_AID(Android ad ID).
You can also send userInfo (firstName, lastName, companyName, title, countryCode; hashed first/last name from version 202609), externalIds, or a Lead Gen Form lead URN. If you send only those, userIds must be an empty list []. LinkedIn says to send multiple identifiers where you have them, because only matched events are used for attribution and optimization.
Normalising email in Node (matches LinkedIn's rule: lower case, no whitespace, SHA-256 hex):
import { createHash } from "node:crypto";
const sha256Email = (e) => createHash("sha256").update(e.toLowerCase().replace(/\s+/g, "")).digest("hex");
sha256Email(" Laura@Example.com ");
// c1d571b0b31d8cb221b46a1cf715146322f10bade76fb1095169c40a2798a503
Capturing li_fat_id
LinkedIn's Enabling Click IDs page says that once enhanced conversion tracking is on for your Insight Tag, LinkedIn appends li_fat_id to landing page URLs on ad clicks. Read it from the URL (and pass it as a hidden form field) or from the cookie when the Insight Tag is installed:
const liFatId = new URLSearchParams(location.search).get("li_fat_id");
Store it with the lead in your CRM so later stages (qualified, closed won) can still send it. Our /track schema has no li_fat_id field, so keep it on your side and send it to LinkedIn only.
Deduplication with the Insight Tag
LinkedIn's deduplication doc recommends sending events through both the Insight Tag and the Conversions API. What it says:
- Create a conversion rule for each data source (one browser rule, one server rule).
- Send the same
eventIdfrom the browser and the server. - If LinkedIn gets an Insight Tag event and a CAPI event from the same account with the same
eventId, it discards the CAPI event and counts only the Insight Tag one. Reporting shows both rules; the Insight Tag rule typically has the higher count when dedup works.
In the browser, for an event-specific conversion:
window.lintrk("track", { conversion_id: 12345, event_id: "demo_7f3a9c" });
For page-load conversions, set window._linkedin_event_id = "demo_7f3a9c"; before the Insight Tag base code. The doc also covers the image pixel (&eventId= on the URL) and Google Tag Manager. The deduplication page does not state a time window; we couldn't confirm one.
Use one ID everywhere: the same string as our event_id, LinkedIn's eventId on server and browser, and Meta's eventID in fbq. Our event_id allows letters, digits and . _ : - up to 128 characters.
One event, two destinations
Here is a closed_won sent to server-track-lab (for Meta) and to LinkedIn directly, sharing the ID and email.
1. To server-track-lab (fields per our src/schema.ts; we hash the email for Meta):
curl https://server-track-lab.pages.dev/api/v1/track \
-H "Authorization: Bearer $SST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_name": "closed_won",
"event_id": "hs_deal_1246965:closed_won",
"timestamp": "2026-10-14T15:02:11Z",
"action_source": "system_generated",
"value": 4800,
"currency": "CAD",
"user": { "email": "laura@example.com", "external_id": "crm_contact_1246965" }
}'
2. To LinkedIn directly (LinkedIn's documented format; you hash the email):
curl -X POST 'https://api.linkedin.com/rest/conversionEvents' \
-H "Authorization: Bearer $LI_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Linkedin-Version: 202609' \
-H 'X-Restli-Protocol-Version: 2.0.0' \
--data '{
"conversion": "urn:lla:llaPartnerConversion:104004",
"conversionHappenedAt": 1791990131000,
"conversionValue": { "currencyCode": "CAD", "amount": "4800.0" },
"user": {
"userIds": [
{ "idType": "SHA256_EMAIL", "idValue": "c1d571b0b31d8cb221b46a1cf715146322f10bade76fb1095169c40a2798a503" },
{ "idType": "LINKEDIN_FIRST_PARTY_ADS_TRACKING_UUID", "idValue": "<li_fat_id stored with the lead>" }
],
"externalIds": ["crm_contact_1246965"]
},
"eventId": "hs_deal_1246965:closed_won"
}'
Notes from LinkedIn's docs: conversionHappenedAt is epoch milliseconds and must be within the past 90 days; amount is a decimal string; success is 201 Created. Batches (header X-RestLi-Method: BATCH_CREATE) take up to 5,000 events, and one invalid record fails the whole batch. Rate limits are 600 requests per minute and 500,000 per day per member token. The 104004 rule ID above is a placeholder.
Compare the windows: Meta's event_time must be within 7 days of sending; LinkedIn's within 90 days. A closed_won 30 days after the click can still go to LinkedIn if you send it from the CRM, but it must reach Meta within 7 days of the stage change.
Consent notes
The LinkedIn developer pages we used don't describe consent fields or a consent parameter, so we won't invent one. General points (not legal advice):
- Server-side sending doesn't remove the need for consent. If a visitor declined marketing tracking, don't send their event to LinkedIn from the server either.
- Only store and forward
li_fat_idwhen your consent setup allows it, and record the choice with the lead in your CRM. - Hashing an email is pseudonymisation, not anonymisation. Your privacy policy should say you share hashed identifiers with ad platforms.
- Check LinkedIn's own advertising terms and your counsel for your regions (for example PIPEDA in Canada, GDPR in the EU).
FAQ
Does server-track-lab send events to LinkedIn?
No, not today. server-track-lab delivers to Meta Conversions API now, Google is coming soon, and LinkedIn is on the roadmap. This guide shows how to call the LinkedIn Conversions API directly while sending the same event_id and user data to server-track-lab for Meta.
How does LinkedIn deduplicate Insight Tag and Conversions API events?
LinkedIn's deduplication docs say you create a conversion rule for each data source (browser and server) and send the same eventId from both. 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 only the Insight Tag event.
How do I hash email for LinkedIn?
LinkedIn's schema says to convert the email to lower case, remove all whitespace, then hash it with SHA-256 and send the HEX-encoded result as idType SHA256_EMAIL.
What is li_fat_id and how do I send it?
li_fat_id is LinkedIn's first-party ad tracking click ID. With enhanced conversion tracking enabled on your Insight Tag, LinkedIn appends it to ad click URLs. Capture it from the landing page URL or the cookie and send it as idType LINKEDIN_FIRST_PARTY_ADS_TRACKING_UUID.
How old can a LinkedIn conversion be?
LinkedIn's docs say conversionHappenedAt is an epoch timestamp in milliseconds and must be within the past 90 days.
Which LinkedIn conversion type should I use for a booked demo?
The LinkedIn pages we checked do not list a demo or appointment type. This guide uses LEAD for demo_booked as our own choice; OTHER is also a documented type. Use separate named rules so reporting stays readable.
Try it
See the Meta payload your event produces in the playground, no signup needed. Then get a free API key: 1,000 events a month free, then CA$2 per 1,000 events. Moving from another tool? Read migrating from Stape or Cometly.
Sources (fetched Oct 14, 2026): LinkedIn on Microsoft Learn: Conversions API, Conversions API schema, Deduplication, Enabling Click IDs, Conversion tracking. LinkedIn is a trademark of LinkedIn Corporation; server-track-lab is not affiliated with LinkedIn.
Free tools: Meta & Google hashing tool · event_id generator · CAPI payload validator