Convert an existing tag

In this guide, you will learn how to convert an existing custom HTML tag to use sandboxed JavaScript.

This tutorial will leverage the injectScript API. injectScript is a common API used to convert an existing tag that relies on third-party scripts. These tags often set up basic functionality while a script loads, then augment it with additional functionality after the script loads.

Original tag

<!-- Google Analytics -->
<script>
  window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
  ga('create', 'GA-XXXXXX-1', 'auto');
  ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->

Convert the code

Consider the JavaScript portion of the above tag:

window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'GA-XXXXXX-1', 'auto');
ga('send', 'pageview');

To create the necessary sandboxed JavaScript, look at what native JavaScript APIs this script uses, and convert your code to use the equivalent sandboxed JavaScript APIs.

For example, in the analytics.js tag, these native JavaScript APIs are used:

Native JavaScript Sandboxed JavaScript
window.ga setInWindow
arguments createArgumentsQueue
+ new Date getTimestamp

To use the sandboxed JavaScript APIs in your script, you need to require them. For example, to use the setInWindow() API, add it to the top of your script:

const setInWindow = require('setInWindow');

Next, convert window.ga:

window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)}
// becomes
const createArgumentsQueue = require('createArgumentsQueue');
const ga = createArgumentsQueue('ga', 'ga.q');

Then, convert the ga.l assignment:

ga.l=+new Date;
// becomes
const getTimestamp = require('getTimestamp');
setInWindow('ga.l', getTimestamp(), true);

Finally, convert the two calls to ga():

ga('create', 'GA-XXXXXX-1', 'auto');
ga('send', 'pageview');
// becomes
const trackingId = data.trackingId;
ga('create', trackingId, 'auto');
ga('send', 'pageview');

In order to use data.trackingId, add a field to your template:

  1. Navigate to the Fields tab, and click Add Field.

    Add a field

  2. Choose the Text input field type.

    Select Text Input

  3. Change the id from text1 to trackingId.

    Update the Id

At this point, you have converted the first <script/> tag, but you also need to load in the supporting script.

To do this:

<script async src='https://www.google-analytics.com/analytics.js'></script>
// becomes
const injectScript = require('injectScript');
const url = 'https://www.google-analytics.com/analytics.js';
injectScript(url, data.gtmOnSuccess, data.gtmOnFailure, url);

Passing a cacheToken to injectScript() enables an optimization. For the following scenarios, the analytics.js script will only be loaded once:

  • A tag that runs multiple times
  • More than one tag from this custom template in the same container.
  • Other custom templates using injectScript() with the same cacheToken

Permissions

If you tried to run this code before this point you might have noticed some errors in the console.

Error accessing globals

These errors appear because sandboxed JavaScript requires you to declare the values and URLs you access. In this example, you need to access the ga.q, ga.l, and ga global variables, and you want to inject a script that's hosted at https://www.google-analytics.com/analytics.js.

To configure the Global Variables permissions:

  1. Navigate to the Permissions tab, Expand Accesses Global Variables, and then click Add Key.

    Add key in UI

  2. Use ga for the key, and check the boxes for Read, Write, and Execute.

    Ga add key UI

  3. Repeat this process for ga.q and ga.l. Note that these fields don't need the Execute permission.

    Finished Global Variables

At this point if you click Run Code again, you'll get a new error in the console. This time, the error mentions Inject Scripts.

Inject Scripts Console Error

To configure the Inject Scripts permission:

  1. Add https://www.google-analytics.com/analytics.js to the Allowed URL Match Patterns.

    Finished Inject Scripts

Now when you click Run Code, there should be no errors in the console. You have successfully converted the tag into a custom template. Click Save and use your new tag just like any other Tag in Google Tag Manager.

Fully converted tag

Your final sandboxed JavaScript result should look like this:

const setInWindow = require('setInWindow');
const copyFromWindow = require('copyFromWindow');
const createArgumentsQueue = require('createArgumentsQueue');
const getTimestamp = require('getTimestamp');
const injectScript = require('injectScript');
const trackingId = data.trackingId;

const ga = createArgumentsQueue('ga', 'ga.q');
setInWindow('ga.l', getTimestamp(), false);
ga('create', trackingId, 'auto');
ga('send', 'pageview');
const url = 'https://www.google-analytics.com/analytics.js';
injectScript(url, data.gtmOnSuccess, data.gtmOnFailure, url);