In Google Tag Manager, the Custom JavaScript variable is an anonymous function with a return
statement. It does not take any parameters, and by default it’s impossible to pass any parameters to it, because the Custom JS variable is simply resolved to whatever value the function returns. If it returns a number, for example, passing a parameter to it would make no sense and would result in a TypeError
since the variable resolves to a number, not a function.
However, you can actually have the variable return a function. You can use this to create your own utilities, which take parameters and, in turn, return some new value based on the calculations done with the variables.
This isn’t a novel discovery - variables returning functions are at the core of how things like hitCallback
and customTask
work. In this article, I’ll explain a bit further what you can do with these utility variables.
The Simmer Newsletter
Follow this link to subscribe to the Simmer Newsletter! Stay up-to-date with the latest content from Simo Ahava and the Simmer online course platform.
Tip 97: Create utilities with the Custom JavaScript variable
A function which returns a function has plenty of use in JavaScript. It’s sometimes called a closure because it has access to the lexical scope of the wrapping function even after that function has ended execution.
In Google Tag Manager, using the function as a closure isn’t necessarily the biggest perk, because Custom JavaScript variables are designed to be ephemeral - simply processing things in scope (e.g. other variables), and then returning the result of this processing.
However, when you return a function which accepts parameters in a Custom JavaScript variable, you can create a utility that can be invoked from Custom HTML tags and other Custom JavaScript variables without having to always rewrite the same code in all the places you need to the utility.
For example, let’s say you want to create a browser cookie in a Custom HTML tag. You have some options:
<script>
// Option 1: Create a global method
window._setCookie = function(name, value, ms, path, domain) {
if (!name || !value) {
return;
}
var d;
var cpath = path ? '; path=' + path : '';
var cdomain = domain ? '; domain=' + domain : '';
var expires = '';
if (ms) {
d = new Date();
d.setTime(d.getTime() + ms);
expires = '; expires=' + d.toUTCString();
}
document.cookie = name + "=" + value + expires + cpath + cdomain;
};
window._setCookie('someCookieName', 'someCookieValue');
// Option 2: Directly call the document.cookie API
document.cookie = 'someCookieName=someCookieValue';
// Option 3: Use a Custom JavaScript variable
{{Set Cookie}}('someCookieName=someCookieValue');
</script>
Option 1 creates a utility method, too, but it adds it to the global namespace. Yes, this has the added benefit of being available to all your Custom HTML tags and Custom JavaScript variables, and actually any other script running on your site, even outside GTM. Assuming these other tags and scripts run after the _setCookie
global method has been created with this tag, that is.
The downside is that you’re polluting the global namespace. You’re reserving a key that might be overwritten or accessed by any other JavaScript running on the site. If only scripts within GTM need this method, you’d be better off with some other solution.
Option 2 is simple in that you don’t need a function at all, you’re directly writing the cookie. With the example above it’s really the simplest way to go about it. However, as soon as you need to do some extra processing, such as determining on which domain or path to write the cookie or what its expiration should be, you’ll add lines and lines of code, and all of these lines need to be rewritten in any other tag where you also want to write a cookie.
Option 3 is what this article is about. Instead of adding the _setCookie
method into the global scope of the page, you can use Google Tag Manager’s Custom JavaScript variables to handle the logic for you. The variable would look like this:
function() {
return function(name, value, ms, path, domain) {
if (!name || !value) {
return;
}
var d;
var cpath = path ? '; path=' + path : '';
var cdomain = domain ? '; domain=' + domain : '';
var expires = '';
if (ms) {
d = new Date();
d.setTime(d.getTime() + ms);
expires = '; expires=' + d.toUTCString();
}
document.cookie = name + "=" + value + expires + cpath + cdomain;
}
}
As you can see, it’s almost the same as Option 1, except instead of assigning the function to a global variable, you’re returning it in the Custom JavaScript variable. And because you return the function, you can then invoke it with the parameters name, value, ms, path, domain
, and have the function handle writing the cookie for you.
Assuming you’ll name that Custom JavaScript variable as Set cookie variable, this is how you would invoke it from a Custom HTML tag or a Custom JavaScript variable:
{{Set cookie variable}}('cookieName', 'cookieValue', 100000, '/', 'simoahava.com');
This is just one example. You could also…
-
Create a SHA-256 hashing function (thanks Johan Terpstra for the link to the source code), which encrypts any string passed to it.
-
Create simple utilities such as string reversal, array equality checks, and converters.
-
Write callbacks for custom event listeners.
In summary, a Custom JavaScript variable which returns a function is useful if you want to…
-
Avoid polluting the global namespace.
-
Avoid rewriting the same code over and over again. and/or c) having a number of similar variables doing almost the same thing.
-
Avoid having a number of similar variables doing almost the same thing.
The last point is especially powerful, as instead of having five different Custom JavaScript variables, you could use a single Custom JavaScript variable, returning a function which takes a parameter, and this function would then return one of five different outcomes, depending on the parameter.
Just remember that you can only run JavaScript in two contexts within GTM: Custom HTML tags and Custom JavaScript variables. So you can’t add parameters to a Custom JavaScript variable in regular tag, trigger, or variable fields.
Do you have any cool utility functions you’d like to share with the readers?