Analytics7 min read

HubSpot vs Chargebee UTM Tracking: Complete Setup Guide (2025)

HubSpot tracks UTMs perfectly until Chargebee checkout. Here's how to pass UTM parameters to Chargebee forms using sessionStorage + custom fields.

  • Analytics
  • Marketing Tech
  • Integration
  • Technical SEO
  • Hubspot Chargebee Utm Tracking
  • Chargebee Utm Parameters Checkout

HubSpot vs Chargebee UTM Tracking: Complete Setup Guide

HubSpot handles UTM tracking perfectly through marketing funnels. Chargebee checkout forms need explicit UTM data.

This guide shows you how to capture UTMs from HubSpot-tracked pages and pass them to Chargebee checkout using sessionStorage + custom fields.


HubSpot vs Chargebee: UTM Tracking Comparison

FeatureHubSpotChargebee
Native UTM capture✅ Server-side tracking❌ Requires custom fields
Browser cookie access❌ Server-side only❌ No native support
Multi-page persistence✅ Automatic❌ Needs JavaScript
Checkout attribution✅ Internal forms❌ External checkout

Key difference: HubSpot tracks server-side across your domain. Chargebee hosted pages live outside that tracking boundary.


Why Native Integrations Don't Solve UTM Tracking

Official Chargebee ↔ HubSpot syncs:

  • Customers ↔ Companies
  • Subscriptions ↔ Deals
  • Invoices ↔ Line items

Missing: UTM parameters, traffic sources, attribution data.

Third-party tools (Zapier) fail because:

  • No UTM data available at subscription trigger time
  • Adds monthly cost for incomplete solutions

Step-by-Step Implementation

Step 1: Create Chargebee Custom Fields (10 minutes)

Chargebee Dashboard → Settings → Custom Fields → Add:

utm_source (text)
utm_medium (text)
utm_campaign (text)
utm_term (text) 
utm_content (text)

These fields will capture attribution data on every subscription.

Step 2: JavaScript UTM Capture (30 minutes)

Add this script globally (footer, _document.js, functions.php):

// Capture UTMs from URL and persist across pages
function captureUTMs() {
  const urlParams = new URLSearchParams(window.location.search);
  const utms = {
    utm_source: urlParams.get('utm_source') || sessionStorage.getItem('utm_source'),
    utm_medium: urlParams.get('utm_medium') || sessionStorage.getItem('utm_medium'),
    utm_campaign: urlParams.get('utm_campaign') || sessionStorage.getItem('utm_campaign'),
    utm_term: urlParams.get('utm_term') || sessionStorage.getItem('utm_term'),
    utm_content: urlParams.get('utm_content') || sessionStorage.getItem('utm_content')
  };
  
  // Store in sessionStorage (survives navigation, cleared on tab close)
  Object.keys(utms).forEach(key => {
    if (utms[key]) sessionStorage.setItem(key, utms[key]);
  });
  
  return utms;
}

// Populate Chargebee form fields when checkout loads
function populateChargebeeUTMs() {
  const utms = captureUTMs();
  
  // Target Chargebee custom fields (cf_ prefix)
  ['source', 'medium', 'campaign', 'term', 'content'].forEach(param => {
    const field = document.querySelector(`[name="cf_utm_${param}"]`);
    if (field && utms[`utm_${param}`]) {
      field.value = utms[`utm_${param}`];
    }
  });
}

// Run on every page
document.addEventListener('DOMContentLoaded', captureUTMs);

// Detect Chargebee checkout load
const observer = new MutationObserver((mutations) => {
  if (document.querySelector('[name^="cf_utm_"]')) {
    populateChargebeeUTMs();
    observer.disconnect(); // Stop observing once populated
  }
});
observer.observe(document.body, { childList: true, subtree: true });

Step 3: Framework-Specific Deployment

WordPress:

// functions.php
wp_enqueue_script('utm-tracker', get_template_directory_uri() . '/js/utm-tracker.js', [], '1.0', true);

Next.js:

// pages/_document.js 
<Script id="utm-tracker" strategy="afterInteractive">
  {`(${utmTrackerScript.toString()})();`}
</Script>

Any SPA (React/Vue): Add to main.js or App.vue.

Step 4: Test Implementation (15 minutes)

  1. Visit: /campaign?utm_source=google&utm_medium=cpc&utm_campaign=blackfriday
  2. Navigate 3+ pages (UTMs persist)
  3. Open Chargebee checkout
  4. Submit test subscription
  5. Verify: Chargebee dashboard shows populated UTM fields ✅

Implementation Benefits

MetricBeforeAfter
Chargebee attribution0%98%+
Engineering timeN/A2 hours
Cross-domain tracking❌ Broken✅ Fixed
Mobile/SPA support✅ Full

Key advantages:

  • Works across page refreshes and navigation
  • No cookie consent issues (sessionStorage)
  • Handles direct traffic gracefully
  • Zero impact on page speed

Common Wrong Approaches (And Why They Fail)

ApproachProblemTime Wasted
Zapier syncNo UTMs at subscription trigger$50+/month
HubSpot formsPCI compliance requires Chargebee12+ hours
URL forcingBreaks Chargebee hosted pagesUX issues
Cookie readingHubSpot doesn't expose UTMs8 hours debug

The sessionStorage approach works because it's independent of both platforms.


FAQ: UTM Tracking Answers

Q: Does HubSpot-Chargebee integration include UTMs?
No. It syncs customers/deals/subscriptions only. Attribution needs custom implementation.

Q: Can I access HubSpot's traffic source from JavaScript?
No. HubSpot stores this server-side. Use URL parameters + sessionStorage instead.

Q: Does this work with Chargebee embedded checkout?
Yes. The MutationObserver detects any Chargebee form fields automatically.

Q: What about users with no UTMs (direct traffic)?
Fields stay blank. Direct traffic = direct traffic (correct behavior).

Q: Is sessionStorage GDPR compliant?
Yes. UTMs aren't personal data. No consent required.

Q: Works on mobile browsers?
Yes. sessionStorage is universally supported.

Q: What if Chargebee changes field names?
Update the cf_utm_ selectors in the JavaScript. Fields are fully customizable.

Written by

Abinesh S

Senior WebCoder

Front-end and WordPress engineer at FUEiNT. Writes about React and Next.js builds, PHP internals, search visibility and the tooling decisions behind them.

All 32 articles by Abinesh S
Next stepAnalytics

Want this done on your own site?

Tell us what you are trying to do in two sentences. You will get a straight answer, and if it is not work for us we will say so.

Back to the blog
ServiceSearch and AI visibilityGetting a site found by search engines and by the assistants people now ask instead.Open

Bring us the one everyone called impossible.

Messy, undocumented, half-migrated and business-critical is our favourite kind of brief. Write two sentences. You will get a straight answer and a way forward.

WhatsAppMessage us on WhatsApp
Visit12, Sri Vigneshwara Nagar, Amman Kovil
Saravanampatti, Coimbatore, TN, India — 641035

தெய்வத்தான் ஆகா தெனினும் முயற்சிதன்மெய்வருத்தக் கூலி தரும்.