B2B Conversion Tracking Setup Guide
Complete conversion tracking implementation for B2B. From pixel installation to offline conversion imports that feed your CRM data back to ad platforms.
Without server-side tracking, you're measuring 40% of what matters. iOS privacy changes, ad blockers, and ITP have gutted client-side pixels. If your conversions are still firing from the browser only, you're feeding Google and Meta half-blind signal — and then wondering why your campaigns don't optimize.
See enterprise GTM fails when you measure and forecasting in demand generation for why this matters more than most teams think.
42's Tracking Philosophy
Track fewer things, track them correctly. We've audited hundreds of ad accounts where teams track 15 conversion events but none connect to CRM. Track form submissions, demo requests, and closed-won. That's it. Everything else is noise.
-- From auditing 200+ B2B ad accounts
The 42 Conversion Hierarchy
Not all conversions are created equal. Here's how we think about conversion priority based on what actually drives revenue.
| Priority | Conversion Type | What to Do |
|---|---|---|
| PRIMARY | Demo request, Sales call booked | Optimize for this. This is where your budget should go. |
| SECONDARY | Form submission, Content download | Report on it. Track for understanding, but don't optimize for it. |
| TERTIARY | Page view, Time on site, Scroll depth | Ignore for optimization. Vanity metrics that don't move pipeline. |
Conversion Value Assignment
Assigning accurate values to conversions enables ROAS-based bidding and prevents platforms from optimizing for low-quality leads.
Value Calculation Formula
Conversion Value = Average Deal Size x Close Rate from that conversion type Example Value Matrix
| Conversion | Close Rate | Avg Deal: $50K | Value |
|---|---|---|---|
| Demo Request | 20% | $50,000 x 0.20 | $10,000 |
| Pricing Page + Form | 15% | $50,000 x 0.15 | $7,500 |
| Webinar Registration | 5% | $50,000 x 0.05 | $2,500 |
| Content Download | 2% | $50,000 x 0.02 | $1,000 |
| Newsletter Signup | 0.5% | $50,000 x 0.005 | $250 |
Server-Side or Die
Browser tracking is dying. If you're not running server-side (Meta CAPI, Google Enhanced Conversions), you're losing 30-40% of conversion data. Ad blockers, Safari ITP, and privacy browsers are eating your attribution. Server-side tracking is no longer optional.
-- This is non-negotiable for 2026
CRM is the Source of Truth
Your ad platform says 50 conversions. Your CRM says 30. Trust the CRM. Build attribution from CRM data, not platform data. Ad platforms are incentivized to over-report. Your CRM is where revenue actually lives.
-- This is why we always start with CRM data when auditing paid media
The Minimum Viable Setup
Before you add complexity, make sure this foundation works. Every B2B company should have these three things nailed before adding anything else.
Google Ads Conversion Tracking
Google Ads offers the most sophisticated B2B conversion tracking with GCLID-based attribution, enhanced conversions, and offline import capabilities.
1. GCLID Capture and Storage
The GCLID (Google Click Identifier) is the key to connecting ad clicks to CRM conversions. Capture it on every landing page visit.
JavaScript - GCLID Capture// Capture GCLID from URL and store in cookie/localStorage function captureGclid() {
const urlParams = new URLSearchParams(window.location.search);
const gclid = urlParams.get('gclid');
if (gclid) {
// Store for 90 days (Google's attribution window) const expires = new Date(Date.now() + 90 * 24 * 60 * 60 * 1000);
document.cookie = `gclid=${gclid}; expires=${expires.toUTCString()}; path=/`;
localStorage.setItem('gclid', gclid);
}
}
// Run on page load
captureGclid();
// Retrieve GCLID for form submission function getGclid() {
return localStorage.getItem('gclid') ||
document.cookie.match(/gclid=([^;]+)/)?.[1] ||
'';
} 2. Hidden Form Field Setup
Add hidden fields to all forms to capture GCLID and pass to your CRM.
HTML - Hidden Fields<!-- Add to your form -->
<input type="hidden" name="gclid" id="gclid" value="">
<input type="hidden" name="utm_source" id="utm_source" value="">
<input type="hidden" name="utm_medium" id="utm_medium" value="">
<input type="hidden" name="utm_campaign" id="utm_campaign" value="">
<!-- Populate on page load -->
<script>
document.getElementById('gclid').value = getGclid();
const params = new URLSearchParams(window.location.search);
document.getElementById('utm_source').value = params.get('utm_source') || '';
document.getElementById('utm_medium').value = params.get('utm_medium') || '';
document.getElementById('utm_campaign').value = params.get('utm_campaign') || '';
</script> 3. Enhanced Conversions for Leads
When GCLID isn't available (cookie deletion, cross-device), Enhanced Conversions uses hashed email to match conversions.
GTM - Enhanced Conversions Setup// In your form submission handler, push to dataLayer
dataLayer.push({
'event': 'form_submission',
'enhanced_conversion_data': {
'email': userEmail // GTM will hash automatically
}
});
// Configure in GTM: // 1. Go to Conversion Linker tag settings // 2. Enable "Enhanced conversions" // 3. Set user-provided data variable to {{enhanced_conversion_data}} 4. Offline Conversion Import
Import downstream conversions (SQL, Opportunity, Closed-Won) from your CRM back to Google Ads.
Offline Conversion Import Format (CSV)Google Click ID,Conversion Name,Conversion Time,Conversion Value,Conversion Currency
EAIaIQobChMI...,SQL,2026-04-10 14:30:00,5000,USD
EAIaIQobChMI...,Closed Won,2026-04-15 09:15:00,50000,USD LinkedIn Conversion Tracking
LinkedIn offers the Insight Tag for web tracking and Conversions API (CAPI) for server-side and offline conversions.
1. Insight Tag Installation (GTM)
GTM - LinkedIn Insight Tag<!-- Create a Custom HTML tag in GTM -->
<script type="text/javascript">
_linkedin_partner_id = "YOUR_PARTNER_ID";
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>
<noscript>
<img height="1" width="1" style="display:none;" alt=""
src="https://px.ads.linkedin.com/collect/?pid=YOUR_PARTNER_ID&fmt=gif" />
</noscript> 2. Event-Specific Conversion Tracking
JavaScript - Fire LinkedIn Conversion// Fire conversion on form submission function trackLinkedInConversion(conversionId) {
if (typeof lintrk !== 'undefined') {
lintrk('track', { conversion_id: conversionId });
}
}
// Example: Demo request form
document.getElementById('demoForm').addEventListener('submit', function() {
trackLinkedInConversion('12345678'); // Your conversion ID
}); 3. LinkedIn Conversions API (CAPI)
Server-side tracking for reliable conversion data and offline imports.
Node.js - LinkedIn CAPI Implementationconst crypto = require('crypto');
async function sendLinkedInConversion(email, conversionRuleId, conversionValue) {
// Hash email using SHA256 const hashedEmail = crypto
.createHash('sha256')
.update(email.toLowerCase().trim())
.digest('hex');
const conversionData = {
conversion: `urn:lla:llaPartnerConversion:${conversionRuleId}`,
conversionHappenedAt: Date.now(),
conversionValue: {
currencyCode: 'USD',
amount: String(conversionValue)
},
user: {
userIds: [{
idType: 'SHA256_EMAIL',
idValue: hashedEmail
}]
},
eventId: `${Date.now()}-${Math.random().toString(36)}`
};
const response = await fetch(
'https://api.linkedin.com/rest/conversionEvents',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${LINKEDIN_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
'LinkedIn-Version': '202401'
},
body: JSON.stringify({ elements: [conversionData] })
}
);
return response.json();
} Meta Conversion Tracking
Meta (Facebook/Instagram) tracking requires both the Pixel and Conversions API for reliable B2B attribution, especially post-iOS 14.5.
1. Meta Pixel Installation (GTM)
GTM - Meta Pixel Base Code<!-- Create a Custom HTML tag in GTM -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=YOUR_PIXEL_ID&ev=PageView&noscript=1"
/></noscript> 2. Standard Events for B2B
JavaScript - B2B Conversion Events// Demo Request (High Intent)
fbq('track', 'Lead', {
content_name: 'Demo Request',
value: 10000,
currency: 'USD'
});
// Content Download (Medium Intent)
fbq('track', 'CompleteRegistration', {
content_name: 'Whitepaper Download',
value: 1000,
currency: 'USD'
});
// Pricing Page View (Intent Signal)
fbq('track', 'ViewContent', {
content_name: 'Pricing Page',
value: 500,
currency: 'USD'
}); 3. Meta Conversions API (CAPI)
Node.js - Meta CAPI Implementationconst crypto = require('crypto');
async function sendMetaConversion(eventName, email, value, eventId) {
const hashedEmail = crypto
.createHash('sha256')
.update(email.toLowerCase().trim())
.digest('hex');
const eventData = {
data: [{
event_name: eventName,
event_time: Math.floor(Date.now() / 1000),
event_id: eventId, // For deduplication with Pixel
action_source: 'website',
user_data: {
em: [hashedEmail]
},
custom_data: {
currency: 'USD',
value: value
}
}]
};
const response = await fetch(
`https://graph.facebook.com/v19.0/${PIXEL_ID}/events?access_token=${ACCESS_TOKEN}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(eventData)
}
);
return response.json();
}
// Usage with deduplication const eventId = `demo_${Date.now()}`;
sendMetaConversion('Lead', 'user@company.com', 10000, eventId); event_id to both to prevent double-counting. Meta will deduplicate events with matching IDs within 48 hours.
HubSpot Form Tracking
HubSpot forms require specific configuration to capture ad click IDs and trigger platform pixels.
1. Hidden Fields for Click ID Capture
Add these hidden fields to all HubSpot forms to capture tracking parameters.
| Field Name | Property Type | Purpose |
|---|---|---|
| gclid | Single-line text | Google Ads click ID |
| li_fat_id | Single-line text | LinkedIn click ID |
| fbclid | Single-line text | Meta click ID |
| utm_source | Single-line text | Traffic source |
| utm_medium | Single-line text | Marketing medium |
| utm_campaign | Single-line text | Campaign name |
| utm_content | Single-line text | Ad/content variant |
2. Auto-Populate Hidden Fields
JavaScript - HubSpot Hidden Field Population// Add to your site's global JS, runs after HubSpot forms load
window.addEventListener('message', function(event) {
if (event.data.type === 'hsFormCallback' &&
event.data.eventName === 'onFormReady') {
const params = new URLSearchParams(window.location.search);
const fields = {
'gclid': getGclid(), // From stored cookie 'li_fat_id': params.get('li_fat_id') || localStorage.getItem('li_fat_id'),
'fbclid': params.get('fbclid') || localStorage.getItem('fbclid'),
'utm_source': params.get('utm_source'),
'utm_medium': params.get('utm_medium'),
'utm_campaign': params.get('utm_campaign'),
'utm_content': params.get('utm_content')
};
Object.keys(fields).forEach(function(fieldName) {
if (fields[fieldName]) {
const input = document.querySelector(
`input[name="${fieldName}"]`
);
if (input) input.value = fields[fieldName];
}
});
}
}); 3. GTM Trigger for HubSpot Form Submissions
GTM - HubSpot Form Submission Trigger// Create a Custom Event trigger in GTM // Event name: hsFormCallback // Then add this Custom HTML tag to capture submissions:
<script>
window.addEventListener('message', function(event) {
if (event.data.type === 'hsFormCallback' &&
event.data.eventName === 'onFormSubmit') {
var formId = event.data.id;
var formData = event.data.data;
// Push to dataLayer for GTM tags
dataLayer.push({
'event': 'hubspot_form_submit',
'hs_form_id': formId,
'hs_form_data': formData
});
}
});
</script> 4. HubSpot Workflow for Offline Conversions
Create workflows to send offline conversions when lifecycle stage changes.
Thank You Page vs Event-Based Tracking
Both methods have trade-offs. Use them together for complete coverage.
| Method | Pros | Cons | Best For |
|---|---|---|---|
| Thank You Page | Simple setup, URL-based triggers, works with any form | Misses conversions if page doesn't load, requires redirect | Backup tracking, simple forms |
| Event-Based | Fires immediately, captures more conversions, works with AJAX forms | Requires JavaScript, can be blocked | Primary tracking method |
| Server-Side (CAPI) | Most reliable, not blocked by browsers, enables offline import | More complex setup, requires backend integration | Critical conversions, CRM events |
Testing and Validation Checklist
Before launching campaigns, validate that all tracking is working correctly.
Pre-Launch Testing
Common Tracking Mistakes
Avoid these pitfalls that break B2B conversion tracking.
| Mistake | Impact | Fix |
|---|---|---|
| Not storing GCLID | Can't attribute offline conversions to Google Ads | Capture GCLID in cookie (90-day expiry) and pass to CRM |
| Missing conversion values | Platform optimizes for volume, not quality | Calculate values based on close rate x deal size |
| Only tracking form submissions | Losing attribution for CRM conversions | Implement offline conversion import for SQL/Opp/Won |
| No CAPI implementation | Missing 30-40% of conversions due to ad blockers | Add server-side tracking alongside Pixel/Tag |
| Duplicate events | Inflated conversion counts, bad bidding signals | Use event_id for deduplication between client and server |
| Cookie expiry too short | B2B sales cycles exceed tracking window | Use 90-day cookies, store click IDs in CRM |
| Thank you page only | Missing AJAX form submissions | Use event-based tracking as primary method |
| Not hashing PII | Privacy violations, potential fines | Always SHA256 hash emails before sending to APIs |
Need Help Getting This Right?
We've set up conversion tracking for 200+ B2B companies. Let's make sure your tracking actually connects to pipeline.
Talk to 42 AgencyThe argument behind the playbook
Related Resources
New playbook every other week
Join 3,500+ B2B marketers getting tactics from $50M+ in managed ad spend.
Subscribe to 42/ Newsletter