Microsoft Advertising Server-Side vs Client-Side Tracking | OpsBlu Docs

Microsoft Advertising Server-Side vs Client-Side Tracking

Comparison of client-side UET tag implementation versus server-side conversion tracking via Microsoft Advertising API.

Overview

Microsoft Advertising supports two primary conversion tracking methods:

  1. Client-Side Tracking: UET tag executes in user's browser
  2. Server-Side Tracking: Conversions sent from your server via API

Each approach has distinct advantages, use cases, and implementation requirements.

Client-Side Tracking (UET Tag)

How It Works

  1. User clicks Microsoft Advertising ad
  2. Lands on your website with msclkid parameter
  3. UET JavaScript tag loads in browser
  4. Tag stores msclkid in cookie
  5. User completes conversion action
  6. UET tag fires conversion event to Microsoft
  7. Conversion attributed to ad click

Advantages

Easy Implementation

  • Copy/paste JavaScript snippet
  • No backend development required
  • Works with any website platform

Automatic Data Collection

  • Page URLs, referrers, user agents collected automatically
  • No manual parameter passing needed
  • Remarketing audiences built automatically

Real-Time Tracking

  • Conversions fire immediately when action occurs
  • No delays for batch processing
  • Instant event tracking for user actions

Rich Event Data

  • Custom event parameters
  • E-commerce product data
  • Page engagement metrics

No Server Load

  • Processing happens on client side
  • No API rate limits to manage
  • Microsoft handles infrastructure

Disadvantages

Browser Dependency

  • Requires JavaScript enabled
  • Blocked by ad blockers (~25% of users)
  • Won't fire if page doesn't fully load
  • Cookie restrictions affect tracking

Privacy Limitations

  • Subject to browser privacy controls
  • ITP (Intelligent Tracking Prevention) limits cookies
  • GDPR/CCPA consent requirements
  • Client-side data can be manipulated

Attribution Gaps

  • Lost conversions if browser crashes
  • Cross-device attribution limited
  • Offline conversions not captured
  • Server-side validation impossible

Delayed Conversions

  • Can't track conversions that occur after session ends
  • Email confirmations or delayed processing not captured
  • Requires user to stay on page until tag fires

Best For

  • Standard e-commerce websites
  • Lead generation forms
  • Content downloads
  • Video engagement
  • Page view conversions
  • Quick implementation needs

Server-Side Tracking (API)

How It Works

  1. User clicks Microsoft Advertising ad
  2. Lands on your website with msclkid parameter
  3. Your server captures and stores msclkid
  4. User completes conversion
  5. Your server validates conversion
  6. Server sends conversion data to Microsoft Advertising API
  7. Conversion attributed to ad click

Implementation Methods

1. Offline Conversion Import (Simple)

  • Manual CSV upload via Microsoft Advertising interface
  • Scheduled automated uploads
  • Suitable for batch processing

2. Microsoft Advertising API (Advanced)

  • Programmatic conversion submission
  • Real-time or batched sending
  • Full automation and integration

Advantages

Enhanced Accuracy

  • Not blocked by ad blockers
  • Not affected by browser settings
  • Server validates conversion before sending
  • Works without JavaScript

Privacy Compliant

  • No client-side cookies required
  • Server-side data control
  • Easier GDPR/CCPA compliance
  • User doesn't need to stay on page

Attribution Completeness

  • Capture offline conversions
  • Phone call conversions
  • Email-based conversions
  • Delayed processing conversions
  • CRM-based attribution

Data Validation

  • Verify payment processed before conversion
  • Fraud detection and filtering
  • Duplicate prevention
  • Revenue validation

Cross-Device Support

  • Track conversions across devices
  • Email-based matching
  • Authenticated user tracking
  • CRM identity resolution

Disadvantages

Complex Implementation

  • Requires backend development
  • API authentication and credentials
  • Error handling and retry logic
  • More technical expertise needed

Development Resources

  • Server-side code changes
  • Database storage for MSCLKID
  • API integration and testing
  • Ongoing maintenance

Limited Automation

  • No automatic remarketing audiences
  • No automatic page engagement data
  • Custom event tracking requires manual implementation
  • Product catalog sync needs separate setup

Delayed Reporting

  • Upload/API delays affect reporting
  • Batch processing introduces lag
  • Not suitable for real-time dashboards
  • 90-day upload window limit

API Rate Limits

  • Throttling for high-volume accounts
  • Need to handle rate limit errors
  • Batch optimization required
  • Monitoring and alerting needed

Best For

  • High-value B2B conversions
  • Offline sales (phone, in-store)
  • CRM-based attribution
  • Payment validation required
  • Multi-step sales processes
  • Cross-device tracking needs
  • Privacy-focused implementations

Comparison Matrix

