Sean Henri
Written By:

Today’s buyers conduct most of their research online, making it critical that you’re able to understand how people are finding your website, which marketing channels are producing the best results, how your content is performing, and where your greatest opportunities for optimization lie. This analysis is critical if you are going to be successful in inbound marketing and inbound sales.

2022 Update: While this solution technically still works, in most cases a solution like this should no longer be needed. HubSpot has significantly upgraded their native tracking and analytics solutions since the original publishing of this article. Read more about Hubspot's recently released Latest source property.

Google Analytics is an invaluable tool for gaining these types of insights. Every time an anonymous visitor goes to your website, Google Analytics automatically detects the specific source that led them there—whether that be a Google search, Facebook, or a referral from an online industry publication. These sources are also automatically grouped into broader marketing channels, called Mediums, which often include organic, CPC, social, referral, email, and direct.

Reviewing this data regularly will help you and your team understand which marketing channels produce the greatest volume of leads and inquiries, and the average cost-per-acquisition for each of these channels, allowing you to adjust your marketing plans to achieve the greatest return on investment (ROI).

While tracking your visit-to-lead conversion rate and average cost-per-acquisition for each marketing channel is a smart move, it doesn’t necessarily tell if you the marketing channel producing the most leads is also the marketing channel producing the most customers. To analyze this data, you must be able to track the original source all the way through the sales pipeline to the time the deal is made and the contract is signed. The problem: Google Analytics isn’t designed for this. It’s scope is mostly focused on the top of your funnel, and typically only goes as far as the form submission.

Once that lead is thrown over the fence to your sales team, your customer relationship management system (CRM) typically becomes the primary tool that tracks the progression of that lead towards becoming a customer.

In order to close the loop and truly determine which traffic sources, content, and campaigns are producing the greatest ROI, you need to find a way to integrate Google Analytics and your CRM.

If you’re using a marketing automation platform like HubSpot, Marketo, or Pardot, this SHOULD be incredibly easy, but unfortunately, some of these systems require a little bit of setup. In this blog post, we’re going to drill into how to do this with HubSpot. If you’re a Marketo or Pardot customer, stay tuned, as we have a solution for you as well. Out of these three solutions, HubSpot handles closed loop reporting right out of the box, but still has some gaps that we’ll address today.

The Challenge: HubSpot Only Tracks The Original Source

2022 Update: This is no longer true. We are preserving this article for those who still wish to try this method out.

HubSpot was designed around the idea that if you create content that educates and facilitates your buyer’s journey towards a purchase, those potential buyers will reward you by giving you their email address in exchange for some valuable resource like a downloadable guide, and then convert into a customer after a series of emails.

In this perfect scenario, the original traffic source of what brought that visitor to your site may be all that you need. HubSpot does a phenomenal job at providing this information in the Sources report, which breaks down your visitors, contacts, and customers by the original traffic source that brought them to you.

HubSpot Sources Report

This information is incredibly valuable to just about every HubSpot user, but there are two scenarios when it might not be enough:

  1. When you’ve pre-loaded your database with contacts because your targeting a very narrow, niche market.
  2. When you’re deploying a prolonged, multi-channel campaign with multiple touches over multiple months.

In scenario 1, a contact may exist in your database for years before they finally engage with your content and convert, but it won’t matter if it was organic search, social media, or cpc that pulled that lead in—HubSpot will still list the source as “Offline Sources.” This makes it very difficult to understand the ROI of your campaigns.

In scenario 2, original source will still carry some weight, but it might be just as important to know which source pushed someone over the edge. If a remarketing ad increases your odds of progressing a contact from a Lead to a Marketing Qualified Lead (MQL) by 50 percent, you’d probably want to know that right?

The Solution: Add Last-Touch Data from Google Analytics Traffic Source Dimensions

By default, Google Analytics attributes conversion to the last campaign or traffic source that brought a user to your website. This means that a single person can visit your website 100 times in a single year and not convert, but if on their 101st visit they decide to convert after clicking on a paid social media ad, that ad will get 100 percent of the credit.

