site logoTune The Web

I've written a book! - click here to view or buy "HTTP/2 in Action" from Manning. Use code 39pollard to get 39% off!

Adding controls to Google Tag Manager

This page was originally created on and last edited on .


Google Tag Manager (GTM) is extremely popular and is used by 22% of all websites. As it's name suggests, it allows managing of marketing tags on a website. Marketing departments love these tags as they allow them to track their marketing campaigns and see if they are directing their budgets to the right places. So if they buy a lot of Facebook ads, they like to see how many people come to the site (which can be measured by clicks on the ad) but also crucially if those clicks led to anything: typically purchases or sign ups. This requires linking the click from the ad, to an action on specific pages (e.g. confirmation pages). So this usually requires adding of a piece of JavaScript to the confirmation page. Similarly remarketing tags involve telling an ad agency that someone was looking at a product on your site, and then the ad agency using that information to display ads for that product, or similar ones, to try to entice you back to finish that purchase. This requires a small snippet of JavaScript on the product page which fires off a call to the ad agency and then they take care of showing appropriate ads when it sees the same user on another site.

How to add these JavaScript snippets depends on how the website is set up and what Content Management System (if any) is used to publish the site. Often it requires web developers to release the snippet onto a page, or to fire it on a certain action. And often these snippets change slightly each time they launch a new ad campaign. Rather than having to go to web developers each time they want to add or change tracking tags to their site, the marketing department can ask the web developers to add the GTM JavaScript snippet once to all pages, and then manage the tags in there. GTM allows you then to fire tags based on various triggers so it will only load the appropriate tags on the appropriate pages at the appropriate times (on page load, when an event occurs, or whatever). So you can fire a Google Adwords snippet if the URL contains "checkout-complete.html" for example, and can even grab hold of the products purchased and send them to Google Adwords.

This all sounds well and good, and frees up web developers to do real web development and allows marketing to do their job. Everyone's happy. However there are some serious downsides to using a tag manager like GTM: in particular security and performance. By definition tag managers allow injection of scripts and code into the website. JavaScript is a really powerful language and can fire off requests to ad agencies, or change the entire look and feel of the webpage or... well pretty much anything really! So that means that, by definition, anyone who has access to GTM has access to inject JavaScript and so, in effect, has full control of the website

Some would recommend never using a tag manager for these reasons, and on certain sites or pages that makes total sense. However the reality is that marketing is a large part of most businesses so while that might be the right technical answer to address security and performance issues, it often is not a realistic one and web developers who try to argue that, often fail. In this post I want to explain some options as to how to add some control back to GTM usage to reduce the risks inherent in them, without going to the extreme of disallowing them completely. This post is about Google Tag Manager but much of the advice will apply to other tag managers, or even those placing tags on their pages manually. I am less familiar with other tag managers so don't know if they offer the same functionality as GTM, so some of these tips may not be possible with them, or they might allow other ways of adding back control.

One thing I'm going to stay completely out of in this post, is the whole ethics of tracking people on the internet and the problems with third party cookies...etc. There are valid privacy concerns and points to be made in those areas, but I'm ignoring them for this post. As I said previously, the reality is that many websites use marketing tags, and tag managers to manage them, and this post is only intended to show how website owners and developers can add some more control to them while still giving the ability to use them. If you can take marketing tags off your website completely, and don't need GTM, then great for you and no need to read further, but for those of us interested in security and performance who are concerned about GTM, but have to use it, then this post could help you feel a little more comfortable with them.

Security Concerns

So let's talk about security first as there's a few things to cover here. As I mentioned previously, giving the ability to put JavaScript on a page, basically gives over full control of the website to whoever has access to put it there. That is an enormous amount of power that is being handed over, and there are security risks even if you totally, 100% trust whoever you are giving access to - which you shouldn't btw as no one is totally, 100% trustworthy, least of all marketing people who's job it is to track you in any way possible :-)

