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:
Navigate to the
Fields
tab, and clickAdd Field
.Choose the
Text input
field type.Change the id from
text1
totrackingId
.
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 samecacheToken
Permissions
If you tried to run this code before this point you might have noticed some errors in the console.
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:
Navigate to the
Permissions
tab, ExpandAccesses Global Variables
, and then clickAdd Key
.Use
ga
for the key, and check the boxes forRead
,Write
, andExecute
.Repeat this process for
ga.q
andga.l
. Note that these fields don't need theExecute
permission.
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
.
To configure the Inject Scripts
permission:
Add
https://www.google-analytics.com/analytics.js
to theAllowed URL Match Patterns
.
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);