Last updated 9 October 2020: customTask updated to a more stable version.

The Custom HTML tag in Google Tag Manager is splendid. It’s your go-to tool when you need to run arbitrary JavaScript on the webpage. Some might even use it to actually add HTML elements to the page, but I’m willing to bet running JavaScript is its most common use.

However, there’s a downside to Custom HTML tags, which is only made more apparent on single-page apps which do not clear the full page when transitioning from one state to another. Custom HTML tags are injected to the end of <body>, which means you might end up with a lot of clutter in your Document Object Model.

In this article, I’ll show you a pretty neat trick. We’ll use customTask to run a “dummy” Universal Analytics tag, whose only purpose is to execute your JavaScript code when the tag is triggered. This way, nothing is injected into the DOM, and the only overhead you’ll run is the initial effort of creating the Google Analytics tracker.


The Simmer Newsletter

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

Tip 94: Trigger custom JavaScript without using a Custom HTML tag

The way it works is fairly simple if you understand how customTask works. This is what a sample function might look like:

function() {
  return function(model) {
    // Prevent hit from being sent
	model.set('sendHitTask', null);

    // The code you want to execute
    var xhr = new XMLHttpRequest();'POST', '/endpoint', true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({'key': 'abc12345'}));

The first few lines of the closure simply prevent the tag from doing anything. They null every single value stored in the model object, including all the tasks. This way once the customTask finishes, the hit builder will no longer do anything else (such as build and send the hit). That’s why I call it a “dummy” tag.

After // The code you want to execute is where you’ll add the JavaScript you want to run. In this example, I’m firing a simple HTTP POST request to an endpoint on my server.

The tag itself can be any Universal Analytics tag. All it needs is the Tracking ID (can be anything you want since the hit will never be dispatched) and the customTask in its field, like so:

As you can see, the tag is extremely simple. Its only purpose is to execute the JavaScript in the customTask variable.

The other critical thing is the trigger. Use the trigger to establish when the JavaScript should be executed. In the example above, when the nonIdle event is pushed into dataLayer, the tag will run the code within {{JS - function - Increase counter}}.

To summarize, this method seeks to address the following malady:

Aside from looking hideous, every single element dynamically inserted into the DOM forces a reflow of the page, which becomes cumulatively more and more expensive the more elements are being added.

By avoiding DOM injection, the JavaScript function is run within the bowels of Google Tag Manager’s container (where it’s compiled into a function) and analytics.js (which builds the hit).

This way, you’ve essentially created a JavaScript Function Tag, whose only purpose is to trigger the execution of JavaScript code.

customTask strikes again! Do you think you’ll have uses for a hack like this? Let me know in the comments.