Marketing departments are not staffed with expert web developers with a deep understanding of HTTP and JavaScript, so they often outsource this work to marketing agencies who will manage all their marketing activities for them. These marketing agencies love GTM as it allows them to do their jobs easier, and so they will often push to get this set up to make it easier to manage tags. However if you do this, and give them full, unrestricted access, then you have now given up full control of your website to an external agency (or agencies). This all leads to multiple security concerns. You have now implicitly (explicitly?) trusted another company with full control of your site. Another company staffed by people you may never have met. Now I'm sure marketing agencies are mostly staffed by diligent, hard working people, who just want to do the job they are being paid for, but that is beside the point. The risk is there and the risk is larger the more control you give up. Giving full control of your company website to an external company is a step too far in my book.

So what exactly are the security risks? Well JavaScript could be used to harvest personal data, like credit cards or passwords from a webpage. Even if you don't put GTM on payment or login pages, it could read cookies giving over full login access. It can be used to deface your webpage. Imagine a banner with "Your company sucks!!" suddenly appearing on your home page, or something less subtle that takes a while to spot. Or it can be used to mine bitcoins, launch a DDOS attack against someone or anything else. Now you might say that, that is unlikely and you trust your marketing department or marketing agencies and they would never do this, but it doesn't need to be done intentionally. They can be tricked into copy the wrong JavaScript, or the JavaScript it calls can be hacked. Web skimming attacks like Magecart have landed a string of high profile companies like TicketMaster, British Airways and Newegg. Now I'm not saying those rogue bits of JavaScript were inserted though GTM, but having a tool that allows inserting of JavaScript obviously opens a greater risk of this.

Security risks can also be more accidental in nature. GTM allows you to grab information off the page. So you could say get the Country of the purchaser, which is the 5th field on the checkout form and send that in the tracking tag. Then if the tag is called on a wrong page, or the checkout form is redesigned, then suddenly you could be grabbing the credit card details or other highly sensitive data and sending it to a marketing partner. That could lead to all sorts of PCI or GDPR or other local legislative problems, fines, and reputational damage! All because GTM gives full access to the page.

Performance Concerns

Even if there are no security risks (and there definitely are!), marketing tags can have a serious performance impact on your site. Web developers can spend a huge amount of time carefully crafting performant code which loads super quickly, and that's blown away with hacked together marketing tags jumping in at the beginning, and then using up all the processing power the browser has. This is especially relevant with more and more browsing happening on mobile devices often with limited network capabilities and potentially less processing power (not everyone runs the latest high powered iPhone!).

You can measure the impact of this yourself or use a tool like to measure this, but it is a serious problem. The sheer amount of tags, and the impact they have can be eye opening! Below screenshots show a site I worked on, that was loading almost 4 times as much third party content as first party content and that once we'd cleaned it up total load times dropped to a third, and was a lot less variable:

Many sites can load more third party requests, than first party! Third party javascript can have a large impact on performance

Marketing agencies will tell that scripts are written with performance in mind and use asnyc attributes, but that's the least they could do (if they use defer then I'd be more impressed that they knew what they were talking about!). Loading, processing and handling resources has a real cost - especially JavaScript, and throwing an async attribute in it doesn't magically make them free.

Breaking your Site Concerns

As well as slowing your website, third party content can also break your website. I've seen marketing tags that load jQuery, overriding the version of jQuery used by the site, and replacing it with one that is incompatible with the site's code. This led to the site not working due to the incompatible version. I've also seen Internet Explorer reduced to a crawl by some marketing JavaScript that obviously hadn't been tested on it, and was making thousands of failed call attempts. Developing performant JavaScript that works in all browsers takes skill, and those that write this code in marketing agencies may not have those skills, or may not see performance as a priority.

Can you add control to GTM?

OK so what can we do about all this? Many web developers or IT departments feel powerless to address their legitimate tag manager concerns. When they raise them, they are overruled or just ignored. However I believe this is just another problem to solve, and one side asking to turn it off and the other side refusing to, is ignoring the problem instead of solving it. There are things you can do if you work with the marketing team to make both of you happy while also not limiting them from doing their jobs. You will have a much higher chance of success if you limit the impact of any controls, rather than trying to insist on a lockdown they will not agree to. Gareth Clubb from the Telegraph recently publish a fantastic post about setting a performance culture up their company and breaking down silos. Reading this prompted me set up a regular forum with the marketing team at work again, after we'd let this lie for a bit after the last clean up. We had put a lot of work into solving this problem a year or so after a spate of skimming attacks on websites were in the news - not ours thankfully, we were just being proactive here! I'd been meaning to write this blog post since then, to help others in our situation. There are sensible changes you can make, without blocking tags or GTM completely. What follows is a list of 12 actions you can undertake to bring some control to GTM and your marketing tags, and when we put them in place I certainly felt a lot more comfortable with having the necessary marketing tags on our website.

