Pitfalls To Avoid With Multiple Google Tag Manager Containers
In 2015, Google began to officially support having multiple Google Tag Manager containers on a page. Fast forward nearly two years, and this question is starting to come up more frequently among clients and attendees at our trainings: “Is it OK to have multiple GTM containers on my site?”
Although we strongly recommend only implementing one GTM container on the page, there may be some cases where it just isn’t feasible:
- To restrict edit/publish permissions to some (but not all) tags, triggers, and variables
- To allow multiple site “owners” to autonomously tag a site
These situations are not common, but tend to occur more regularly in large, complex organizations with many stakeholders interested in various aspects of analytics and marketing. For example, consider a large publisher that embeds its content on various third-party domains. The publisher wants their GTM code on the page, but the third-party domains may already have their own GTM code, and may be unwilling (for good reasons) to give the publisher access to their GTM. If you find yourself in this unavoidable boat, be sure to read the about the pitfalls below.
However, sometimes the question comes up and there is a clear solution that does not involve multiple containers. For example, your agency or vendor may ask you to put their GTM container on your site. Perhaps the agency wants to be able to quickly deploy remarketing pixels in support of the client, which is reasonable. However, I have never encountered a situation where adding an agency or vendor’s GTM container is the best solution (or one I would even remotely consider).
Instead, the best approach is to give the agency/vendor access to your GTM container. Now you have full visibility into the change they make and if needed, you can restrict their access so they can’t publish any changes.
Speaking of publishing, it’s important to remember is that anyone with publish permissions to a GTM container on your site has the potential to break your site. By putting multiple containers on your site, you’re opening up the door for people who may not know what they’re doing to insert custom HTML and/or JavaScript into your page. [Shiver] This can bypass important testing and security practices your IT team may have. This is not something to take lightly – multiple containers should always be the last resort.
Technical Pitfalls
However, if you find yourself in a situation where multiple containers are the only option, here are the main technical pitfalls to be aware of:
dataLayer Name
This is straight from Google’s developer documentation:
“… using more than one data layer can cause some triggers to stop working and could have other implications.”
If you’re implementing multiple containers on the page, you MUST use a single dataLayer. Although you can still rename the dataLayer (e.g. myDataLayer), you must rename the dataLayer for all containers. This is specifically called out in the documentation because in the past, unofficial recommendations were exactly the opposite.
dataLayer Instantiation
Another thing to be aware of is with the dataLayer instantiation (instantiation is just a fancy way of saying “creation”). If you have multiple “owners” of the page, and one of the GTM implementations instantiates the dataLayer like this:
dataLayer = [{ 'name': 'value', 'name2': 'value2', ... }]
then it will overwrite anything that happened to have been in the dataLayer already. This is also an issue even with single containers on a page, where the dataLayer is instantiated multiple time (often through externally loaded JavaScript libraries). Part of this problem traces back to Google’s developer documentation:
If you follow Google’s advice, the above code will completely overwrite any existing dataLayer variable. If there is already a dataLayer variable on the page with information (key/value pairs) in it, you will lose that information.
The proper, robust, fool-proof way to instantiate the dataLayer is as follows:
var dataLayer = window.dataLayer = window.dataLayer || [];
Then always use dataLayer.push to push info into the dataLayer, like:
dataLayer.push({ 'pageCategory': 'signup', 'visitorType': 'high-value' });
This method will work if it’s the first time that the dataLayer is instantiated, or if it’s the second time, tenth time, etc. If it finds an existing dataLayer, it will simply continue to add information. If it doesn’t find a dataLayer, then it will create a new, empty dataLayer.
Unintended Triggers
Because all containers are using a “shared” dataLayer, any events or other variables that get pushed to the dataLayer are available to both containers.
This can sometimes cause issues and confusion if, for example, one container pushes an event to the dataLayer that inadvertently causes a tag to fire in the other container.
Essentially, you just need to avoid pushing “generic” events to the dataLayer (or having triggers that rely on “generic” events). For example, some people will push an event to the dataLayer like the following:
dataLayer.push({ 'event': 'gaEvent', 'eventCategory': 'Example Category', 'eventAction': 'Example Action', 'eventLabel': 'Example Label', ... });
Then they have a single Google Analytics event tag in GTM that triggers on the custom event of gaEvent.
This single tag can essentially handle many different events (as long as the category, action, label, etc. is pushed to the dataLayer).
This is not ideal for several reasons. As it relates to multiple containers, if both containers were pushing to the dataLayer in the same way, you would be accidentally firing tags for the other container’s dataLayer pushes.
Unintended Eavesdropping
To reiterate, anything that is in the dataLayer is available to both containers. Image the following hypothetical scenario:
LunaMotors is an automotive manufacturer with independant car dealerships throughout the country. As part of their relationship with the dealers, they provide customizable websites. LunaMotors wants to track all these dealer websites (using GTM, of course), but many of the individual dealers also want to track their own websites (also with GTM), so we end up with two containers on the page.
Some dealers are doing some really interesting stuff with lead generation and remarketing. As part of that they are pushing information like customer name, email, address, phone number, etc. to the dataLayer for use in various marketing tags (not for use in Google Analytics, which prohibits personally identifiable information – PII). For example:
dataLayer.push({ 'name': 'Jim Gianoglio', 'email': 'myemail@gmail.com', 'phone': '555-1234', 'address': '123 Not My Address Drive', 'city': 'Pittsburgh' });
However, LunaMotors isn’t aware of this. To make matters worse, they are also pushing a variable called ‘name’ to the dataLayer, with the name of the dealership. So they have a variable in GTM that captures the name variable from the dataLayer, which they think is the name of the dealership, and are sending that as a custom dimension to Google Analytics. Unfortunately, because of the dealership use of the name dataLayer variable, now LunaMotors has PII in Google Analytics.
These types of accidental conflicts are less common, but it’s the uncommon issues that catch you by surprise!
Old V1 Legacy Listener Tags
Remember in the old days of GTM, before auto event triggers, when we had to set up listener tags for clicks and form submissions? If you have any of these relics still hanging around in your container beware – they are not supported with multi-container setups. You will need to migrate them over to the auto event trigger configurations available in V2.
Parting Thoughts
Reasons for using multiple containers usually boil down to data governance issues. If at all possible, it’s always best to work out these issues internally and develop a system that only requires a single GTM container.
However, if that is not possible, you may find yourself in the multi-container world with the pitfalls outlined above. At least now you know that those pitfalls exists, and how to avoid them.