#GTMTips: Using Document.write Safely in GTM Tags

Guest post by Dan Wilkerson on how the document.write setting in Google Tag Manager's Custom HTML tags works.

This article is a guest article by someone from the analytics community I really look up to. Dan Wilkerson is an analytics developer at Bounteous, a company I hold in high esteem. Dan is one of the smartest technical analytics experts out there, and a large bulk of the awesome scripts and hacks that Bounteous produces (almost on a daily basis) have been orchestrated by him. So I’m very pleased to give the floor to Dan, so that he can tell you all about using the pesky document.write() method in your Google Tag Manager Custom HTML Tags!

Tip 46: Safely using document.write in Google Tag Manager Tags

Often, 3rd party marketing tags make use of an archaic JavaScript method called document.write. This method has been the go-to for adding in dynamic tracking pixels and scripts because it is universally supported and predictable. However, document.write won’t play nicely with asynchronously loaded scripts. Since Google Tag Manager forces scripts to load asynchronously, and since many 3rd party marketing tags depend on document.write, there was a time when we couldn’t implement these tags in GTM. Fortunately, the engineers at Google added a clever solution which temporarily replaces document.write with a safe alternative while your tag executes.

In the past, document.write was meant to be used to add dynamic content using JavaScript in between when your browser first started to load the page and when the page completed loading. This content would execute synchronously by default, making the outcome predictable and implementation straightforward. Many ad tech vendors came to rely on this functionality to load in snippets and add in tracking pixels, instead of using more asynchronous-friendly methods. This made writing their tags simple and concise, but synchronously executing snippets would cause the browser to stop rendering and slow down the overall speed of the page on a site.

Unfortunately, when document.write is called after the document is finished loading, the browser overwrites the existing document and replaces it with just the contents of the document.write call (read: your entire site becomes a blank page). In the past, this wasn’t a big deal; we’d hard code our handful of marketing tags straight into the HTML of the page.

Unfortunately, modern front-end engineering best practices, the proliferation of tracking pixels, and tag management systems don’t play nicely with this paradigm. These days, it’s all about asynchronicity and speed. Thus, we see the crux of the issue: vendors want simplicity and reliability, and engineers want speed and efficiency.

The engineers at Google have implemented a solution to this problem for us in Google Tag Manager. When a Custom HTML Tag in Google Tag Manager requires document.write to run, Google Tag Manager temporarily replaces the default document.write function with a safe version of their own. When we want to use a tag that uses document.write, we simply need to check a box in the Custom HTML Tag creation interface. Enabling this feature will allow us to safely deploy any tags that use document.write, even after our page has loaded. Here’s where to do that in your tag:

Note! You should not check the box if the tag or any script loaded by the tag does not use document.write.

Once the tag has finished firing, GTM then switches document.write back to the browser default. Wondering if you have a Tag that isn’t using this feature? If you see an error in your console like below:

you may have a tag in GTM that is firing asynchronously and attempting to use document.write. Try and track down this tag quickly and fix it. (Hint: if you click the line reference in the far right of the interface, Chrome will take you straight to the offending code):

Otherwise, your tracking pixels won’t work. GTM will even warn you proactively if you try and save a tag with document.write that doesn’t have this feature enabled:

This feature allows us to have our cake and eat it, too. Before, we’d have to deliver the tags synchronously. You deliver the same tags as before, and you can give your users a better experience.

GTM’s replacement for document.write uses document.createElement and then appends the result into a hidden div at the bottom of the page. It negotiates the handoff by binding to the onload event or the onreadystatechange event of the element.

And that’s all there is to it! Simply check the box, and your tag will load asynchronously and write to the document, as expected. Remember, if you see a warning in the Developer Tools, that means there may be a Custom HTML Tag with document.write that doesn’t have that box checked.

Summary (by Simo)

First of all, kudos to Dan for giving a thorough run-through of something most of us take for granted. The simple little checkbox in the Custom HTML Tag hides a wealth of complexity, engineered solely to make life easier for anyone who has to work with advertising pixels.

It’s kind of odd that something so crucial to businesses these days (ad revenue) hinges on a technology which is dubious at best. In my book, document.write is in the same bucket of nastiness as iframes, single-pixel image beacons, (third-party) browser cookies, and all other technologies designed to facilitate the spread of malware.

But this article wasn’t about advertising. This was about zooming in on yet another interesting technical manoeuvre that the Google Tag Manager engineers have done to make sure that the tool caters to all its target audiences (whatever they might be) with equal precision. So thank you, Dan!

As always, the comment section is here for you.