Tip 1 - Own your GTM Account

Often marketing agencies will set up a GTM container for your site under their GTM account. While trying to be helpful, this should be a moved to a GTM account that is owned by the website owner and not the marketing agency. This then allows you to set up appropriate permissions. Without owning this yourself, it is impossible to lock down administrators (covered next) or even move to another marketing agency if you want. Luckily GTM makes this very easy to transfer. In settings the whole container can be exported from one account, and then imported into another account. This will give you a new GTM container id (GTM-XXXXX) so will require updating all your web pages to reference this container id instead of the old one.

Also if you manage several sites, even if related and under the same parent brand, you should set up a separate container ids for each. We used to have one container id for multiple sites, but it made it more difficult to see if tags were used, and meant people had access to sites they didn't need to. Split them out. In a similar manner to migrating to different accounts, you can export the shared GTM container and upload to a new container for the second site, and then delete the tags, triggers and variables not needed for that site.

Tip 2 - Set Appropriate User Access Permissions for GTM

One of the most important things you can do to bring control to GTM, is to ensure only the appropriate people have access to it. GTM has a good user management model, with the ability for everyone to have their own account and then permissions. Permissions can be set at the account level and the container level. Account level permissions are basically Users, or Administrators (who can add other users). External partners, and non-technical users should only be Users and never Administrators. This is one reason for Tip 1.

Container level permissions can be one of four settings:

How you use these permissions is up to you. What probably makes most sense for some companies who use marketing agencies is to allow the agencies have Edit or Approve permissions, and then have someone in your company actually review and publish the change. This should really be someone in IT because of the power of GTM, but if you lock this down further with some of the other suggestions, you may be comfortable for marketing to publish tag additions themselves.

Tip 3 - Audit user access regularly

It should go without saying that you should regularly audit user access to remove people and agencies who have left their roles. It should go without saying, but it needs to be said, as it's far too easy to forget to do this. Again depending on how you use GTM, it may give full access to your website, so that access should be controlled, and that includes removing access when people no longer require it.

Tip 4 - Clean up unused tags regularly

It is entirely possible (likely even!) that you will have legacy tags that may not even be needed any more. Work with your marketing department and agencies to clean them up. This may be painful, it may take a long time, but will have the biggest impact and make subsequent steps easier. The above graphs show the huge gains that can be made - mostly from simply not running tags we weren't even using anymore. Also remove unused Triggers and Variables regularly. The less that is in GTM, the easier it is to maintain.

Tip 5 - Categorise your tags

When cleaning up your tags, you probably came across tags that you couldn't find out where they came from or why they were added. Use Folders in GTM to categorise all Tags, to an owner, to make this job easier in future. You'll thank yourself for it. If you can't find why a tag is on your page, and no one owns jup to it, then you can Pause that tag until you find an owner. If no one comes forward, then that's one more tag you've cleaned up :-) Folders will make this easier in future so you can go directly to the owner to confirm if it's still being used.

Tip 5 - Review when triggers fire

Marketing love to have their triggers fire as early as possible. They figure tracking people going to a page is more important than loading the page. I disagree. So review your GTM triggers. Are they firing immediately on Page View? If so can they be delayed until the later "Page View - DOM Ready", or maybe even the "Page View - Window Loaded" event that happens after that? This then gives the actual contents of the page more browser resources to load. This could mean a reduction in tracking if people happen to click away from the page while it is still loading and you need to decide if that is acceptable but I strongly feel the priority should be on the page, and marketing tracking can wait. Your company may disagree, but that recent Telegraph post on this topic that I mentioned earlier, had an interesting observation when they deferred third party JavaScript:

