Server-Side vs Client-Side LinkedIn Tracking | OpsBlu Docs

Server-Side vs Client-Side LinkedIn Tracking

Compare client-side Insight Tag and server-side API implementations for LinkedIn Ads conversion tracking

Overview

LinkedIn Ads offers two primary approaches for conversion tracking: client-side using the Insight Tag and server-side using the Conversion API. This guide helps you understand the differences, benefits, trade-offs, and implementation approaches for each method.


Client-Side Tracking (Insight Tag)

How It Works

The Insight Tag is a JavaScript snippet that:

  1. Loads in user's browser
  2. Sets first-party cookies
  3. Captures page views and events
  4. Sends data to LinkedIn's servers
  5. Attributes conversions to ads

Data Flow:

User's Browser → Insight Tag (JavaScript) → LinkedIn Servers → Campaign Manager

Advantages

1. Easy Implementation

<!-- Simple tag installation -->
<script type="text/javascript">
_linkedin_partner_id = "1234567";
window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];
window._linkedin_data_partner_ids.push(_linkedin_partner_id);
</script>
<script type="text/javascript">
(function(l) {
if (!l){window.lintrk = function(a,b){window.lintrk.q.push([a,b])};
window.lintrk.q=[]}
var s = document.getElementsByTagName("script")[0];
var b = document.createElement("script");
b.type = "text/javascript";b.async = true;
b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
s.parentNode.insertBefore(b, s);})(window.lintrk);
</script>

No backend development required.

2. Automatic Attribution

LinkedIn handles:

  • Click tracking
  • View-through attribution
  • Cookie matching
  • User identification
  • Attribution windows

3. Rich Data Collection

Captures:

  • Page views (automatic)
  • User behavior
  • Site demographics
  • Engagement metrics
  • Session data

4. Website Retargeting

Enables:

  • Retargeting audiences
  • URL-based segments
  • Behavioral targeting
  • Lookalike audiences

5. No Server Infrastructure

  • Runs entirely client-side
  • No API credentials needed
  • No server maintenance
  • Instant updates from LinkedIn

Disadvantages

1. Browser Dependencies

Requires:

  • JavaScript enabled
  • Cookies enabled
  • Page fully loaded
  • No blocking extensions

Fails When:

  • JavaScript disabled
  • AdBlockers active
  • Network issues prevent tag load
  • Page abandonment before tag fires

2. Privacy Limitations

Increasingly Affected By:

  • Browser privacy features (ITP, ETP)
  • Cookie restrictions
  • GDPR/CCPA requirements
  • User consent requirements
  • Third-party cookie deprecation

Impact:

  • Reduced match rates
  • Attribution gaps
  • Incomplete tracking
  • Data loss

3. Client-Side Vulnerabilities

Challenges:

  • Users can inspect/manipulate
  • Browser console access
  • Tag can be blocked
  • No guaranteed firing
  • Timing dependencies

4. Limited Control

  • Can't track without page load
  • Dependent on frontend changes
  • Difficult offline conversions
  • No backend-only events

Server-Side Tracking (Conversion API)

How It Works

Server-to-server API calls:

  1. User completes action
  2. Your server detects event
  3. Server calls LinkedIn API
  4. LinkedIn records conversion
  5. Attributes to campaigns

Data Flow:

User Action → Your Server → LinkedIn Conversion API → Campaign Manager

API Endpoint

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

Advantages

1. Reliable Tracking

  • Not dependent on browser
  • No JavaScript required
  • Immune to ad blockers
  • Guaranteed delivery (with retries)
  • Works offline or server-side only

2. Privacy Compliant

  • First-party data only
  • No browser cookies required
  • Better GDPR/CCPA compliance
  • Server-controlled data sharing
  • Reduced client-side tracking

3. Complete Control

  • Track any backend event
  • Flexible timing
  • Retry logic
  • Data validation
  • Custom attribution

4. Enhanced Security

  • API credentials server-side
  • No client-side exposure
  • Validated data
  • Encrypted transmission
  • Audit trails

5. Offline Conversions

Track events that occur:

  • In-person (retail, events)
  • Via phone calls
  • Through offline channels
  • Days/weeks after initial interaction

Disadvantages

