Tracking utm parameters in HubSpot forms

Tracking utm parameters in HubSpot forms

I had an interesting question from a client about the option to track utm_ parameters from URLs into HubSpot, capturing them via HubSpot forms.

They had a promotion campaign in place and a landing page was being promoted via an industry site. The industry site had set the URL to use a bunch of their own utm parameters, and my client wanted to be able to view signups that had come from that particular site.

In this case my client wanted to be able to capture the utm parameters and view them on each individual contact.

What are utm parameters?

utm_ parameters are the extra bits that are added to a URL to include source and campaign data. Here’s an example of a URL with utm parameters in green:

In this example there are 4 utm parameters in place: utm_campaign, utm_source, utm_medium and utm_content.

For a fuller description of how utm parameters are used, Google’s URL builder page has some good examples.

For building your own URLs with utm tracking parameters, HubSpots tracking URLs builder is an easy way to organise and generate them (look for it from your HubSpot Reports section).

Capturing URL parameters

HubSpot already captures URL utm_ parameter details behind the scenes, however these aren’t viewable on the individual contact details. Instead they are used in reports for consolidating the details. You can drill down into Campaign results via Sources reports to see the list of contacts that came via a particular campaign, but there’s no way to select the contacts from Contact search. Nor any way to see the utm parameters on the individual contact profiles.**

In order to view them on individual contacts, we need to set up a process to capture them. The following sections detail a way to set this up (but note the caveats section at the end).

There’s two main steps for setting up HubSpot to track the utm parameters:

  1. Add contact custom properties
  2. Add the contact custom properties as hidden fields on your form(s)

BTW this process will work with any parameters in URLs (ie not just utm_ parameters) but for the sake of this post, we are just discussing utm_ examples (see also this HubSpot KB article).

1. Adding utm parameter custom properties

The first thing to do is add custom properties for each utm parameter you want to track.

From Contact settings, start by adding a new property, using the exact name of the utm parameter in the label:

Adding HubSpot contact properties

Note: I had already created a new Group called XEN Hidden, just for grouping together all my hidden field properties.

Do this for each of the utm parameters. The naming is important – the custom property label must exactly match the utm parameter you wish to track.

Use Single-line text field as the Field type, and make sure they are available for use in forms.

After adding them all you’ll have a group of them like so:

HubSpot custom contact properties

You can edit any of them if required:

Edit HubSpot contact custom properties

BTW, later after the field has been used in forms you can click on the Analytics tab to give you an overview of how many contacts have this property filled:

HubSpot contact custom properties analytics

2. Adding utm parameter fields to forms

The next step is to add the new custom fields to your form(s).

Add the fields to your form, and set them to be hidden:

HubSpot form adding hidden fields

The label should match the utm parameter that is to be tracked.

Here’s how a form looks with all 5 of my utm parameter custom contact properties added as hidden fields:

HubSpot form fields

Make sure the fields are optional (ie don’t set them to be required), and don’t set them to be smart (ie we always want them to be rendered in a form).

And you’re done. Save the form and the next time it is used, the form will look for the utm parameters in the URL and insert them into the hidden fields.

Viewing utm parameter fields on contacts

Now that the new custom fields are being set to track, you can add them to contact listing and profile layouts.

These fields can be added to contact listing columns and summary field layouts:

HubSpot CRM contact fields

One advantage of having the fields on the contact summary field list is you can easily hover over the history ‘clock’ icon to their right to see a full log of their history:

HubSpot CRM field history log


There’s a few things to note with this tracking:

  • the utm parameters will get overwritten by later form submits ie if a visitor returns later (via another URL with different utm parameters) the utm custom properties will be overridden with the latest
  • but you can always check the custom field history to see the log of changes


17 SEO Myths
Craig Bailey

Craig is the Founder and Technical Director at XEN Systems. He’s been involved in IT, web development and digital marketing for more than 25 years.