We can say with confidence though that deferring our JavaScript hasn’t skewed any existing analytics and it certainly hasn’t delayed any advertising. By using custom performance marks in the advertising code, deferring JavaScript and reducing bundle sizes, the First Ad Loaded metric improved by an average of four seconds.

So defering third party JavaScript actually improved how long they took to load as all the JavaScript wasn't fighting with each other! Now granted this was for Advertisements, rather than tracking beacon calls, but it's still interesting.

Tip 6 - Review GTM pages

Do you need GTM on all pages? Or can you remove it from more security sensitive pages? Is your Login Page where people enter passwords, for example one, that marketing really cares about or could they live without it? Of course if you login through a component that is on every page, then that may not be an option. Similarly pages where people enter personal details, or payment information maybe could live without GTM - though if part of a Single Page Application, as many Checkout flows are, then again this may not be possible to restrict as the Checkout flow is probably one of the key pages you want GTM for. Still, it's worth reviewing and asking if it's needed on every page.

Tip 7 - Push data to the GTM Data Layer

GTM variables are used to set triggers or send parameters to tags. These may be set by information that GTM has access to (e.g. URLs) or may be based on information on the page (e.g. a product in your basket). GTM is extraordinarily powerful in that it provides full access to the DOM or allows custom JavaScript to be run to set these variables, or even access to global JavaScript variables. As discussed previously, this introduces security concerns that private data (personally identifiable data, credit card information, passwords...etc.) could intentionally, or even accidentally be scraped off the page and sent to a third party. So instead of using GTM to pull data from the DOM this way, make your web pages and web applications push data to the GTM data layer. This will make it easier to use it in GTM, make them more robust as less likely to break if you change your application and where data is located in the DOM or displayed on screen. Additionally, as this is controlled by the page pushing data, this means that you can control exactly what is (and is not) pushed to the Data Layer, rather than allowing everything to be grabbed and hoping nothing sensitive is. You can then restrict direct DOM or JavaScript access from GTM which we'll cover later.

To push items to the data layer will require code changes to your web page, but assuming you are willing to do that it's relatively simple. For static server, side generated pages, you can set these by intialising the dataLayer variable before loading the GTM tag on the page:

<script> dataLayer = [{ 'pageCategory': 'signup', 'visitorType': 'high-value' }]; </script> <!-- Google Tag Manager --> ... <!-- End Google Tag Manager -->

For dynamic client-side applications you can use code like below to push variables to the GTM data layer:

dataLayer.push({ 'color': 'red', 'conversionValue': 50, 'event': 'customizeCar' });

GTM can then assign GTM variables from the Data Layer, or can even listen for Data Layer changes with a CustomEvent trigger.

Tip 8 - Investigate pixels as an alternative to tags

Marketing tags started their life as image pixels, but now often use JavaScript to get access to get more details (e.g. a tracking ID set in a variable, the URL, maybe the screen dimension to guess the device type...etc.). These often offer a <noscript> alternative for those browsers who have JavasScript disabled, which will be faster, but this is usually severely limited in functionality as it does not have access to all the data the JavaScript version does. GTM however allows you to have the best of both worlds: you can use GTM variables (perhaps based on the GTM Data Layer as mentioned above?) and then use GTM to load the pixel passing in URL params to a pixel. This is often much more performant and safer than loading loads of third party JavaScript.

Now you may be against passing user specific data in the URL, as it's kind of against what you've been taught before however a lot of those concerns don't really matter when it comes to image pixels (they aren't seen in the URL bar, won't be bookmarked, won't be in history, won't be printed), and as long as you're using HTTPS (you are using HTTPS aren't you?), then the only party who should get this data or see it in their weblogs is the advertising company. Plus, other than an advertising id, you really, really, really shouldn't be sending personally identifiable data to an advertising agency so if you've concerns about anything that shouldn't go in a GET request then you've got to question whether that's data for an advertising agency!

Let's look at a real life example of what I'm talking about here. The Facebook Tracking Pixel has an img tag alternative, that they recommend as a <noscript> alternative and it can be used as an equivalent to JavaScript:

Initially you are advised to call the following code:

<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', ''); fbq('init', 'your-pixel-id-goes-here'); fbq('track', 'PageView'); </script> <noscript> <img height="1" width="1" style="display:none" src=" &ev=PageView &noscript=1"/> </noscript>

However you can just call the <noscript> part for the same Tracking, though when doing this drop the noscript=1 part, as the JS version doesn't call that (in fact if you look at your Developer tools with the JavaScript verion you'll see that this is ultimately what the JS version ends up calling - but just with more URL parameters):