1. Complex Implementation

Requires:

  • Backend development
  • API integration
  • Authentication setup
  • Error handling
  • Testing infrastructure

2. No Automatic Attribution

You Must Provide:

  • User identifier (email hash)
  • Conversion timestamp
  • Attribution data
  • Click ID (if available)

LinkedIn can't automatically:

  • Track clicks
  • Set cookies
  • Identify users
  • Handle view-through attribution

3. Limited Retargeting

  • No page view data
  • Can't build URL-based audiences
  • No automatic demographic insights
  • Manual audience uploads required

4. Development Resources

Ongoing Needs:

  • Server maintenance
  • API monitoring
  • Error handling
  • Credential management
  • Version updates

5. Delayed Attribution

  • Must match email to LinkedIn member
  • Lower match rates than cookie-based
  • Requires user identification
  • Hash matching limitations

Comparison Table

Aspect Client-Side (Insight Tag) Server-Side (API)
Implementation Easy, JavaScript snippet Complex, API integration
Attribution Automatic Manual
Browser Required Yes No
JavaScript Required Yes No
Cookie Required Yes No
Ad Blocker Proof No Yes
Privacy Impact Higher Lower
Match Rate Higher (cookie-based) Lower (email-based)
Retargeting Full support Limited
Website Demographics Yes No
Offline Conversions No Yes
Development Effort Minimal Significant
Reliability Browser-dependent Server-controlled
Data Control Limited Complete
Real-Time Tracking Yes Yes (with implementation)

Server-Side Implementation

Prerequisites

Required:

  • LinkedIn Campaign Manager account
  • LinkedIn Marketing API access
  • OAuth 2.0 credentials
  • Server infrastructure
  • Development resources

Step 1: API Access

Get Access:

  1. Register application at LinkedIn Developers
  2. Request marketing API permissions
  3. Generate OAuth 2.0 credentials
  4. Obtain access token

Required Permissions:

  • w_member_social
  • rw_ads
  • r_ads_reporting

Step 2: Conversion Tracking Setup

Create Conversion (if not exists):

POST https://api.linkedin.com/v2/conversions
Authorization: Bearer {ACCESS_TOKEN}
Content-Type: application/json

{
  "account": "urn:li:sponsoredAccount:123456",
  "name": "Purchase",
  "type": "PURCHASE",
  "attributionType": "LAST_TOUCH_BY_CAMPAIGN",
  "postClickAttributionWindowSize": 30,
  "viewThroughAttributionWindowSize": 7
}

Response includes Conversion ID:

{
  "id": "urn:li:conversion:987654"
}

Step 3: Track Conversions

API Call Structure:

POST https://api.linkedin.com/v2/conversionEvents
Authorization: Bearer {ACCESS_TOKEN}
Content-Type: application/json

{
  "conversion": "urn:li:conversion:987654",
  "conversionHappenedAt": 1699564800000,
  "user": {
    "userIds": [
      {
        "idType": "SHA256_EMAIL",
        "idValue": "hash_of_user_email"
      }
    ]
  },
  "conversionValue": {
    "currencyCode": "USD",
    "amount": "99.99"
  },
  "eventId": "unique_event_id_12345"
}

Step 4: Implementation Examples

Node.js Example

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

async function trackLinkedInConversion(userEmail, conversionValue) {
  // Hash email
  const hashedEmail = crypto
    .createHash('sha256')
    .update(userEmail.toLowerCase().trim())
    .digest('hex');

  // Prepare conversion event
  const conversionEvent = {
    conversion: 'urn:li:conversion:987654',
    conversionHappenedAt: Date.now(),
    user: {
      userIds: [
        {
          idType: 'SHA256_EMAIL',
          idValue: hashedEmail
        }
      ]
    },
    conversionValue: {
      currencyCode: 'USD',
      amount: conversionValue.toString()
    },
    eventId: `order_${Date.now()}_${Math.random()}`
  };

  try {
    const response = await axios.post(
      'https://api.linkedin.com/v2/conversionEvents',
      conversionEvent,
      {
        headers: {
          'Authorization': `Bearer ${process.env.LINKEDIN_ACCESS_TOKEN}`,
          'Content-Type': 'application/json'
        }
      }
    );

    console.log('Conversion tracked:', response.data);
    return response.data;
  } catch (error) {
    console.error('Error tracking conversion:', error.response?.data || error.message);
    throw error;
  }
}