15 thoughts on “Tracking utm parameters in HubSpot forms

  1. Emily says:

    It seems as though this solution is not working for leads who come to the site with utms and click on more than one page before converting on a form (utms disappear from url and are stored in the cookies).

    Once the utms disappear from the url string, those utms cannot be pulled into the hidden forms via the form?

      • Jon Eric says:

        I know I’m a month late to the conversation – anyway to make that work? Some type of script code to embed in a C2A button that would pass the UTM parameters? I just need it to pass for one page.

        • JK says:

          Am also having a request similar like Jon Eric.

          @Eric: This is the custom script am using but its only works when the clickable element is HREF tag.

          function updateQueryString(uri, key, value) {
          var re = new RegExp(“([?&])” + key + “=.*?(&|$)”, “i”);
          var separator = uri.indexOf(‘?’) !== -1 ? “&” : “?”;
          if (uri.match(re)) {return uri.replace(re, ‘$1’ + key + “=” + value + ‘$2’);}
          else {return uri + separator + key + “=” + value;}

          var links = $(“a.external-link”);
          for(var i = 0; i < links.length; i++) {
          links[i].href = updateQueryString(links[i].href, "utm_source", "{{utm_source}}");
          links[i].href = updateQueryString(links[i].href, "utm_campaign", "{{utm_campaign}}");
          links[i].href = updateQueryString(links[i].href, "utm_medium", "{{utm_medium}}");
          links[i].href = updateQueryString(links[i].href, "utm_term", "{{utm_term}}");
          links[i].href = updateQueryString(links[i].href, "utm_content", "{{utm_content}}");

          I done this via GTM and you need to create the variables which used above(utm_source, medium, campaign, term, content)

          Any tips on passing the UTM on button click guys?

          • JK says:

            To add one more point: This request is not about Hubspot storing this value but the UTM need to be in the final landing page URL.
            Because most cases hubspot landing pages are under subdomain.
            This way tools like salesforce or internal CRM tools can query UTM from page URL

  2. Matt Buckley says:

    Hi Craig,

    Great post. Do you know if this technique will work with an embedded HubSpot form, or does it have to live on a complete HubSpot landing page?


    • Craig Bailey says:

      Hi Matt – yes, this will work with embedded forms – our main XEN site is in WordPress, and our client had a custom enterprise CMS they used, and it works with both of those systems. Cheers, Craig

  3. Ed says:

    Hi Craig,

    as others have mentioned, a script is needed within the respective page in order to parse the parameters to the form. Can you confirm this?



    • Craig Bailey says:

      Hi Ed,
      It depends.
      The script is needed if you want to track the utm parameters through their journey on the site eg if they land on one page and then fill out a form on another page – that will require a script to keep the variables for their session.
      However if the page they land on has the form and they fill it out then you don’t need the script. This second simpler scenario is the one my post refers to. So if you are sending traffic to a landing page that converts pretty well, this will be a good solution.
      Hope this helps.

  4. hugh gordon says:

    Hi Craig,
    Thanks for this post, very helpful!
    Do you have any suggestions for how to create an additional custom property in Hubspot, to record the first touch UTM values, which would not be overwritten by subsequent visits/form submissions by the same user?

  5. Bob says:

    You can create a second set of contact properties, one for each UTM variable. Label them ‘Original’, i.e. ‘utm medium – original’ etc.
    Now create a workflow for each variable, that enrolls contacts with the following criteria:

    – utm_medium = known
    – utm_medium – original = unknown

    The only action this workflow does, is populate the ‘original’ field with the value from the field that gets updated all the time. And since the enrollment criteria is that the ‘original’ field is unknown, it will only happen once when the contact first enters the database.

    You can now use the ‘Original’ field to track what piece of content originally drew someone to your world, and the other field to track the most recent entry (for example to determine what piece of content eventually convinced someone to purchase).

    • Craig Bailey says:

      Thanks for this Bob.

      This will work when there’s also a script to keep the utm parameters in the cookie (ie as per Ed’s comment).

      However in the case where an anonymous person arrives and then moves about the site, by the time they submit a form on another page the utm parameters will be lost (ie if there’s no script to keep them in the cookie).

      However, once the utm parameters are initially set, this workflow will work well for keeping the original values, given that the contact may come back for later visits (and with new utm parameters in those later visits).

      Many thanks,

    • Hailey says:

      Bob – This is exactly what I’m trying to do. I’m wondering if you can explain what your workflow looks like a little more. I get what you’re going for – but not sure what the action of the workflow is.

      So set enrollment of the workflow to be :
      – utm_medium = known
      – utm_medium – original = unknown

      But what after that? Have the workflow perform a property change? Or simply having that workflow with the enrollees will make sure that the ‘original’ field gets populated that first time?

      Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.