<img height="1" width="1" style="display:none" src=" &ev=PageView"/>

You can also just call the same URL from a GTM Custom Image tag. Three other params that Facebooks JavaScript ends up adding are dl (for the URL), sw (for screen width) and sh (for screen height). The first is available in GTM anyway, and last two are used to guess the device type so can be useful to have. It would be nice if GTM had calculated these for you, but until then, these can be set with a bit of JavaScript on the page which pushes to the Data Layer. Then they can be added to the image URL called:

<img height="1" width="1" style="display:none" src=" &ev=PageView &dl=url-goes-here &sw=calculated-screen-width-goes-here &sh=calculated-screen-height-goes-here"/>

See the screenshot below for how this can be set up based on some prefdefined GTM variables:

Using Facebook Pixels in GTM rather than JavaScript

For tracking conversions you can do similar. You would normally call the fbq JavaScript function, that the Facebook JavaScript snippet that you initialised above has set up for you:

fbq('track', 'Purchase', {currency: "USD", value: 30.00});

But this can again be replaced by again just loading an image with the appropriate params:

<img height="1" width="1" style="display:none" src=" &ev=Purchase &cd[currency]=USD &cd[value]=30.00 &dl=url-goes-here &sw=calculated-screen-width-goes-here &sh=calculated-screen-height-goes-here""/>

And in the same way, clicking on a button you want to track normally requires calling the fbq function:

<!-- Somewhere there is a button that performs Add to Cart --> <button id="addToCartButton">Add To Cart</button> <!-- Add Pixel Events to the button's click handler --> <script type="text/javascript"> var button = document.getElementById('addToCartButton'); button.addEventListener( 'click', function() { fbq('track', 'AddToCart', { content_name: 'Really Fast Running Shoes', content_type: 'product', value: 4.99, currency: 'USD' }); }, false ); </script>

But since GTM allows you to track click events, you can use that as a trigger and then just call yet another image:

<img height="1" width="1" style="display:none" src=" &ev=AddToCart &cd[content_name]=Really%20Fast%20Running%20Shoes &cd[content_type]=product &cd[value]=49.99 &dl=url-goes-here &sw=calculated-screen-width-goes-here &sh=calculated-screen-height-goes-here""/>

GTM also allows you to add a random id at the end for cache-busting to ensure the browser does send the requests back to the server (little known fact but, for efficiency reasons, two images on the same page will not normally result in two requests to the server even if HTTP caching headers say not to cache). In fact, as we had the Facebook tracking JavaScript in GTM already at my work, all we had to do was change our Facebook tag types in GTM from Custom HTML (which had <script> tags in them) to Custom Images and construct the image URL from the variables we were already using in the JavaScript version. So this was actually a very easy change to do as all the triggers and variables were already set up. Marketing were a little sceptical that it would give them the same tracking, but after convincing them that it should and to give it a go we got agreement to trail it for a week. Apart from a small upset with not being able to track devices (the sw and sh fields mentioned above which are not documented by Facebook), after the week they saw no change in tracking and so were happy to stick with this permanently.

Facebook do note the following limitations with this:

Please note that pixels installed using an <img> tag have the following limitations:

  • Cannot be fired multiple times on each page load
  • Cannot track standard or custom events triggered by UI interactions (e.g., a button click)
  • Subject to HTTP GET limits in sending custom data or long URLs
  • Cannot be loaded asynchronously