Google breaks the traffic data down in the following way:

  • Source: The specific website or source that triggered the visit. Examples include Facebook or Google.
  • Medium: The broader marketing channel that the source belongs to. Examples typically include organic, cpc, email, or referral.
  • Keyword: If the click came from a paid search ad, this will reflect the keyword being targeted.
  • Content: The individual link, ad, or call-to-action that was clicked. This allows you to distinguish multiple links or ads on the same page.
  • Campaign: The campaign name associated with the marketing effort.

This got us thinking. If we can append the Campaign, Source, Medium, Content, and Term values to the HubSpot form submission, we can have a clear view of what acquired the contact in the first place, and what triggered their most recent conversion. Eureka!

The Other Challenge: Google Analytics No Longer Stores This Data in a Local Cookie

In the classic version of Google Analytics, traffic acquisition data like source, medium, campaign content, and keyword were stored in a local cookie called _utmz, set by the classic ga.js tracking code.

Do a quick Google search and you’ll find tons of scripts that were designed to extract the values from the cookie and pass them into hidden form fields. For a while, this solved the problem.

Unfortunately these scripts no longer work because with the new version of Google Analytics, called Universal Analytics, all tracking happens at the server-side and the cookie set by the new analytics.js contains no information about the user’s traffic sources.

Technically, the classic Google Analytics tracking script still works, so you could simply place the old version on your site until Google no longer supports it.

Since this isn’t a good permanent solution, we chose to go with a script created by e-nor, which mimics the classic Google Analytics cookie and can be found here. With the tracking script problem resolved, we can now focus our efforts on extracting that data from the cookie and passing them to hidden fields in a HubSpot form.

Making It All Work: Step By-Step-Instructions

The next section of this post gets pretty technical. If you’re comfortable working with Google Tag Manager and customizing javascript, read on. If not, forward a link to this blog post to a developer who can assist.

1. Create Custom Fields in your CRM

You’ll need to create at least 5 custom fields in your CRM where the traffic source data will be stored. If using Salesforce, you may want to create these on both your Lead and Contact objects so the values can carry over when a lead is converted to a contact. If you’re using HubSpot, you’ll only need to do this once.

  • GA_Medium
  • GA_Source
  • GA_Campaign
  • GA_Term
  • GA_Content
  • Landing Page—this is an extra field that will be used to tell us what page on your website the user landed.
  • Conversion Page—this field will tell us the URL of the page where they converted.

Alternatively, you can label them Last-Touch Medium, Last Touch-Source, etc. If you change the names, be sure to modify the script in step #6 to match your custom names.

2. Add the Fields to your Forms

Add the same fields created in the previous step to all forms you wish to integrate with Google Analytics. Since these should not be visible to the user, be sure to mark them as hidden.

HubSpot Hidden Fields

3. Deploy the Clone Classic Google Analytics Cookie

Download a copy of e-nor’s javascript to mimic the Classic Google Analytics tracking script cookie behavior. This will be customized in the next step.

4. Modify The Javascript to Work With Your Domain

Open the script you just downloaded in your favorite editor, and modify the line that looks like:

var domains = [“”, “”]; Change mydomain to any top-level domains that this script will be deployed on. This allows you to implement cross-domain browsing so session data will persist across multiple top-level domains.

5. Download and Deploy The Extraction Script

This is the magic bullet that extracts the traffic source data stored in our mimicked Google Analytics cookie, and then passes those values to hidden HubSpot form fields, allowing us to pass that data along with the lead throughout their journey in our CRM.

If you chose to use different labels for your custom fields, you’ll want to modify the field labels referenced in the script to match your own.

