GrowthLaneGrowthLane

Narayan Prasath · 2026-01-04

LinkedIn Conversion API (CAPI) Setup: Complete Guide

Complete guide to setting up LinkedIn Conversion API (CAPI) for server-side tracking. Improve conversion accuracy, bypass ad blockers, and track offline events.

LinkedIn Conversion API (CAPI) Setup: Complete Guide

TL;DR: LinkedIn Conversion API (CAPI) sends conversion data directly from your server to LinkedIn, bypassing browser tracking limitations. It requires developer resources to implement but delivers more accurate conversion tracking—especially when users block cookies or make offline purchases. Set up via Campaign Manager by generating an API token, then integrate with your server using LinkedIn's API endpoints.

Prerequisites

Before implementing LinkedIn Conversion API, you need:

Important: CAPI is an advanced implementation. If you're just starting with LinkedIn ads, implement standard pixel-based conversion tracking first.

What Is LinkedIn Conversion API?

LinkedIn Conversion API (CAPI) is a server-to-server integration that sends conversion data directly from your backend to LinkedIn. Unlike the Insight Tag (which tracks in the browser), CAPI operates on your server.

Traditional Tracking (Insight Tag Only)

User clicks LinkedIn ad → Lands on website → Insight Tag fires → Conversion tracked

Limitations:

Server-Side Tracking (CAPI)

User converts → Your server records event → Server sends data to LinkedIn API → Conversion tracked

Benefits:

Best practice: Use both Insight Tag AND CAPI simultaneously for maximum accuracy. LinkedIn automatically deduplicates events.

How LinkedIn Conversion API Works

The CAPI Data Flow

  1. User interaction: Someone clicks your LinkedIn ad and visits your website
  2. User converts: They fill out a form, make a purchase, or complete your conversion goal
  3. Server captures event: Your backend records the conversion (email, user ID, timestamp)
  4. Server sends to LinkedIn: Your server makes an HTTPS POST request to LinkedIn's CAPI endpoint with conversion details
  5. LinkedIn matches user: LinkedIn matches the conversion to the original ad click using email hash or LinkedIn UUID
  6. Conversion attributed: The conversion appears in Campaign Manager attributed to the correct campaign/ad

What Data CAPI Sends

Required fields for each conversion:

Optional fields for better matching:

Step 1: Set Up Conversion Tracking in Campaign Manager