Most of these (except the third one on HTTP GET limits) are not true when used dynamically in GTM, rather than in a <noscript> tag. GTM can fire image beacons multiple times if you want with the cache buster param. It can also fire images based on events. Finally images are, by definition asynchronous, and making them based on DOM Ready or Window Loaded means they do not need to hold up the initial page load. As I said above I have been able to totally replace all Facebook JavaScript on the site I manage in my work with pixels instead, with no detrimental effect to marketing, but with better performance and security. Win win! It also means you can be clear what data you are sending to the likes of Facebook as, let's be honest, they do have a bit of bad reputation when it comes to collecting data without making it clearer they are doing this!

Certain marketing tags won't have img pixel alternatives, or won't offer the same functionality if they are used, so this may not be an option for all but it's definitely worth investigating. You can also have a look at the Developer Tools and see what network calls are being called for those advertisers and reverse engineer to create an img pixel alternative (I think that's what we did to get the sw and sh params for Facebook as those aren't documented), but that might be subject to breaking and it would be better to push those companies for documented img pixel tag alternatives if they don't offer them! You may encounter resistance as marketers have been told that img pixels give less tracking information, and may not understand the above explanation as to why this doesn't need to be the case, but persevere - it will be worth it if you can reduce the JavaScript on your page.

I really think that using pixel images in a smart way like this, could be a game changer in terms of solving the third party JavaScript issue. After all, all that the JavaScript usually ultimately does is load an img pixel to do the actual tracking - they just are doing this via their own JavaScript after setting up a load of variables to figure out the params to send with that image call. GTM gives the ability to work those out so there is no need to use the vendor's JavaScript. We can calculate all the necessary tracking information once in GTM, rather than multiple times in each's vendor's code. In fact this is basically the approach the Accelerated Mobile Pages (AMP) project takes to ensure their analytics are fast (though I really don't like AMP). Until this post, I've not really seen anyone suggesting using GTM to revert back to img pixels. If I've missed something here then do let me know but it's been in place at my work for over a year and seems to be working fine!

Tip 9 - Restrict GTM tags

If you manage to completely remove all custom JavaScript from GTM, then you can actually configure GTM to block it, so if someone tries to add some back later it will not work. GTM allows you to define the types of tag and functionality that you allow by pushing a blacklist or whitelist to the GTM Data Layer. For example, we used the following:

//Restrict GTM variables: dataLayer.push({'gtm.blacklist': ['html','d','jsm', 'j']}); <!-- Google Tag Manager --> ... <!-- End Google Tag Manager -->

This says we don't allow GTM to use the following:

This therefore blocks access to the most dangerous functions of GTM as you can't use GTM to inject JavaScript except for 1) any that GTM uses itself and 2) JavaScript loaded by pre-defined tags in GTM. Not all marketing Tags are predefined in GTM (the Facebook Tracking pixel is not defined for example), so adding these restrictions will mean you cannot use these in GTM unless you use the img pixel method discussed above, where you don't need JavaScript in GTM. Additionally access to DOM elements or JavaScript variables may be needed unless your web page pushes everything your tags need to the GTM data layer as discussed above. Believe it or not I've put some thought into the order of these tips! ;-)

And a good thing about this is that these restrictions are set on the page - it is not a setting inside GTM, so it's not something that can be reversed, unless you have access to edit the GTM loading code on the page. And of course if you don't trust those that have access to edit the page, then all of this GTM lock down is pointless anyway :-)

Putting in these blacklists is definitely more restrictive. However it does really bring a lot of security to your GTM set up and reduces the chance of performance issues, so I would strongly encourage you to do this if at all possible. A good model is to allow pixel image tags or pre-defined tags with this, and then any tags that need JavaScript need to go through the development team and have to be added to the page. This allows a greater review of these tags and also the delay this causes, should make marketing consider alternatives - or push the tacking firm to implement pixels in future.

Of course, even with these restrictions in place, one of the predefined tags that you do allow, could cause bad JavaScript to be injected into your page, but I'm presuming (perhaps naively!) that Google performs some kind of review for performance and security implications before allowing them to be listed as a predefined tag in GTM. All these tips (especially when combined together) will add security and reduce the change of bad JavaScript getting on your page, but they will not eliminate that chance completely. As with all things, there are no absolutes in real life, and you need to find your acceptable level of risk.