Feature Client-Side (UET Tag) Server-Side (API)
Implementation Easy (copy/paste) Complex (development)
Technical skill Basic HTML Backend programming
Setup time Minutes Days to weeks
Ad blocker resistance Blocked Not affected
Browser dependency Required Not required
Real-time tracking Immediate Depends on implementation
Remarketing audiences Automatic Manual setup
Offline conversions Not supported Fully supported
Cross-device Limited Supported
Data validation Client-side only Server-side
Privacy compliance Requires consent Easier compliance
Conversion delay None Seconds to hours
Maintenance Low Moderate
Cost Free Development + maintenance

Combine both methods for maximum coverage:

Architecture

User Journey:
1. Click ad → Land with msclkid
2. Client-side UET tag fires (pageview)
3. Server captures msclkid
4. User completes conversion
5. Client-side UET fires conversion (immediate)
6. Server validates conversion
7. Server sends offline conversion (backup)

Benefits

  • Immediate tracking: Client-side conversion fires instantly
  • Validated backup: Server-side confirms after payment processing
  • Ad blocker recovery: Server-side captures what client misses
  • Remarketing: UET tag builds audiences automatically
  • Accuracy: Server-side deduplicates and validates

Implementation

Step 1: Deploy Client-Side UET

<!-- Standard UET tag on all pages -->
<script>
(function(w,d,t,r,u){
  var f,n,i;
  w[u]=w[u]||[],f=function(){
    var o={ti:"12345678"};
    o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")
  },
  n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function(){
    var s=this.readyState;
    s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)
  },
  i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)
})(window,document,"script","//bat.bing.com/bat.js","uetq");
</script>

<!-- Fire immediate conversion -->
<script>
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': 99.99,
  'currency': 'USD'
});
</script>

Step 2: Capture MSCLKID Server-Side

// PHP example
<?php
session_start();

// Capture msclkid from URL parameter
if (isset($_GET['msclkid'])) {
  $_SESSION['msclkid'] = $_GET['msclkid'];
  // Also store in database with user session
  $db->query("UPDATE sessions SET msclkid = ? WHERE session_id = ?",
    [$_GET['msclkid'], session_id()]
  );
}
?>
// Node.js example
app.use((req, res, next) => {
  if (req.query.msclkid) {
    req.session.msclkid = req.query.msclkid;
    // Store in database
    db.sessions.update({
      session_id: req.sessionID
    }, {
      msclkid: req.query.msclkid
    });
  }
  next();
});

Step 3: Send Server-Side Conversion After Validation

// After payment processing and validation
<?php
function sendOfflineConversion($orderId, $amount, $currency) {
  global $db;

  // Retrieve msclkid from database
  $order = $db->query("SELECT msclkid FROM orders WHERE id = ?", [$orderId])->fetch();

  if (!$order || !$order['msclkid']) {
    return false; // No msclkid, conversion won't be attributed
  }

  // Prepare conversion data
  $conversionData = [
    'Microsoft Click ID' => $order['msclkid'],
    'Conversion Name' => 'Purchase',
    'Conversion Time' => gmdate('Y-m-d H:i:s'), // UTC timezone
    'Conversion Value' => $amount,
    'Conversion Currency' => $currency
  ];

  // Option 1: Queue for batch upload (CSV)
  appendToCSV('conversions.csv', $conversionData);

  // Option 2: Send via API immediately (see API section below)
  sendViaMicrosoftAPI($conversionData);
}
?>

Step 4: Configure Deduplication

In Microsoft Advertising:

  1. Navigate to Conversions > Conversion goals
  2. Edit goal settings
  3. Set Count to Unique
  4. Microsoft automatically deduplicates based on MSCLKID + timestamp

Offline Conversion Import

CSV File Format

Microsoft Click ID,Conversion Name,Conversion Time,Conversion Value,Conversion Currency
abc123xyz,Purchase,2025-12-24 10:30:00,99.99,USD
def456uvw,Lead,2025-12-24 11:45:00,0,USD
ghi789rst,Purchase,2025-12-24 14:20:00,249.99,USD

Requirements

  • Microsoft Click ID: Exact match from ad click (required)
  • Conversion Name: Must match existing conversion goal (required)
  • Conversion Time: UTC timezone, format: YYYY-MM-DD HH:MM:SS (required)
  • Conversion Value: Numeric value, no currency symbols (optional)
  • Conversion Currency: 3-letter ISO code (optional, defaults to account currency)

Upload Process

Manual Upload:

  1. Navigate to Tools > Conversions > Conversion goals
  2. Click Offline conversions tab
  3. Click Upload offline conversions
  4. Select CSV file
  5. Map columns
  6. Click Upload

Automated Upload:

Use Microsoft Advertising API to automate uploads (see API section).

Timing Requirements

  • Conversions must be uploaded within 90 days of ad click
  • Upload processing takes 2-4 hours
  • Best practice: Upload daily for timely reporting

Microsoft Advertising API Integration

Authentication Setup

Step 1: Register Application

  1. Go to Microsoft Advertising Developer Portal
  2. Create new application
  3. Note Client ID and Client Secret

Step 2: Get OAuth Token

# Python example using bingads SDK
from bingads import AuthorizationData, OAuthWebAuthCodeGrant

