42 Agency
Technical Guide

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.

Google Ads LinkedIn Meta HubSpot
4
Platforms Covered
90 Days
GCLID Lookback
3x
Better Attribution
ROAS
Based Bidding
Our take

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.

PriorityConversion TypeWhat 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.
Warning: Never optimize Google Ads for page views. You'll get great CPMs and zero pipeline. We've seen it happen dozens of times.

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

ConversionClose RateAvg Deal: $50KValue
Demo Request20%$50,000 x 0.20$10,000
Pricing Page + Form15%$50,000 x 0.15$7,500
Webinar Registration5%$50,000 x 0.05$2,500
Content Download2%$50,000 x 0.02$1,000
Newsletter Signup0.5%$50,000 x 0.005$250
Warning: Without conversion values, platforms optimize for volume. You'll get more newsletter signups (cheap) and fewer demo requests (expensive but valuable). This is why B2B campaigns often fail.

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.

1
Google Tag Manager
Central control for all tags
2
Enhanced Conversions
Server-side with email hashing
3
CRM Integration
Click IDs stored in HubSpot/Salesforce
42's Rule: Don't add complexity until this works. No fancy multi-touch attribution models. No CDP. No data warehouse. GTM + enhanced conversions + CRM integration. Get this right first.

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
API Upload (Recommended): For automated imports, use the Google Ads API to upload conversions in real-time when CRM stage changes. HubSpot's native Google Ads integration can do this automatically.

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 Implementation
const 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(); }
Best Practice: Use both Insight Tag (client-side) and CAPI (server-side) together. CAPI catches conversions that client-side tracking misses due to ad blockers or cookie restrictions.

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 Implementation
const 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 Deduplication: When using both Pixel and CAPI, pass the same 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 NameProperty TypePurpose
gclidSingle-line textGoogle Ads click ID
li_fat_idSingle-line textLinkedIn click ID
fbclidSingle-line textMeta click ID
utm_sourceSingle-line textTraffic source
utm_mediumSingle-line textMarketing medium
utm_campaignSingle-line textCampaign name
utm_contentSingle-line textAd/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.

HubSpot Workflow Setup
Trigger: Lifecycle stage becomes SQL
Condition: GCLID is known
Action: Webhook to Google Ads offline import API
Trigger: Lifecycle stage becomes Opportunity
Action: Webhook to LinkedIn CAPI with opportunity value
Trigger: Deal stage becomes Closed Won
Action: Webhook to all platforms with actual deal value

Thank You Page vs Event-Based Tracking

Both methods have trade-offs. Use them together for complete coverage.

MethodProsConsBest 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
Recommendation: Use event-based tracking as primary, thank you page as backup validation, and server-side CAPI for all high-value conversions and CRM lifecycle changes.

Testing and Validation Checklist

Before launching campaigns, validate that all tracking is working correctly.

Pre-Launch Testing

Google Ads
Tag Assistant shows Google Ads tag firing
GCLID captured and stored in cookie
Test form submission creates lead with GCLID in CRM
Conversion appears in Google Ads within 24 hours
Enhanced Conversions showing matched status
LinkedIn
LinkedIn Insight Tag Helper shows tag active
Conversion events fire on form submission
CAPI test event returns 200 response
Conversions appear in Campaign Manager within 48 hours
Meta
Meta Pixel Helper shows Pixel active
Standard events fire with correct parameters
CAPI events appear in Events Manager Test Events
Deduplication working (no double events)
Event Match Quality score is Good or Great
HubSpot Integration
Hidden fields populated on form load
Form submission triggers GTM events
UTM parameters stored on contact record
Lifecycle stage change triggers offline conversion workflow

Common Tracking Mistakes

Avoid these pitfalls that break B2B conversion tracking.

MistakeImpactFix
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
The Biggest Mistake: Treating B2B tracking like B2C. In B2B, the real conversion (closed deal) happens weeks or months after the click. If you only track form fills, platforms optimize for the wrong outcome.

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 Agency
Further reading on 42/

The argument behind the playbook

42/ Essay

Enterprise GTM fails when you measure

When measurement theater replaces real insight.

42/ Essay

Forecasting in demand generation

Why pipeline math usually lies.

Related Resources

New playbook every other week

Join 3,500+ B2B marketers getting tactics from $50M+ in managed ad spend.

Subscribe to 42/ Newsletter