Variables
To make sure that your data is as accessible as possible, we create variables and tags according to a particular framework. If you/your site's developers are deploying tags, we ask that you work within this framework.

Constant variables for metadata

You will often want to associate the same label with events across your website. For this reason, we recommend setting up multiple "Constant" type variables whose values are set to strings that describe events. We also recommend naming variables using camel case, as is typical for Javascript variables, to distinguish them from other assets you create in Tag Manager. Here are several examples:
Variable name
String to set it to
linkClick
Link click
buttonAsLinkClick
Button as link click
buttonTypeSubmitClick
Submit button click
buttonTypeButtonClick
Button as button click

baseApp

Variable type: Constant
Stores a value that identifies the website, and that you include in your event tags. For example, the baseApp value for DTAConnect is dtaconnect.
You should set baseApp to be a constant, and it's a good idea to use the "Format value" option to set it "Lowercase."

Task Path

Variable type: Custom Javascript
Identifies where in the app an event took place. "Where," here, is somewhat up to you. You'll want to identify the different "tasks" a user can complete on your website, along with the various steps they can take to completing the task.
Every Task Path begins this way:
1
function() {
2
var baseApp = {{baseApp}};
3
var section = (window.location.pathname).toLowerCase();
4
return baseApp + ' ' + section;
5
}
Copied!
Note that GTM Custom Javascript tags do not support Ecmascript 6 features (such as let or const). {{baseApp}}refers to your container's baseApp variable (see above): GTM tags are able to reference other GTM variables.
The example above only does part of what Task Path should do: It identifies the app and the URL. The next step is to identify which task the user is trying to complete based on the URL of the current page, such as in this example, which the URL /app/add-to-cart indicates that the user is b which is part of a license purchase, you might extend this code above like so:
1
function() {
2
var baseApp = {{baseApp}};
3
var section = (window.location.pathname).toLowerCase();
4
if (section === '/app/add-to-cart') {
5
section = baseApp + ' license purchase';
6
}
7
return section;
8
}
Copied!
If there are many possible tasks on your website, you may wish to set up an object that matches paths and task names to serve as a lookup table:
1
function() {
2
var baseApp = {{baseApp}}; // for example, uionline
3
var section = (window.location.pathname).toLowerCase();
4
5
var tasks = {
6
'/app/add-to-cart'': 'license purchase',
7
'/app/user-profile':'update profile',
8
'/app/locations':'find a location',
9
'/app/register-for-course':'register for a course'
10
// etc.
11
}
12
13
return baseApp + ' ' + tasks[section] //e.g. massfishhunt license purchase
14
}
Copied!
You can also do this with a series of ifstatements.
What is important is that ultimately, we're able to label data by site name and by area of the site in which an event was triggered.

Hit timestamp

Type: Custom Javascript
The date and time, down to the millisecond, a hit (pageview, click) occurred. Google Analytics also provides its own time dimensions, but we use this for convenience while we are using the free version, where we have limited access to data.
1
function() {
2
// Get local time as ISO string with offset at the end
3
var now = new Date();
4
var tzo = -now.getTimezoneOffset();
5
var dif = tzo >= 0 ? '+' : '-';
6
var pad = function(num) {
7
var norm = Math.abs(Math.floor(num));
8
return (norm < 10 ? '0' : '') + norm;
9
};
10
return now.getFullYear()
11
+ '-' + pad(now.getMonth()+1)
12
+ '-' + pad(now.getDate())
13
+ 'T' + pad(now.getHours())
14
+ ':' + pad(now.getMinutes())
15
+ ':' + pad(now.getSeconds())
16
+ '.' + pad(now.getMilliseconds())
17
+ dif + pad(tzo / 60)
18
+ ':' + pad(tzo % 60);
19
}
Copied!

Sequence timestamp

Provides a more human-readable timestamp. The example below is built on Mass.gov's, whose format is YYYY MM DD HH:MM:SS. You may re-order the time dimensions if you like for your use case.
1
function() {
2
try {
3
var timestamp = new Date();
4
var time = timestamp.toString().split(' ');
5
return time[3]+ " " +time[1]+ " " +time[2]+ " "+time[4];
6
} catch(e) {
7
return "unknown";
8
}
9
}
Copied!

Session ID

Type: Custom Javascript
We use Session ID in concert with Hit Timestamp to map all data points in a session in order. It should look like this:
1
function() {
2
return new Date().getTime() + '.' + Math.random().toString(36).substring(5);
3
}
Copied!
For context, our session identifier is built on top of Google's session identifier. Here is how they work together: We ask Google to treat Session ID as a "session-scoped" dimension. This means that at the end of each session, the last hit's session ID (per above: generated by combining a timestamp and a random number) is associated with every hit that Google recorded for the session.
This can be confusing if you are following along in preview, as you will see a new session ID generated on each new hit -- each new pageview, click, etc. The way to interpret this, each new Session ID overwrites the previous one. The only one recorded in Google Analytics for each hit in the session is the last one generated by Google Tag Manager. [Mass Digital's note: We know this explanation is confusing, and we're working on it. Please get in touch if you want to talk through this!]