// 2 second delay to let Google Analytics cookies load
    setTimeout(function () {

        // Split the GA cookie
        var GATrafficSource = (function () {
            var pairs = (/(?:^|; )__utmz=([^;]*)/.exec(document.cookie) || []).slice(1).pop().split('.').slice(4).join('.').split('|');
            var vals = {};
            for (var i = 0; i < pairs.length; i++) {
                var temp = pairs[i].split('=');
                vals[temp[0]] = temp[1];
            return {
                'utm_source': (vals.utmgclid) ? "google" : vals.utmcsr,
                'utm_medium': (vals.utmgclid) ? "cpc" : vals.utmcmd,
                'utm_campaign': vals.utmccn,
                'utm_content': vals.utmcct,
                'utm_term': vals.utmctr

        // Find and split campaign name cookie
        function readCookie(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) == ' ') c = c.substring(1, c.length);
                if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
            return null;
        var campaignName = /[^(=)]*(?=\|utmcmd)/.exec(readCookie('__utmz'))
        var conversion_page = window.location.pathname;
        var landing_page = window.location.pathname;

        // Create cookie function
        function setCookie(cname, cvalue, exdays, path) {
            var d = new Date();
            d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
            var expires = "expires=" + d.toGMTString();
            document.cookie = cname + "=" + cvalue + "; " + expires + ";;" + "path=" + path;
        // If cookie is empty, create cookie. This should be one loop.

        if (readCookie("source") === null) {
            setCookie("source", GATrafficSource.utm_source, 1, '/');
        if (readCookie("medium") === null) {
            setCookie("medium", GATrafficSource.utm_medium, 1, '/');
        if (readCookie("content") === null) {
            setCookie("content", GATrafficSource.utm_content, 1, '/');
        if (readCookie("keyword") === null) {
            setCookie("keyword", GATrafficSource.utm_term, 1, '/');
        if (readCookie("campaign") === null) {
            setCookie("campaign", campaignName, 1, '/');
        if (readCookie("landing_page") === null) {
            setCookie("landing_page", landing_page, 1, '/');

        // Conversion page cookie is rewritten every page load
        setCookie("conversion_page", conversion_page, 1, '/');

	// Add cookie info to hidden fields for web to lead fields
      }, 2000); // The 2 second delay from the beginning

6. Deploy Scripts Through Google Tag Manager

Deploy both the Cloned Classic Google Analytics Cookie script and the Extraction script through Google Tag Manager on any page of your website you wish to include with this solution. In most cases this should be all of the same pages you’re tracking with Google Analytics.

7. Run Some Tests

As a rule of thumb, you should always test any code deployments locally in your browser using Google Tag Manager’s Preview and Debug feature. While in debug mode, you can verify that the values are being set by exploring the source code or using an extension like Hidden Form Finder.

If you’ve implemented everything correctly and you’re using the Hidden Form Finder extension, you should see the blank fields when your form loads. To test what values appear

8. Publish and Monitor

Now that you have a working solution that you’ve tested and validated, it’s time to unleash it into the wild. Be sure to go back and check the results of your data after a few days or weeks to be sure that you’re getting the results you expected, and then revise accordingly.

Enjoy Closed Loop Reporting!

With this solution you’ll be able to analyze the effectiveness of your marketing efforts like never before. Good luck and be sure to share your results, comments, questions, and suggestions for improvements in the comments.

Subscribe to The Stack

Stay Updated

Join our email list to get a weekly digest of the latest content published by the Pepperland Marketing team.

Other Content You Might Enjoy

How to Create a Social Media Calendar to Plan your Content

How to Create a Social Media Calendar to Plan your Content


In today's digital landscape, where social media has become an essential platform for communication and engagement,...

read more
How To Build a Strong Social Media Team in Higher Education

How To Build a Strong Social Media Team in Higher Education


Social media has become an essential part of our daily lives and transformed the way higher education institutions...

read more
Avoid Burnout as a Higher Education Social Media Manager

Avoid Burnout as a Higher Education Social Media Manager


Burnout has become an increasingly common problem for social media specialists in higher education. According to Inside...

read more
5 Types of Content to Include in your College's Instagram Strategy

5 Types of Content to Include in your College's Instagram Strategy


As enrollment marketers, we are constantly trying to find new ways to reach potential students. The new generation of...

read more
6 Examples of Successful Higher Education Instagram Campaigns

6 Examples of Successful Higher Education Instagram Campaigns


Executing unique Instagram campaigns is just as important as your routine daily posts. Even though the two may seem...

read more
24 Statistics Proving The Power Of Instagram In Higher Education

24 Statistics Proving The Power Of Instagram In Higher Education


As more college-aged students join Instagram, using the platform as a marketing tool grows more beneficial....

read more