One of the big mysteries in browser-based data collection platforms like Google Analytics is what happens when the visitor is not being tracked. This is most obvious in cases where the user explicitly opts out of tracking, when the user does not have JavaScript active in their browser, in bounced sessions, and on exit pages.

Opt-outing means that the user explicitly prohibits a website from tracking them. In some cases, it’s possible that opt-out is the default, and the user must explicitly opt-in to allow GA to record their visits. In this article, I will of course not give you ideas how to circumvent this, as you must respect the user’s wishes.

Browsing with JavaScript disabled is surprisingly common, even though it makes a large part of the web unusable. If you disable JavaScript in your browser, the browser will no longer be able to run script blocks or arbitrary JavaScript functions. DOM methods still work, for example, but you won’t be able to use persistent storage such as cookies in your GTM container.

Bounced sessions and exit pages are problematic, since certain metrics such as Time on Page can only be calculated with two pageviews. This means that bounced sessions, which have a maximum of one pageview, will not be able to tell you how much time a visitor spent on your site. Similarly, an exit page does not have a subsequent pageview, which means that time on page is lost for these as well.

I’ve got two use cases I want to explore. Because I want to keep things short(er than usual), I’ve split this into two articles. The first one, this, concerns sending pageview hits from browsers with JavaScript disabled.

The second article (read it here) covers using User Timings to capture time on page for bounced sessions and exit pages.

I’m implementing both use cases using Google Tag Manager. As usual, these articles aren’t just about tackling specific GA use cases. They’re also about introducing cool JavaScript APIs and lesser-known Google Analytics features to the non-developer public.


The Simmer Newsletter

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

Collect pageviews from non-JS browsers

To collect pageviews from browsers where JavaScript has been disabled, we’ll need to leverage a number of advanced features of both Google Tag Manager and Google Analytics. The steps we’re going to take are these:

  1. Add a dataLayer key-value pair into the iframe of the noscript element in the GTM container snippet.

  2. Use a Custom Image Tag to fire a Measurement Protocol pixel when this dataLayer key-value pair is detected.

  3. Filter these MP hits into their own Google Analytics profile.

(NOTE: The point of this solution is to show how the iframe can be used to leverage the Data Layer Variable in GTM. There’s actually a much more elegant way to check if the user doesn’t have JavaScript enabled in their browsers. Check Duncan’s comment below for the solution!)

This means that when a browser that’s disabled JavaScript enters the site, the noscript tag is executed, and the dataLayer key-value pair causes the Custom Image Tag to fire. This tag is a pageview hit to the Universal Analytics endpoint using Measurement Protocol. This way you can collect data from visitors who have JavaScript disabled!

1. Edit the container snippet

So, the first thing you need to do is edit the container snippet. When a browser without JavaScript tries to render the container snippet, it will not execute any of the code within the script element. Instead, it finds the noscript block, and renders the contained HTML code.

Google Tag Manager loads an iframe, which is tailored to your container. By passing key-value pairs as query parameters to this iframe, you add data into the internal data model of Google Tag Manager, and it can be used by the Data Layer Variable even on browsers without JavaScript enabled.

So, in this use case, I want to send a key-value pair to Google Tag Manager, which I can then use as a Trigger condition to fire a Tag only for browsers which render the iframe. As you can see below, I’m sending nojscript=true to GTM. This is the non-JavaScript equivalent of dataLayer.push({'nojscript' : 'true'});

2. Data Layer Variable for nojscript

Next, we’ll need a Data Layer Variable that accesses this key-value pair, and a Custom Event Trigger which fires the tag when nojscript=true is found in the data model.

This Data Layer Variable will retrieve the value of the key nojscript from the data model if such a key exists.

3. Custom Event Trigger

The Trigger which fires the Tag when nojscript=true looks like this:

As you can see, the Event for the Trigger is still gtm.js. This is the equivalent of the “All Pages” Trigger. However, you need to specify a new condition, which demands that the Data Layer Variable for nojscript resolve to true.

So, quick recap. Now we’ve modified the container snippet to push nojscript=true into Google Tag Manager’s data model when the user’s browser does not have JavaScript enabled. Then, we have a Data Layer Variable which picks up this information from the data model. Finally, we have a Trigger which fires any Tag it is attached to, when the value of nojscript is true.

4. Custom Image Tag

Now, we need the Tag itself. Create a new Custom Image Tag:

Use the Trigger you just created as the only Trigger for this Tag.

Custom Image Tags are still supported even if the visitor’s browser does not use JavaScript. This is because the special iframe document that is loaded in the noscript can still render normal HTML tags, which an img very much is.

The URL of the img tag is a Measurement Protocol pixel call. If you know your Universal Analytics, you’ll know that every single hit from your web properties uses the Measurement Protocol, since it’s basically just a pixel that is loaded from the URL All the fields and settings for each hit are provided as parameters to this call. So, this is what the Measurement Protocol hit for the Custom Image Tag would look like:{{Page URL}}&dt=No%20JavaScript&cid={{Random Number}}&tid=UA-XXXXXXX-X&gtm=GTM-XXXX

This sends a very simple pageview hit with no extra parameters or dimensions. The Document Location, which GA uses to parse the page path from, is taken from the {{Page URL}} Built-In Variable, the Document Title of the page is “No JavaScript”, and the Client ID of the hit is a random number, generated by another Built-In Variable. Remember to substitute your own Google Analytics tracking code for the &tid= parameter. Also, if you want to mimic other GTM hits, add the &gtm= parameter with your container ID.

Add any other parameters you might like to. For the full list of available parameters, see this guide.

I use “No JavaScript” as the page title because I use that to create the Include filter in Google Analytics:

Naturally, you’ll want to add a similar Exclude filter to your main reporting profiles.

In the Measurement Protocoll call, we can’t use a stored client ID in the hit, because cookies are inaccessible in browsers where JavaScript is disabled. This means that you will not be able to stitch hits together as sessions, or sessions as users. Each hit is a new session, essentially. This is why it won’t make sense to include these hits in your main reporting profile.

There are ways around this restriction. You’ll need to build a server-side script which takes the client ID from the _ga cookie sent with each GET request, and renders this as another URL parameter in the iframe URL in the GTM noscript snippet. However, this is way beyond the scope of this simple guide.

Once you publish this setup, you should end up with a profile in Google Analytics collecting pageview hits from all visitors who do not have JavaScript enabled in their browsers. You can use this data to get an idea of just how many hits you are actually missing because of these over-cautious visitors. You can also use the average for Pages / Session to get an estimate of how many sessions these hits comprise.


The idea behind this guide was to introduce the elusive noscript tag of the GTM container snippet. You can use it to push key-value pairs into Google Tag Manager’s data model, and you can then use this information to fire any Tags you want to reserve for users without JavaScript.

If you have marketing platforms that have specified a <noscript> alternative, you would use this solution to compile the image tag that’s usually provided as the JavaScript-less option.

Remember to come back in a little time to read the next part of this guide: how to get an accurate time on page metric for bounced sessions and exit pages!