here here here

title picture for article

Flagging internal remote users in GTM

When your workforce is mostly remote, how do you exclude them from results?

It was all so easy in the old world. You could just add an IP filter to your Google Analytics view and suddenly all of your average-skewing internal traffic to your site would be gone.

But now most teams have a large proportion of remote work, so how do we filter out developers and project managers from our data when we know they are refreshing pages endlessly and making a mess of our "time on site" averages?

At Polestar, we use a set of signals that in any one session would definitely mark out a user standing apart from a "regular" web user, and then persist that information long term.

The most successful signal for us is if anyone visits a staging or a development server. All types of non-production servers at Polestar are protected behind various mechanisms, so if you successfully load a web page on one of these domains, you're definitely beyond a level of suspicion of being an "internal" user. We start with a GTM variable (we'll call it "visitor type - cookie" for now) that returns the value of a cookie called "gtm.visitorType", and then use that in another GTM variable that evaluates it and adds some logic:

// GTM var "visitor type - var"
function() {
// if the user type is cookied
if ({{visitor type - cookie}}) {
return {{visitor type - cookie}};
// spot the users coming in to staging/dev or are debugging
} else if ({{Page Hostname}}.includes('stage') || {{Page Hostname}}.includes('local')) {
return 'internal';
return 'public';

This is checking for a long-term cookie first (only the internal users will be cookied, limiting the consent required), and if no cookie is found, it checks if the host was any non-production url (stage, localhost, etc), before returning what type of visitor this is - although there's currently only two types - "public" and "internal".

A GTM tag/trigger combination then fires if the variable is "internal" but no cookie is found - a sure sign that we've just caught a new internal user at the start of their session. This tag sets a long term cookie to complete the cycle, and it means we don't need to re-evaluate them from now on. I'm normally an advocate of using local/sessionStorage, but in this case a cookie is the best tool, as localStorage is scoped to a single sub domain (eg www.google.com), whereas an appropriately set first-party JS cookie can cover the whole domain (eg google.com), so that it can be set on one subdomain (eg stage.google.com) and then read it back on a different subdomain (eg www.google.com).

<!-- trigger for this tag set for when the {{visitor type - cookie}} is undefined & {{visitor type - var}} is NOT "public" -->
(function() {
var visitorType = '{{visitor type - var}}';
if (visitorType && visitorType !== 'public') {
// Set cookie for all subdomains for one year.
document.cookie = 'gtm.visitorType={{visitor type - var}}; path=/; max-age=' + (60*60*24*365) + '; domain=.polestar.com';

The last thing we do is to include this piece of information (The GTM variable "visitor type - var") in any GA hit data, for instance in Universal Analytics we add it to the GA settings variable in GTM as a custom dimension scoped to the user. In GA4, we send it as a user parameter. Setting it as a user scoped dimension means you'll be able to filter (or segment) out these users as long as they have that device until it's cookies are cleared or the browser obfuscates the GA cookie.

Caveats #

It's not a perfect solution - visiting production URLs in incognito mode will make you look like a normal non-alien user again.

Then there is the question of multiple devices. Because we're only using cookies, we're only flagging internal users per device, which might at least capture those devs doing responsive design testing on their phones, but probably not the copywriter checking their update to the news page on the bus to pick up the kids.

And that's where we need more signals...

More signals that can flag internal users #

<!-- trigger for this tag set for when the {{Page URL}} contains 'flag-as-internal' -->
// Set cookie for all subdomains for one year.
document.cookie = 'gtm.visitorType=internal; path=/; max-age=' + (60*60*24*365) + '; domain=.polestar.com';

Building an audience #

Remember it's a game of odds, you need to reduce the amount of internal users to bring your average metrics back to reality, so spotting 80% of internal users is probably good enough. I like to flag internal users instead of remove them from results, as it gives another level of context to the data, a story of it's own.