Client ID

Type: Custom Javascript
Client ID is an identifier Google assigns to each user (or, at least, what it thinks amounts to a user based on device, IP address, and other characteristics).
1
function() {
2
// Change customDimensionIndex if you want to change the dimension Client ID gets sent to
3
var customDimensionIndex = 3;
4
return function(model) {
5
model.set('dimension' + customDimensionIndex, model.get('clientId'));
6
}
7
}
Copied!
Type: Custom Javascript

GA Property X-Domain

Type: Constant
The Google Analytics property to which Google Tag Manager will send data. This will be associated with every tag you make.
Type: Custom Javascript
1
function(){
2
return function(){
3
if (document.location.search.match(/_ga=([^&]*)/)) {
4
var new_url;
5
var rebuilt_querystring;
6
// A small function to check if an object is empty
7
var isEmptyObject = function(obj) {
8
var name;
9
for (name in obj) {
10
return false;
11
}
12
return true;
13
}
14
// Let's build an object with a key-value pairs from the current URL
15
var qsobject = document.location.search.replace(/(^\?)/, '').split("&").map(function(n) {
16
return n = n.split("="),
17
this[n[0]] = n[1],
18
this
19
}
20
.bind({}))[0];
21
// Remove the _ga parameter
22
delete qsobject['_ga'];
23
// Let's rebuild the querysting from the previous object with the _ga parameter removed
24
var rebuilt_querystring = Object.keys(qsobject).map(function(k) {
25
if (!qsobject[k]) {
26
return encodeURIComponent(k);
27
} else {
28
return encodeURIComponent(k) + '=' + (encodeURIComponent(qsobject[k] || ""));
29
}
30
}).join('&');
31
// We want to if the current querystring was null
32
if (isEmptyObject(qsobject)) {
33
new_url = location.pathname + location.hash;
34
} else {
35
new_url = location.pathname + '?' + rebuilt_querystring + location.hash;
36
}
37
// Use replaceState to update how the URL appears in the browser
38
window.history.replaceState({}, document.title, new_url);
39
}
40
}
41
}
Copied!
For context: We link analytics across domains by passing a cookie through URLs. To make sure that cookie doesn't appear in a URL and confuse site visitors, we use the above code to remove it. We also remove it from clicked URLs that we track that become part of our data (see below).
Type: Custom Javascript
Note: You need to enable the built-in variable Click URL to deploy this variable.
Use this to remove the Google Analytics cookie from the ends of clicked URLs.
1
function(){
2
var new_url = {{Click URL}} // Click URL is a built in GA variable
3
if ({{Click URL}}.match(/_ga=([^&]*)/)) {
4
var querystring = {{Click URL}}.split("?")[1];
5
var rebuilt_querystring;
6
7
// A small function to check if an object is empty
8
var isEmptyObject = function(obj) {
9
var name;
10
for (name in obj) {
11
return false;
12
}
13
return true;
14
}
15
16
// Let's build an object with a key-value pairs from the current URL
17
var qsobject = querystring.replace(/(^\?)/, '').split("&").map(function(n) {
18
return n = n.split("="),
19
this[n[0]] = n[1],
20
this
21
}.bind({}))[0];
22
23
// Remove the _ga parameter
24
delete qsobject['_ga'];
25
26
// Rebuild the querysting from the previous object with the _ga parameter removed
27
var rebuilt_querystring = Object.keys(qsobject).map(function(k) {
28
if (!qsobject[k]) {
29
return encodeURIComponent(k);
30
} else {
31
return encodeURIComponent(k) + '=' + (encodeURIComponent(qsobject[k] || ""));
32
}
33
}).join('&');
34
35
// We want to if the current querystring was null
36
if (isEmptyObject(qsobject)) {
37
new_url = {{Click URL}}.split("?")[0];
38
} else {
39
new_url = {{Click URL}}.split("?")[0] + '?' + rebuilt_querystring;
40
}
41
}
42
return new_url;
43
}
Copied!
For context: We link analytics across domains by passing a cookie through URLs. To make sure that URLs that become part of our datasets don't include that the cookie -- a long, ugly text string -- we use the above code to remove it.

Constants for all common actions

You should create variables that hold the values you want to assign to all actions you will need to tag. This will make it much easier to change these later if you need to, and it will make the data itself much cleaner. Example values you should consider making variables for include:
    Link click
    Button as link click
    Submit button click
    Error message appears
Last modified 1yr ago