Overview
Microsoft Advertising supports two primary conversion tracking methods:
- Client-Side Tracking: UET tag executes in user's browser
- 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
- User clicks Microsoft Advertising ad
- Lands on your website with
msclkidparameter - UET JavaScript tag loads in browser
- Tag stores
msclkidin cookie - User completes conversion action
- UET tag fires conversion event to Microsoft
- 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
- User clicks Microsoft Advertising ad
- Lands on your website with
msclkidparameter - Your server captures and stores
msclkid - User completes conversion
- Your server validates conversion
- Server sends conversion data to Microsoft Advertising API
- 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 |
Hybrid Approach (Recommended)
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:
- Navigate to Conversions > Conversion goals
- Edit goal settings
- Set Count to Unique
- 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:
- Navigate to Tools > Conversions > Conversion goals
- Click Offline conversions tab
- Click Upload offline conversions
- Select CSV file
- Map columns
- 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
- Go to Microsoft Advertising Developer Portal
- Create new application
- 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
- User completes conversion
- Your server sends hashed email/phone to Microsoft
- Microsoft matches to signed-in user
- Improves cross-device attribution
- 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
- Review data layer setup for advanced e-commerce tracking
- Explore Microsoft Advertising API documentation
- Set up integrations with CRM systems
- Configure troubleshooting tools for monitoring