authorization_data = AuthorizationData(
    account_id='YOUR_ACCOUNT_ID',
    customer_id='YOUR_CUSTOMER_ID',
    developer_token='YOUR_DEVELOPER_TOKEN',
    authentication=None
)

oauth = OAuthWebAuthCodeGrant(
    client_id='YOUR_CLIENT_ID',
    client_secret='YOUR_CLIENT_SECRET',
    redirection_uri='https://your-app.com/oauth/callback'
)

# Get authorization URL
auth_url = oauth.get_authorization_endpoint()

# After user authorizes, exchange code for token
oauth.request_oauth_tokens_by_authorization_code('AUTHORIZATION_CODE')
authorization_data.authentication = oauth

Offline Conversion Upload via API

from bingads.v13.bulk import *
from bingads.service_client import ServiceClient

# Initialize bulk service
bulk_service = ServiceClient(
    service='BulkService',
    version=13,
    authorization_data=authorization_data
)

# Prepare offline conversion records
offline_conversions = [
    {
        'MicrosoftClickId': 'abc123xyz',
        'ConversionName': 'Purchase',
        'ConversionTime': '2025-12-24 10:30:00',
        'ConversionValue': 99.99,
        'ConversionCurrencyCode': 'USD'
    },
    {
        'MicrosoftClickId': 'def456uvw',
        'ConversionName': 'Lead',
        'ConversionTime': '2025-12-24 11:45:00',
        'ConversionValue': 0,
        'ConversionCurrencyCode': 'USD'
    }
]

# Upload conversions
response = bulk_service.UploadOfflineConversions(
    OfflineConversions=offline_conversions,
    AccountId='YOUR_ACCOUNT_ID'
)

print(f"Upload successful: {response}")

Node.js Example

const axios = require('axios');

async function uploadOfflineConversion(msclkid, conversionName, amount, currency) {
  const accessToken = await getAccessToken(); // OAuth token

  const conversionData = {
    msclkid: msclkid,
    conversion_name: conversionName,
    conversion_time: new Date().toISOString(),
    conversion_value: amount,
    conversion_currency: currency
  };

  try {
    const response = await axios.post(
      'https://api.bingads.microsoft.com/v13/OfflineConversions',
      conversionData,
      {
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json'
        }
      }
    );

    console.log('Conversion uploaded:', response.data);
    return true;
  } catch (error) {
    console.error('Upload failed:', error.response.data);
    return false;
  }
}

Error Handling

try:
    response = bulk_service.UploadOfflineConversions(
        OfflineConversions=offline_conversions,
        AccountId=account_id
    )
except Exception as e:
    # Handle common errors
    if 'Invalid MSCLKID' in str(e):
        print('MSCLKID not found or expired')
    elif 'Conversion goal not found' in str(e):
        print('Conversion name does not match existing goal')
    elif 'Outside conversion window' in str(e):
        print('Conversion occurred more than 90 days after click')
    else:
        print(f'Unknown error: {e}')

Enhanced Conversions

Microsoft Advertising's enhanced conversions use hashed customer data for improved attribution:

How It Works

  1. User completes conversion
  2. Your server sends hashed email/phone to Microsoft
  3. Microsoft matches to signed-in user
  4. Improves cross-device attribution
  5. Works even if cookies are deleted

Implementation

// Client-side with hashed email
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': 99.99,
  'currency': 'USD',
  'em': hashEmail(userEmail), // SHA-256 hashed email
  'ph': hashPhone(userPhone)  // SHA-256 hashed phone
});

function hashEmail(email) {
  // Use SHA-256 hashing (example using CryptoJS)
  return CryptoJS.SHA256(email.toLowerCase().trim()).toString();
}

Note: Enhanced conversions require advertiser verification and compliance with privacy policies.

Decision Framework

Choose Client-Side If:

  • Standard e-commerce or lead generation
  • Need quick implementation
  • Limited development resources
  • Real-time remarketing audiences needed
  • Low ad blocker usage in audience
  • Conversions happen in single session

Choose Server-Side If:

  • High-value B2B conversions
  • Offline conversions (phone, in-store)
  • Payment validation required
  • Multi-day sales cycles
  • Ad blocker resistance critical
  • Privacy regulations strict

Choose Hybrid If:

  • Best of both worlds
  • Have development resources
  • Maximum attribution coverage
  • Need remarking + validation
  • Want ad blocker backup

Implementation Checklist

Client-Side:

  • UET tag deployed on all pages
  • Conversion goals configured
  • Event tracking implemented
  • Revenue values dynamic
  • Testing completed with UET Tag Helper

Server-Side:

  • MSCLKID capture implemented
  • MSCLKID storage in database
  • Conversion goal created in Microsoft Advertising
  • CSV export or API integration built
  • Upload automation scheduled
  • Error handling and retry logic
  • Testing with sample conversions

Hybrid:

  • Both client and server implementations complete
  • Deduplication configured (Unique count)
  • Monitoring for both methods
  • Alerting for upload failures
  • Regular accuracy audits

Next Steps