Monday, March 3, 2025
HomeAnalytics#GTMTips: Fix The Rogue Referral Problem In Single-Page Sites

#GTMTips: Fix The Rogue Referral Problem In Single-Page Sites


Single-page sites (or single-page apps) typically have just one page load. When navigating the site, subsequent content is either uncovered from the DOM, where it’s been in a hidden state, or loaded from the server using HTTP requests that do not invoke a new page refresh. This behavior, however, has some implications for Google Analytics tracking, especially when configured via Google Tag Manager.

The crux of the problem is this: When you create a Google Analytics tracker, the URL of the page (without a possible #hash) from when the tracker was created is sent as the value of the Document Location field with every hit that uses this tracker. This is used for a number of things, most significantly attributing the session to the campaign specified by URL parameters such as gclid (AdWords) or utm_source, utm_medium.

Now, on single-page sites you send “virtual” pageviews whenever new content is loaded from the server. The reason this works fine with on-page GA is because you’re always using the same tracker object to send the hits. Google even recommends this in their developer guide. Thus the Document Location field stays the same, and campaigns are attributed correctly.

With Google Tag Manager, every single Universal Analytics Tag that fires on the site creates a new, unique tracker object. This means that the Document Location field is updated with every Tag you fire, which is a problem if the URL changes due to browser history manipulation. Thus you can end up with a situation where the first Universal Analytics Tag has gclid in the URL, attributing the session to AdWords, but the next pageview doesn’t have this in the URL anymore, as you would not include it in the “virtual” pageview path names. Instead, since gclid is no longer in the URL, GA looks at the HTTP referrer of the page to see what the previous page was for attribution. It finds google.com, as you came from the search engine (HTTP referrer is not updated when manipulating the URL with the browser History API). Thus a new session starts with attribution to Google Organic! I’ve dubbed this as the Rogue Referral problem.

There are ways to combat this. David Vallejo’s written a great article on setting the Tracker Name in your GTM Tags. This will effectively work like on-page GA, maintaining the initial value of Document Location throughout the page load. However, there are some risks with the tracker name setting, so I wanted to offer an alternative.


X


The Simmer Newsletter

Subscribe to the Simmer newsletter to get the latest news and content from Simo Ahava into your email inbox!

Tip 51: Manually Set Document Location To Prevent Rogue Referrals

The way this works is that you store the initial page URL in a global variable such as dataLayer, and then manually set the Document Location field in all your Universal Analytics tags to use this variable.

The most robust way to do this would be to have the following in the page HTML before the GTM container snippet:

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  originalLocation: document.location.protocol + '//' +
                    document.location.hostname +
                    document.location.pathname +
                    document.location.search
});

This would store the original URL of the page (without #hash) into a dataLayer variable named originalLocation. Then, you’d add this to all your Universal Analytics tags by browsing to Fields to Set and adding a new field:

Field name: location
Value: {{Data Layer Variable – originalLocation}}

Here, {{Data Layer Variable – originalLocation}} would be a Data Layer Variable you’ve created, pointing to the originalLocation you store when the page is first loaded.

(UPDATE: Note that if you add the location field, you must also specify the page, or else all pages will use what’s stored in location as the page path sent to GA! If you have a single-page site, you probably already have the page field set to a virtual page path, but if not, you can always use something like:

Field name: page
Value: {{JS – Get Page URL}}

Where the variable {{JS – Get Page URL}} is a Custom JavaScript variable with:

function() {
  return document.location.pathname + document.location.search;
}

This would send the current page pathname with any query parameters as the virtual page path dispatched with your GA Tags. Thank you Brian Clifton for pointing out that query parameters should be sent, too.)

If you can’t or don’t want to edit the page HTML, you can also use Tag Sequencing. First, you would need to create a Custom HTML Tag with the same code as above (enclosed in

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments

Skip to toolbar