Bislam Sarymamedov
Table of Content

When working on digital marketing campaigns, tracking the source of your traffic is crucial for measuring the effectiveness of your efforts.
Capturing UTM parameters from URLs and storing them until a user converts is one effective method.
In this step-by-step guide, we’ll walk you through capturing UTM parameters on Webflow websites without any third-party plugins, storing them in the browser’s local storage, and ensuring they persist until conversion without needing HubSpot API calls.
This method leverages HubSpot’s built-in capabilities to scan URLs for UTM parameters and attach them to hidden form fields when found.
This way, we achieve a seamless setup without overly complex coding.
This method is suitable for any type of website.
In our case, the website was built on Webflow, so we had to adapt it accordingly.
Depending on your setup, you might need to make specific adjustments to accommodate your configuration properly.

lead source detection ubunzo

Step 1: Capture UTM Parameters from the URL

First, we need a function that extracts UTM parameters from the URL.

/ * ------------ Pass UTM parameters to user's Cookie ------------ * //
function () {
 // Helper function to get URL parameters
 function getUTMParams() {
   const params = new URLSearchParams(window.location.search);
   const utmParams = {};
   params.forEach((value, key) => {
     if (key.startsWith('utm_')) {
       utmParams[key] = value;
     }
   });
   return utmParams;
 }

Step 2: Store UTM Parameters in Local Storage

Once captured, store the UTM parameters in the browser’s local storage to ensure persistence. In this case we have also added a 60 day expiration date.

// Save UTMs to local storage for 60 days
 function saveUTMsToLocalStorage(utmParams) {
   const now = new Date().getTime();
   const expiry = now + 60 * 24 * 60 * 60 * 1000; // 60 days in milliseconds
   const data = {
     params: utmParams,
     expiry: expiry
   };
   localStorage.setItem('utm_data', JSON.stringify(data));
 }

Step 3: Retrieve Stored UTM Parameters

To utilize the stored UTM parameters, create a function to retrieve them from local storage. This function also checks if 60 day expiration period hasn't passed.

// Load UTMs from local storage if still valid
 function loadUTMsFromLocalStorage() {
   const storedData = localStorage.getItem('utm_data');
   if (storedData) {
     const data = JSON.parse(storedData);
     const now = new Date().getTime();
     if (now < data.expiry) {
       return data.params;
     } else {
       localStorage.removeItem('utm_data');
     }
   }
   return null;
 }

Step 4: Clean up URL

Remember, the HubSpot cookie only captures UTMs when they are present in the URL. Therefore, for pages without conversion forms, we can leave the URL field clean of UTMs until the user is redirected to the required page, allowing the HubSpot cookie to capture the UTM parameters where needed. The goal here is to keep URLs clean in the browser’s address bar so that, if a user shares the link elsewhere, any additional referral actions won’t interfere with the initial UTM tracking information.

// Remove UTMs from URL without reloading the page
 function removeUTMsFromURL() {
   const url = new URL(window.location.href);
   url.searchParams.forEach((value, key) => {
     if (key.startsWith('utm_')) {
       url.searchParams.delete(key);
     }
   });
   window.history.replaceState({}, document.title, url.pathname + url.search);
 }

Step 5: Check if there is a HubSpot form

This function checks if there is a HubSpot form on the page. Remember that UTMs will only populate on pages containing a HubSpot form, keeping the link clean on all other pages.

/* ------------ Append UTM Parameters to Internal Links ------------ */
// Check if current page contains .hbspt-form
 function pageContainsHbsptForm() {
   return document.querySelector('.hbspt-form') !== null; //.hbspt-form - is the HubSpot native class which we check in order to see if there is a form on the page
}

Step 6: Populate UTMs in URL if HubSpot form presented

Once we confirm that a HubSpot form is present on the page, the UTMs are retrieved from the user's local storage and added to the URL. This way, the HubSpot cookie can capture them when the user ultimately converts.

// Populate UTMs from local storage if present on pages with .hbspt-form
 function populateUTMsFromLocalStorage() {
   const utmParams = loadUTMsFromLocalStorage();
   if (utmParams && pageContainsHbsptForm()) {
     const url = new URL(window.location.href);
     Object.keys(utmParams).forEach(key => {
       url.searchParams.set(key, utmParams[key]);
     });
     window.history.replaceState({}, document.title, url.pathname + '?' + url.searchParams.toString());
   }
 }

Step 7: Clean Up Expired UTM Parameters

We set up this function to delete all UTM information from the local page once the user arrives at a specific page, such as a thank-you page, after converting via a HubSpot form.

// Fully delete UTMs and reload page
 function handleThankYouPage() {
   const isThankYouPage = window.location.pathname.includes('/your-url');
   if (isThankYouPage) {
     localStorage.removeItem('utm_data');
     if (!sessionStorage.getItem('utm_reloaded')) {
       sessionStorage.setItem('utm_reloaded', 'true');
       window.location.reload();
     }
   }
 }

Step 8: Initialize the Script

Finally, initialize the script to handle all the logic.

// Main script execution
 (function main() {
   const utmParams = getUTMParams();
   if (Object.keys(utmParams).length > 0) {
     saveUTMsToLocalStorage(utmParams);
   }

   // Remove UTMs from URL if .hbspt-form is not present
   if (!pageContainsHbsptForm()) {
     removeUTMsFromURL();
   }

   // Populate UTMs on pages with .hbspt-form
   populateUTMsFromLocalStorage();

   // Handle thank-you page logic
   handleThankYouPage();
 })();

Complete Code for Passing UTM Parameters into HubSpot Form's Hidden Fields in Webflow

Here's the complete code for passing UTM parameters into HubSpot form's hidden fields on the Webflow website.
Simply copy and paste this code into your Webflow' Custom Code footer section, do adjustments for your specific case and publish it.
You can test the Local Storage using Google Chrome's Inspect feature.
To check the Form Submission, please go to your Hubspot Dashboard.

/* ------------ Pass UTM parameters to user's Cookie ------------ */

(function () {
 // Helper function to get URL parameters
 function getUTMParams() {
   const params = new URLSearchParams(window.location.search);
   const utmParams = {};
   params.forEach((value, key) => {
     if (key.startsWith('utm_')) {
       utmParams[key] = value;
     }
   });
   return utmParams;
 }

 // Save UTMs to local storage for 60 days
 function saveUTMsToLocalStorage(utmParams) {
   const now = new Date().getTime();
   const expiry = now + 60 * 24 * 60 * 60 * 1000; // 60 days in milliseconds
   const data = {
     params: utmParams,
     expiry: expiry
   };
   localStorage.setItem('utm_data', JSON.stringify(data));
 }

 // Load UTMs from local storage if still valid
 function loadUTMsFromLocalStorage() {
   const storedData = localStorage.getItem('utm_data');
   if (storedData) {
     const data = JSON.parse(storedData);
     const now = new Date().getTime();
     if (now < data.expiry) {
       return data.params;
     } else {
       localStorage.removeItem('utm_data');
     }
   }
   return null;
 }

 // Remove UTMs from URL without reloading the page
 function removeUTMsFromURL() {
   const url = new URL(window.location.href);
   url.searchParams.forEach((value, key) => {
     if (key.startsWith('utm_')) {
       url.searchParams.delete(key);
     }
   });
   window.history.replaceState({}, document.title, url.pathname + url.search);
 }

 // Check if current page contains .hbspt-form
 function pageContainsHbsptForm() {
   return document.querySelector('.hbspt-form') !== null;
 }

 // Populate UTMs from local storage if present on pages with .hbspt-form
 function populateUTMsFromLocalStorage() {
   const utmParams = loadUTMsFromLocalStorage();
   if (utmParams && pageContainsHbsptForm()) {
     const url = new URL(window.location.href);
     Object.keys(utmParams).forEach(key => {
       url.searchParams.set(key, utmParams[key]);
     });
     window.history.replaceState({}, document.title, url.pathname + '?' + url.searchParams.toString());
   }
 }

 // Fully delete UTMs and reload page
 function handleThankYouPage() {
   const isThankYouPage = window.location.pathname.includes('/your-link');
   if (isThankYouPage) {
     localStorage.removeItem('utm_data');
     if (!sessionStorage.getItem('utm_reloaded')) {
       sessionStorage.setItem('utm_reloaded', 'true');
       window.location.reload();
     }
   }
 }

 // Main script execution
 (function main() {
   const utmParams = getUTMParams();
   if (Object.keys(utmParams).length > 0) {
     saveUTMsToLocalStorage(utmParams);
   }

   // Remove UTMs from URL if .hbspt-form is not present
   if (!pageContainsHbsptForm()) {
     removeUTMsFromURL();
   }

   // Populate UTMs on pages with .hbspt-form
   populateUTMsFromLocalStorage();

   // Handle thank-you page logic
   handleThankYouPage();
 })();
})();


/* ------------ End Pass UTM parameters to user's Cookie ------------ */

Site > Settings > Custom Code > Footer Code > Save > Publish
UTM link screenshot
Use test query at the end of your URL to check the functionality: ?utm_source=google&utm_medium=cpc&utm_campaign=test_campaign&utm_term=test_term&utm_content=test_content
how to check local sotrage
Right Click on the page > go to Inspect > Application > Local Storage > Your Website

Conclusion

By following these steps, you can effectively capture, store, and maintain UTM parameters in a user's browser storage until they convert.
This approach does not require any API calls, leveraging HubSpot’s built-in cookies to scan the URL for UTM parameters and attach them to hidden fields.
This ensures a seamless and efficient tracking setup for your digital marketing campaigns.

Be sure to email us at hi@ubunzo.com if you have any suggestions or would like to chat about this topic further.
This is an experimental solution we developed and decided to share with others who might face the same issues.
It's not ideal, and we will most likely update this code in the near future. For now, it works and meets our needs.
Hopefully, it will save you some time as well!

Share with others
FAQ

‍Tracking UTM parameters helps measure the effectiveness of your marketing efforts by identifying the source of your traffic, which is crucial for understanding which channels drive the most conversions.

UTM parameters are tags added to a URL to track the performance of campaigns and content across different traffic sources.

You can capture UTM parameters by using a custom JavaScript function to extract them from the URL.

Once captured, use a JavaScript function to store the UTM parameters in the browser’s local storage to ensure they persist until the user converts.

Create a function to retrieve the UTM parameters from local storage when needed.

our services

Choose a monthly subscription to get a full 3D team without the headaches of hiring—ideal for ongoing work and long-term collaboration. Or go with flat-rate projects for one-off needs, with clear timelines and set budgets. Simple, flexible, and built to fit your workflow.

3D Design
Service

3D Motion
3D Stills

Clear scope, fixed price, no surprises. Our 3D services are designed to be simple from the start—reasonable turnaround, clean execution, and results you can count on.

Why chose 3D design?

3D design isn’t just about making things look cool—it’s a practical, versatile tool that helps you communicate better, build trust, and market smarter. Whether you're launching, scaling, or just trying to stand out, 3D gives your brand an edge.
This is why

Stand Out From The Noise

Markets are saturated. Feeds are busy. 3D visuals cut through the clutter with bold, scroll-stopping imagery that makes your product feel modern and premium—without falling back on clichés or stock photos.
This is why

Explain Complex Ideas Fast

Whether it’s a tech product, physical object, or system in motion, 3D helps you tell the story in a way that’s clear and compelling. No long paragraphs, no flat diagrams—just clean, visual communication.
This is why

Make More With Less

A single 3D asset can turn into videos, stills, ads, web content, and more—without needing a full reshoot every time. It’s efficient, adaptable, and scales with your content needs.

who is & why ubunzo

Ubunzo is a 3D design studio built for teams that want results without the overhead. We're not a big agency with layers of managers and vague timelines. We're a tight team of designers, animators, and developers who care about doing good work—and doing it right.

Our clients include startups, B2B brands, e-comm, and tech companies that need strong visuals to pitch, launch, or grow. Some come for a single motion video. Others use our subscription like an in-house team—minus the hiring.

What sets us apart is how we work: clear communication, no fluff, and zero ghosting. We listen, we build, we deliver.

Our team is remote—spread from Alberta to Europe to Southeast Asia—so we stay nimble, cost-efficient, and fast. No office drama, no wasted time. Just a clean pipeline and solid results.

Launching your first product or your fiftieth? We’ll help you make it look great and work hard. That’s Ubunzo.