// Usage
trackLinkedInConversion('user@example.com', 99.99);

Python Example

import hashlib
import time
import requests
import os

def track_linkedin_conversion(user_email, conversion_value):
    # Hash email
    hashed_email = hashlib.sha256(
        user_email.lower().strip().encode()
    ).hexdigest()

    # Prepare conversion event
    conversion_event = {
        'conversion': 'urn:li:conversion:987654',
        'conversionHappenedAt': int(time.time() * 1000),
        'user': {
            'userIds': [
                {
                    'idType': 'SHA256_EMAIL',
                    'idValue': hashed_email
                }
            ]
        },
        'conversionValue': {
            'currencyCode': 'USD',
            'amount': str(conversion_value)
        },
        'eventId': f'order_{int(time.time())}_{hash(user_email)}'
    }

    # Make API call
    response = requests.post(
        'https://api.linkedin.com/v2/conversionEvents',
        json=conversion_event,
        headers={
            'Authorization': f'Bearer {os.getenv("LINKEDIN_ACCESS_TOKEN")}',
            'Content-Type': 'application/json'
        }
    )

    if response.status_code == 201:
        print('Conversion tracked successfully')
        return response.json()
    else:
        print(f'Error: {response.status_code} - {response.text}')
        raise Exception('Failed to track conversion')

# Usage
track_linkedin_conversion('user@example.com', 99.99)

PHP Example

<?php
function trackLinkedInConversion($userEmail, $conversionValue) {
    // Hash email
    $hashedEmail = hash('sha256', strtolower(trim($userEmail)));

    // Prepare conversion event
    $conversionEvent = [
        'conversion' => 'urn:li:conversion:987654',
        'conversionHappenedAt' => time() * 1000,
        'user' => [
            'userIds' => [
                [
                    'idType' => 'SHA256_EMAIL',
                    'idValue' => $hashedEmail
                ]
            ]
        ],
        'conversionValue' => [
            'currencyCode' => 'USD',
            'amount' => strval($conversionValue)
        ],
        'eventId' => 'order_' . time() . '_' . uniqid()
    ];

    // Make API call
    $ch = curl_init('https://api.linkedin.com/v2/conversionEvents');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($conversionEvent));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . getenv('LINKEDIN_ACCESS_TOKEN'),
        'Content-Type: application/json'
    ]);

    $response = curl_exec($ch);
    $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($statusCode === 201) {
        echo 'Conversion tracked successfully';
        return json_decode($response, true);
    } else {
        throw new Exception('Failed to track conversion: ' . $response);
    }
}

// Usage
trackLinkedInConversion('user@example.com', 99.99);
?>

Best of Both Worlds

Use Client-Side For:

  • Page view tracking
  • Website retargeting audiences
  • Demographic insights
  • Automatic attribution
  • View-through conversions

Use Server-Side For:

  • High-value conversions
  • Offline conversions
  • Backend-only events
  • Compliance requirements
  • Guaranteed tracking

Implementation

Step 1: Install Insight Tag

Standard client-side implementation for retargeting and attribution.

Step 2: Server-Side for Critical Conversions

When high-value conversion occurs server-side:

// Server-side (Node.js example)
app.post('/checkout/complete', async (req, res) => {
  const order = req.body;

  // Process order
  await processOrder(order);

  // Track to LinkedIn via API
  await trackLinkedInConversion(order.email, order.total);

  // Return success
  res.json({ success: true });
});

Step 3: Client-Side as Backup

On confirmation page:

<script>
// Client-side tracking as backup/supplement
window.lintrk('track', {
  conversion_id: 987654,
  value: {{ order.total }},
  currency: 'USD'
});
</script>

Step 4: Deduplication

LinkedIn's backend handles deduplication when:

  • Same conversion ID
  • Same user (matched via email or cookie)
  • Similar timestamp
  • Uses eventId for server-side

Use unique eventId:

eventId: `order_${orderId}_${timestamp}`

LinkedIn deduplicates based on eventId within 24 hours.