Before implementing CAPI, create your conversion events:

  1. Log into Campaign Manager at business.linkedin.com/campaign-manager
  2. Click Analyze > Conversion Tracking
  3. Click Create Conversion
  4. Fill in conversion details:
    • Name: "Demo Request" (internal name)
    • Attribution Window: 30 days (default)
    • Conversion Type: Lead, Purchase, or Other
    • Value: Optional revenue amount
  5. Click Create
  6. Note the Conversion ID (you'll need this for CAPI integration)

Repeat for each conversion event you want to track (e.g., "Download Whitepaper," "Free Trial Signup," "Purchase").

Step 2: Generate CAPI Access Token

Create an API access token to authenticate server requests:

  1. In Campaign Manager, navigate to Account Settings
  2. Click Conversion Tracking tab
  3. Scroll to Conversion API (CAPI) section
  4. Click Generate Access Token
  5. Copy the access token (appears once—store securely)
  6. Save token as an environment variable in your server (never commit to version control)

Security: Treat this token like a password. Anyone with this token can send conversion data to your LinkedIn account.

Token format: CAP1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Step 3: Implement Server-Side Integration

Integration Method 1: Direct API Calls (Custom Development)

If building a custom integration, your server makes HTTPS POST requests to LinkedIn's CAPI endpoint:

Endpoint:

POST https://api.linkedin.com/v2/conversionEvents

Headers:

Authorization: Bearer {YOUR_ACCESS_TOKEN}
Content-Type: application/json
LinkedIn-Version: 202401

Request Body (Example):

{
  "conversion": "urn:li:conversion:12345678",
  "conversionHappenedAt": 1706371200000,
  "conversionValue": {
    "amount": "99.99",
    "currencyCode": "USD"
  },
  "user": {
    "userIds": [
      {
        "idType": "SHA256_EMAIL",
        "idValue": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
      }
    ],
    "userInfo": {
      "ipAddress": "203.0.113.42",
      "userAgent": "Mozilla/5.0..."
    }
  },
  "eventId": "unique-event-id-123",
  "campaignId": "123456789"
}

Required fields explained:

Integration Method 2: Using Official SDKs

LinkedIn doesn't provide official CAPI SDKs, but you can use HTTP libraries in your language:

Python Example:

import requests
import hashlib
import time

def send_conversion_to_linkedin(email, conversion_id, value=None):
    # Hash email with SHA256
    email_hash = hashlib.sha256(email.lower().encode()).hexdigest()
    
    # Build payload
    payload = {
        "conversion": f"urn:li:conversion:{conversion_id}",
        "conversionHappenedAt": int(time.time() * 1000),
        "user": {
            "userIds": [{
                "idType": "SHA256_EMAIL",
                "idValue": email_hash
            }]
        },
        "eventId": f"event_{int(time.time())}_{email_hash[:8]}"
    }
    
    # Add optional value
    if value:
        payload["conversionValue"] = {
            "amount": str(value),
            "currencyCode": "USD"
        }
    
    # Send to LinkedIn
    headers = {
        "Authorization": f"Bearer {LINKEDIN_ACCESS_TOKEN}",
        "Content-Type": "application/json",
        "LinkedIn-Version": "202401"
    }
    
    response = requests.post(
        "https://api.linkedin.com/v2/conversionEvents",
        json=payload,
        headers=headers
    )
    
    return response.status_code == 201

Node.js Example:

const axios = require('axios');
const crypto = require('crypto');

async function sendConversionToLinkedIn(email, conversionId, value = null) {
  // Hash email
  const emailHash = crypto
    .createHash('sha256')
    .update(email.toLowerCase())
    .digest('hex');
  
  // Build payload
  const payload = {
    conversion: `urn:li:conversion:${conversionId}`,
    conversionHappenedAt: Date.now(),
    user: {
      userIds: [{
        idType: 'SHA256_EMAIL',
        idValue: emailHash
      }]
    },
    eventId: `event_${Date.now()}_${emailHash.substring(0, 8)}`
  };
  
  // Add optional value
  if (value) {
    payload.conversionValue = {
      amount: value.toString(),
      currencyCode: 'USD'
    };
  }
  
  // Send to LinkedIn
  try {
    const response = await axios.post(
      'https://api.linkedin.com/v2/conversionEvents',
      payload,
      {
        headers: {
          'Authorization': `Bearer ${process.env.LINKEDIN_ACCESS_TOKEN}`,
          'Content-Type': 'application/json',
          'LinkedIn-Version': '202401'
        }
      }
    );
    return response.status === 201;
  } catch (error) {
    console.error('CAPI Error:', error.response?.data);
    return false;
  }
}

Integration Method 3: Using Marketing Platforms

Popular marketing platforms offer LinkedIn CAPI integrations:

Segment:

  1. In Segment, go to Catalog > Destinations
  2. Search for "LinkedIn Conversions API"
  3. Connect your LinkedIn account
  4. Map Segment events to LinkedIn conversion rules
  5. Enable destination

Zapier:

  1. Create Zap triggered by your conversion event (form submission, CRM deal stage change)
  2. Add action: "LinkedIn Ads - Send Conversion"
  3. Authenticate with LinkedIn
  4. Map fields: Email, Conversion ID, Value
  5. Turn on Zap

HubSpot:

  1. Install LinkedIn Ads integration
  2. Navigate to Settings > Marketing > Ads
  3. Connect LinkedIn account
  4. Enable "Send offline conversions"
  5. Map HubSpot properties to LinkedIn conversion events

Note: Third-party tools often have limitations (e.g., Zapier's 15-minute delay). Custom integration provides real-time tracking.

Step 4: Hash User Identifiers Correctly

LinkedIn requires email addresses hashed with SHA256:

Email normalization rules:

  1. Convert to lowercase: John@Example.comjohn@example.com
  2. Trim whitespace: user@example.comuser@example.com
  3. Hash with SHA256
  4. Send as hex string (64 characters)

Example transformation:

Common hashing mistakes:

Test your hashing: Use an online SHA256 calculator to verify your hashing logic matches expected output.

Step 5: Implement Deduplication

LinkedIn automatically deduplicates conversions received from both Insight Tag and CAPI if they have matching:

Best practice: Always send a unique eventId with each CAPI request:

"eventId": "order_12345_1706371200"

Format: {event_type}_{unique_identifier}_{timestamp}

This prevents:

Step 6: Test CAPI Implementation

Before launching, test your integration:

Test 1: Send Test Conversion

Trigger a conversion on your website using a test email:

  1. Use test email: test@yourcompany.com
  2. Complete conversion action (form submit, purchase)
  3. Check your server logs for CAPI API call
  4. Verify API response: 201 Created (success) or error code

Test 2: Check Campaign Manager

Wait 15-30 minutes after test conversion:

  1. Campaign Manager > Analyze > Conversion Tracking
  2. Click your conversion event
  3. Check Recent Conversions list
  4. Look for your test conversion (may show "Direct" as source if not from an ad click)

Note: CAPI conversions without a LinkedIn ad click appear as "Direct" conversions in reports. They won't attribute to campaigns but confirm CAPI is working.

Test 3: Validate with Ad Click

Generate a real conversion with ad attribution:

  1. Click one of your own LinkedIn ads (use a test campaign)
  2. Complete the conversion on your site
  3. Check that CAPI sends the conversion to LinkedIn
  4. Wait 30 minutes
  5. Campaign Manager > Check campaign performance for the conversion

Success: Conversion appears attributed to your test campaign.

Test 4: Deduplication Test

Verify LinkedIn deduplicates properly:

  1. Complete a conversion (triggers both Insight Tag and CAPI)
  2. Wait 1 hour
  3. Check conversion count in Campaign Manager
  4. Expected: Only 1 conversion counted (not 2)

If seeing duplicate conversions, check your eventId and timing implementations.

Step 7: Monitor CAPI Performance

After launching CAPI, monitor for issues:

API Error Monitoring

Log all CAPI API responses:

Common error codes:

Monitoring strategy:

  1. Set up alerts for 4xx/5xx error rates above 5%
  2. Log all failed CAPI requests for debugging
  3. Implement retry logic with exponential backoff for 5xx errors
  4. Rotate access tokens if seeing persistent 401 errors

Conversion Discrepancy Tracking

Compare conversion counts weekly:

WeekCRM ConversionsLinkedIn ReportedMatch RateIssue
Jan 1-715014295%Acceptable
Jan 8-1420016080%Investigate

If match rate drops below 85%:

Attribution Quality Check

Monitor conversion source mix:

Before CAPI (Insight Tag only):

After CAPI:

Expected improvement: 15-30% increase in attributed conversions (CAPI captures users with ad blockers).

Advanced CAPI Use Cases

Use Case 1: Offline Conversion Tracking

Track conversions that happen off your website:

Example: Phone call conversions

  1. Prospect clicks LinkedIn ad
  2. Calls your sales team (tracked in phone system)
  3. Phone system API sends conversion to your server
  4. Your server sends CAPI request to LinkedIn with prospect's email

Implementation:

Use Case 2: CRM-Based Conversion Tracking

Track when leads become opportunities or customers:

Example: HubSpot deal stage change

  1. Lead from LinkedIn ad enters CRM
  2. Sales team moves deal to "Closed Won"
  3. HubSpot webhook triggers on deal stage change
  4. Your server receives webhook
  5. Server sends CAPI "Purchase" conversion to LinkedIn

Benefits:

Use Case 3: Mobile App Conversions

Track in-app conversions from LinkedIn ad clicks:

Example: iOS app subscription

  1. User clicks LinkedIn ad on mobile
  2. Installs app from App Store
  3. User subscribes in app
  4. App backend sends CAPI conversion to LinkedIn

Requirements:

Use Case 4: Multi-Touch Attribution

Use CAPI to send multiple touchpoints:

Example funnel:

Each CAPI event helps LinkedIn understand the full buyer journey for better optimization.

Common Mistakes with LinkedIn CAPI

Mistake 1: Not Using Both Insight Tag and CAPI

Wrong: Replacing Insight Tag entirely with CAPI Right: Run both simultaneously for maximum coverage

CAPI alone misses users who convert before your server processes data. Insight Tag + CAPI = best accuracy.

Mistake 2: Incorrect Email Hashing

Wrong: Hashing email with original case: John@Example.COM → hash Right: Normalize first: john@example.com → hash

Case sensitivity breaks user matching, causing conversion loss.

Mistake 3: Sending Conversions Without eventId

Wrong: Omitting eventId field Right: Always include unique eventId

Without eventId, retried requests create duplicate conversions.

Mistake 4: Not Implementing Error Handling

Wrong: Fire-and-forget CAPI requests without checking responses Right: Log errors, implement retries for 5xx errors, alert on high error rates

Missing error handling leads to silent conversion tracking failures.

Mistake 5: Using Outdated API Version

Wrong: Using API version 202301 or earlier Right: Use latest version (202401+) in LinkedIn-Version header

Older API versions lack features and may be deprecated.

Troubleshooting LinkedIn CAPI

Issue 1: CAPI Conversions Not Appearing in Campaign Manager

Causes:

Fixes:

  1. Test API token with simple request
  2. Verify conversion ID: Campaign Manager > Conversion Tracking > Click conversion > Note ID
  3. Validate JSON payload with LinkedIn's API docs
  4. Check conversionHappenedAt is recent and in milliseconds (not seconds)
  5. Review server logs for API error responses

Issue 2: Conversions Not Attributed to Campaigns

Causes:

Fixes:

Issue 3: High Error Rates (429 Too Many Requests)

Cause: Exceeding LinkedIn's API rate limits

Fix: Implement request batching and rate limiting:

import time
from collections import deque

class LinkedInCAPIRateLimiter:
    def __init__(self, max_requests_per_second=10):
        self.max_requests = max_requests_per_second
        self.requests = deque()
    
    def wait_if_needed(self):
        now = time.time()
        # Remove requests older than 1 second
        while self.requests and self.requests[0] < now - 1:
            self.requests.popleft()
        
        # If at limit, wait
        if len(self.requests) >= self.max_requests:
            sleep_time = 1 - (now - self.requests[0])
            time.sleep(max(0, sleep_time))
            self.requests.popleft()
        
        self.requests.append(time.time())

LinkedIn's rate limits: ~100 requests/minute per access token.

Issue 4: Duplicate Conversions Despite eventId

Cause: Multiple systems sending same conversion with different eventId values

Fix:

  1. Audit all systems sending CAPI requests (backend, CRM, marketing tools)
  2. Choose ONE source of truth for each conversion type
  3. Disable CAPI in duplicate systems
  4. Use consistent eventId format across all systems

CAPI Security Best Practices

  1. Store access token securely: Use environment variables, never hardcode
  2. Restrict token permissions: Generate separate tokens for different environments (dev/prod)
  3. Hash user data: Never send plain text emails or PII in API requests
  4. Use HTTPS only: All CAPI requests must use encrypted connections
  5. Log cautiously: Don't log plain text user data or access tokens
  6. Rotate tokens regularly: Generate new tokens every 90 days
  7. Monitor for unauthorized usage: Alert on unexpected API call volume spikes
  8. Implement IP whitelisting: If possible, restrict API calls to known server IPs
  9. Use API versioning: Pin to specific API version to prevent breaking changes
  10. Test in sandbox environment: Never test CAPI with production conversion rules initially

Glossary

TermDefinition
CAPIConversion API - server-to-server method for sending conversion data to LinkedIn
Server-Side TrackingTracking conversions from your backend server instead of user's browser
Access TokenAPI key that authenticates your server's requests to LinkedIn
Conversion Rule IDUnique identifier for each conversion event type in Campaign Manager
eventIdUnique identifier for each conversion instance (prevents duplicates)
SHA256Cryptographic hash function used to anonymize email addresses
User AgentString identifying user's browser and device (helps with matching)
Attribution WindowTime period after ad click during which conversions are attributed
DeduplicationLinkedIn's process of counting same conversion from multiple sources only once
Rate LimitingRestricting number of API requests in a time period

Verification Checklist

After implementing LinkedIn CAPI:

Next Steps After CAPI Setup

  1. Week 1: Monitor conversion match rates between CRM and LinkedIn
  2. Week 2: Check campaign attribution improvements (should see 15-30% more attributed conversions)
  3. Week 3: Implement advanced use cases (offline conversions, CRM integration)
  4. Week 4: Optimize campaigns using improved conversion data
  5. Monthly: Review CAPI error logs and API success rates
  6. Quarterly: Audit all conversion rules, update as business goals evolve

Screenshot List:

  1. Campaign Manager Conversion Tracking page (Campaign Manager > Analyze > Conversion Tracking)
  2. Create Conversion dialog with fields (Conversion Tracking > Create Conversion button)
  3. Conversion detail view showing Conversion ID (Conversion list > Click conversion name > Conversion ID field)
  4. Account Settings with CAPI section (Campaign Manager > Account Settings > Conversion Tracking tab)
  5. Generate Access Token button in CAPI section (Account Settings > CAPI section > Generate Token button)
  6. Access token display (one-time view after generation)
  7. Recent Conversions list showing CAPI test conversions (Conversion detail > Recent Conversions tab)
  8. API error response in developer tools/logs (Server logs showing 400/401 response from LinkedIn API)
  9. Campaign performance with CAPI conversions attributed (Campaign Manager > Campaign detail > Conversions column)
  10. Conversion reporting showing source breakdown (Conversion detail > Reporting > Source dimension)
  11. Example Python/Node code in text editor (Code editor showing CAPI integration script)
  12. Server logs showing successful CAPI requests (Terminal/logging dashboard with 201 status codes)