In Google Analytics, the utm_source URL parameter is mandatory when you’re trying to capture campaign parameters.

Even if your URL has utm_campaign and utm_medium on it, GA will not capture the Campaign and Medium data if you are missing utm_source.

If your Google Analytics tagged campaigns are not capturing Campaign / utm_campaign data, then it might be because of this missing utm_srouce parameter. Even great resources like the “troubleshooting missing acquisition sources” post from Bounteous leave out this reason.

The diagram below shows how GA handles campaign & traffic source reporting when certain URL parameters are missing. This will clarify how it misclassifies campaign links that are missing utm_source:

From https://support.google.com/analytics/answer/6205762?hl=en#zippy=%2Cin-this-article

Note that, if you are missing utm_source, the traffic source processing does go on. One of the next conditions that GA checks is the presence of a Referrer.

If the browser passes a Referrer to your page and utm_campaign is present on the page URL, GA will disregard the Campaign and will treat the visit as having Medium = “Referral” and Campaing = “(not set)”. The source will be tied to the Referral value. I have done some testing, and this is what actually happens within GA reports.

As an example, if an external page is linking to a URL like this
https://yoursite.com/demo-page?utm_medium=GoogleAds&utm_campaign=CENTRAL-productA-webinar
your traffic from it will looks something like this in the Google Analytics report:

Despite specifying utm_medium, the absence of utm_source means that the Source becomes “referral”

Can I see the raw URL in Google Analytics?

If you are trying to find the historical traffic for utm_campaign when utm_source is missing from the URL, you’re out of luck.

There is no spot in Google Analytics where you could still get the raw URL of the request (and see traffic associated with the other utm_ parameters you had there). GA hides those parameters from the “Page” URL it shows in reports.

You can capture this data on a going forward basis. To do that, create a Hit-level custom dimension for the full URL in GA. Then, set up Google Tag Manager to capture the “location” value of each page into that dimension, in the tag with your Google Analytics code.

Remediation: how to override utm_source with Google Tag Manager

So, now you are in a situation where many of your campaigns could be sending traffic, but this traffic gets misclassified without your knowledge.

Their tracking URLs might be missing utm_source, but you’d never know because they are getting classified as Source = (not known) or as Referral traffic (if a referrer is passed).

To allow you to see Campaign and Medium information for this traffic, you can override utm_source with Google Tag Manager. Our aim is to add a utm_source of our own whenever it is missing. Then, you will be able to see which Campaigns need their tracking links to be fixed.

Here is the 3 part setup. It assumes that you use Google Tag Manager to put the Google Analytics code onto your webpages.

Step 1: set up a Trigger – utm_campaign present, utm_source not present

To keep things simple, let’s create a trigger that fires only when your URL does have utm_campaign but is missing utm_source.

Set it up as in the screenshot below (it is a Page View trigger event, firing on specific pages – those where the URL contains utm_campaign AND the URL does not contain utm_source)

Step 2: create a Tag that fires up a modified GA code

Next, we will create the Google Analytics tag that will be fired up whenever we see the trigger scenario from above.

We need to set up the tag so it plugs in our own manually-provided utm_source value to make up for the fact this field is missing. To do this, I took inspiration from the steps described by Adil Khan in this GA parameter post here (archived version).

Next, copy your Google Analytics Tag and customize the field called location (1 below). For simplicity, we will just set the location to the current URL (2) and append &utm_source=your-manually-set-value at the end (3). This approach works because we already know that there is at least a “?” on the URL due to the presence of a utm_campaign parameter.

In the example below, at (3), I chose to set all Sources to “unspecifiedSource” whenever a source is missing. This will make it easy for me to pull a report on all traffic from “unspecifiedSource” in the future – and to finally figure out which campaigns have badly configured tracking URLs.

Finally, configure this tag to fire when the Trigger you set up in the previous step is activated.

Caveat: by simply adding a parameter to the end of the URL, we might be messing up any URLs that have an anchor identifier in them (one of the parts that look like #this). That portion with the hash needs to be the last part of the URL.

There is an easy way to add a campaignSource variable into the GA tag, but I didn’t get success with it. I believe it is because all the other source/campaign parameters I was passing were through the utm_ URL, rather than through the analytics.js fields like campaignMedium. So there was a mismatc..

Step 3: prevent the regular GA tag from firing when your special trigger matches

If we leave things as-is, you will have GA tags double-firing whenever a page with utm_campaign & without utm_source is loaded.

Go to your main GA tag (which presumably fires on All Pages), and set up your Trigger from step 1 as an Exclusion trigger.

Note that your Exclusion Trigger needs to be of the same Event type as the Trigger you use to load that main GA tag. Basically, it means that if your main GA tag is triggered on Pageview, it can only be blocked by another Trigger that runs on Pageview. More about event types and blocking Triggers here.

Gather visitor data and find the Campaigns with malformed tracking links

Once you put in place the 3 elements above, Preview your GTM setup. Take the URL of a page on your site and add utm_campaign while leaving out utm_source. Check that:

  1. Your visit appears in the Real Time “Content” report in Google Analytics
  2. Your visit is only counted once (the regular GA Tag gets blocked)
  3. Your Source shows up as the manually defined value you set (your altered GA Tag is firing). Below is what I saw with my setup using “unsepcifiedSource” value for Source.

Set aside some time to gather visits. Then, run a GA report to show you all the Campaign and Medium data for traffic from the manually set Source you chose (“unspecifiedSource”). Now you will be able to trace back which of your campaigns are missing the Source utm parameter and need to have their tracking URLs fixed.

Thanks for reading!
Please share your comments / challenges / insights below 👇