When to Choose Each Approach

Client-Side Only

Best For:

  • Small to medium businesses
  • Limited development resources
  • Standard e-commerce
  • Retargeting-focused campaigns
  • Quick implementation needed

Examples:

  • Blog/content sites
  • E-commerce with simple checkout
  • Lead generation forms
  • SaaS trial signups

Server-Side Only

Best For:

  • Enterprise applications
  • Strict privacy requirements
  • Offline conversions
  • Complex attribution needs
  • High-value transactions

Examples:

  • B2B sales (long cycles)
  • Offline retail with CRM
  • Phone/call conversions
  • Multi-touch attribution

Hybrid Approach

Best For:

  • Large businesses
  • Comprehensive tracking
  • Multiple conversion types
  • Advanced marketing
  • Compliance + performance

Examples:

  • Enterprise SaaS
  • Large e-commerce
  • Multi-channel businesses
  • Financial services
  • Healthcare (HIPAA compliance)

Best Practices

Client-Side

  1. Install on all pages - Comprehensive tracking
  2. Use tag manager - GTM for flexibility
  3. Test thoroughly - Verify before launch
  4. Monitor tag health - Regular checks
  5. Respect privacy - Implement consent management

Server-Side

  1. Secure credentials - Environment variables, never hardcode
  2. Hash emails properly - SHA256, lowercase, trimmed
  3. Implement retries - Handle API failures
  4. Unique event IDs - Prevent duplicates
  5. Log conversions - Audit trail for debugging

Hybrid

  1. Clear separation - Document which events use which method
  2. Consistent IDs - Use same conversion IDs when appropriate
  3. Deduplication strategy - Understand LinkedIn's handling
  4. Monitor both sources - Verify data consistency
  5. Fallback logic - Server-side backup for critical events

Troubleshooting

Client-Side Issues

Tag not loading:

  • Check JavaScript console errors
  • Verify tag code correct
  • Ensure no ad blockers
  • Confirm page fully loads

Conversions not tracking:

  • Verify Insight Tag on conversion page
  • Check conversion_id correct
  • Confirm lintrk function available
  • Review Network tab for requests

Server-Side Issues

API authentication errors:

  • Verify access token valid
  • Check token not expired
  • Confirm proper permissions
  • Regenerate if needed

Conversion not attributed:

  • Verify email hash correct
  • Check match rate (typically 40-60%)
  • Confirm conversion URN correct
  • Review eventId for uniqueness

Rate limiting:

  • Implement exponential backoff
  • Batch requests when possible
  • Monitor rate limit headers
  • Distribute load

Monitoring and Analytics

Client-Side Monitoring

Campaign Manager:

  • Tag health dashboard
  • Detected domains
  • Recent activity
  • Conversion counts

Google Analytics:

  • UTM parameter tracking
  • Conversion correlation
  • Cross-platform analysis

Server-Side Monitoring

Application Logs:

logger.info('LinkedIn conversion tracked', {
  eventId: event.eventId,
  conversionId: event.conversion,
  value: event.conversionValue.amount,
  timestamp: event.conversionHappenedAt
});

Error Tracking:

try {
  await trackLinkedInConversion(email, value);
} catch (error) {
  errorLogger.error('LinkedIn API error', {
    error: error.message,
    statusCode: error.response?.status,
    email: hashEmail(email) // Log hash, not actual email
  });
}

Metrics to Track:

  • API success rate
  • Response times
  • Match rates
  • Error types
  • Conversion volume

Future Considerations

Privacy Evolution

Trends:

  • Increased cookie restrictions
  • Third-party cookie deprecation
  • Stricter privacy laws
  • User consent requirements

Impact:

  • Server-side becomes more important
  • First-party data focus
  • API tracking advantages grow
  • Hybrid approaches essential

LinkedIn Platform Updates

Stay informed:

  • API version changes
  • New features
  • Deprecation notices
  • Best practice updates

Next Steps

  1. Evaluate needs - Determine best approach for your business
  2. Plan implementation - Client-side, server-side, or hybrid
  3. Develop solution - Code and test thoroughly
  4. Monitor performance - Track success and errors
  5. Iterate and optimize - Refine based on results

Additional Resources