Tip 10 - enable 2-step login verification for certain operations

In the Account Settings you can tick the "Require 2-step login verification for certain operations" which means changes to User permissions or adding JavaScript, will require Google Two-Step verification in case your GTM account gets compromised. Non-techies like marketing may struggle with Two-Step verification, but then they should not need to do these operations often. As per above, my personal preference is to disable adding JavaScript completely, in which case, this option is even less inconvenient, so no reason not to switch on!

Tip 11 - Secure your cookies

Ensure you secure your cookies so sensitive cookies, that do not need to be accessed from JavaScript, cannot be accessed from JavaScript! This is especially relevant if you are allowing third party JavaScript on to your site. Some cookies may need to be accessed from JavaScript but most cookies, especially sensitive ones like login session cookies, should not need to be accessed so tell the browser that! It would be nice if the default for cookies was to block from JavaScript, and you had to explicitly allow them to be accessed if you wanted them to when creating them, rather than the other way around where it's insecure by default, but that's a whole other topic. At the end of the day changing that would unfortunately break too much of the internet, so we're left with having to do it the other way around and explicitly secure cookies you want to secure.

Tip 12 - Implement a Content Security Policy

Content Security Policy (CSP) is a way for you, as a website owner, to tell the browser what items or sources of item, you are going to allow on your website. It's similar in concept (though a lot more complex!) to the GTM restrictions we talked about above. You whitelist content types and domains that are allowed, and if the page tries to load content from somewhere else, that you have not whitelisted, then the browser will block it. This means if you GTM gets compromised and tries to load content from, or one of the third party tags you load gets compromised and tries the same, then CSP can protect you. Setting up a CSP is quite complex, and beyond the scope of this post, but it offers strong protections for a website - especially when you allow third party content into your site (like tag managers do) and so are inherently in greater need of the protections it offers.

The downside to implementing a CSP with GTM is that tags do change. You whitelist, and then they decide to change their script to load Seriously - they did that recently and were blocked by our work site (though at least, unlike most, Hotjar publish details of what you need in your CSP). Anyway when things change, that means you need to update your CSP. Similarly if marketing use another tag for the first time, you might need to whitelist another domain.

If you are able to get by with just img pixels instead of script ones (see above), then CSP gets easier as you can just enable https: in your img-src to allow it to load images from all domains. Yes this could be used to scrape and extra data as this proof of concept shows, but that requires a JavaScript or CSS vulnerability too and is a lot less common that using XHR requests which you should lock down fully with the connect-src attribute. As I say repeatedly through this post - I'm trying to tighten security here a lot more than typical GTM installs, not make them impregnable.

The final issue with CSP is that Google Tag Manager uses two inline scripts in preview mode. If you add a CSP which does not allow unsafe-inline in your script-src (which you should not allow!), then you cannot use preview mode - which is quite annoying as this is very useful and reduces the ability to test GTM changes. gives the other policys needed when using GTM with a CSP

CSP takes time to implement, more time to maintain and can even break your site but, as I say, it does also offer strong protection because of that. Many say GTM is incompatible with CSP and you need unsafe-inline or unsafe-eval, but that is not the case - depending how the JavaScript in your tags is written.


Tag managers are widely used, and GTM is king of the tag managers at the moment. This is because they are useful for managing marketing campaigns on websites, but they do introduce risks to a website - particularly for introducing security problems, or hindering the performance of a website. This blog post has detailed some ways to reduce those risks. As I've stated several times here, these tips will not reduce the risk completely and some will be uncomfortable with the whole concept of tag managers and tracking tags. That is entirely understandable and I am not suggesting adding these changes will alleviate all those concerns. I'm simply trying to offer ways to use them better for those that do choose to use tag manager. Hopefully some of you will find this post useful and can add more security to your websites, and also improve your performance while you are at it.

Finally, there are a number of changes I would like to see those in the industry make to help make all this easier:

So if you're a marketer (or Google) and have any influence on these, then please consider these next time you are implementing a tag for companies to use!

Have any comments or any other tips to improve GTM? Let me know below!

Want to read more?

More Resources on this subject

This page was originally created on and last edited on .

How useful was this page?