Developer Guide

This document describes details of how to implement Google tag Manager on your site.

Using a Data Layer

To ensure maximum flexibility, portability, and ease of implementation, Google Tag Manager functions best when deployed alongside a data layer. A data layer is an object that contains all of the information that you want to pass to Google Tag Manager. Information such as events or variables can be passed to Google Tag Manager via the data layer, and rules can be set up in Google Tag Manager based on the values of variables (e.g. fire a remarketing tag when purchase_total > $100) or based on the specific events. Variable values can also be passed through to other tags (e.g. pass purchase_total into the value field of a tag).

Rather than referencing variables, transaction information, page categories, and other important signals scattered throughout your page, Google Tag Manager is designed to easily reference information that you put in this data layer. However, explicitly declaring the data layer is optional and if you choose not to implement the data layer, you can still access values from the page using the the Macros feature, but you cannot use events without the data layer. Implementing the data layer with variables and associated values, as opposed to waiting for those variables to load throughout the page, ensures that they will be available as soon as you need them to fire tags.

Adding Data Layer Variables to a Page

To set up your data layer, add the following snippet of code to the head of your page (or elsewhere above your container snippet):

  dataLayer = [];

The above snippet is an empty object that can be populated with information to pass to Google Tag Manager. For example, we might want to set data layer variables within the data layer to indicate that the page is a signup page and that the visitor has been identified as being a high-value customer. To do so, we'd populate our data layer as follows:

  dataLayer = [{
    'pageCategory': 'signup',
    'visitorType': 'high-value'

For example, Google Tag Manager can be configured to fire tags on all pages marked as signup and/or on which the visitor has been marked as high-value. It's important that this data layer snippet be set above the container snippet described in the Quick Start.

If the data layer code is called after the container snippet, any variables declared within will not be available for Google Tag Manager to selectively fire tags on page load. Here are some examples:


  <!-- Google Tag Manager -->
  <!-- End Google Tag Manager -->
    dataLayer = [{
      'pageCategory': 'signup',
      'visitorType': 'high-value'


    dataLayer = [{
      'pageCategory': 'signup',
      'visitorType': 'high-value'
  <!-- Google Tag Manager -->
  <!-- End Google Tag Manager -->

Each of the variables declared within the data layer object will persist as long as the visitor remains on the current page. Data layer variables that are relevant across pages (e.g. visitorType) must therefore be declared in the data layer on each page of your website. While you don't need to put the same set of variables in the data layer on every page, you should use a consistent naming convention. In other words, if you set the page category on the signup page using pageCategory, to set a page category on a purchase page, you should do so using pageCategory as well.

Explicitly declaring a data layer is optional. Therefore, if you choose not to implement the data layer code and populate it with variables, the Google Tag Manager container snippet will initiate a data layer object for you.

Using the Data Layer with HTML Event Handlers

Google Tag Manager provides a special data layer variable called an event that is used within JavaScript event listeners to initiate tag firing when a user interacts with website elements such as a button. For example, you may want to fire a conversion tracking tag when a user clicks the Submit button on a newsletter signup form. Events may be called based on user interaction with website elements such as links, buttons, components of a Flash-driven menu system, or based on other JavaScript (e.g. time delays, etc.).

This functionality is accomplished by calling the push API as a method of the data layer on your page (e.g. attached to the particular elements to be tracked). The basic syntax for setting an event, then, is as follows:

dataLayer.push({'event': 'event_name'});

where event_name is a string indicating what the given event or element is.

As an example, to set an event when a user clicks a button, you might modify the button's link to call the push() API as follows:

<a href="#" name="button1" onclick="dataLayer.push({'event': 'button1-click'});" >Button 1</a>

Sometimes, the data you wish to collect or use to trigger certain tags may not load until after the user has interacted with the page. Using a combination of data layer variables and events, you may dynamically push this information to your data layer as necessary.

Data layer variables may be pushed dynamically to the data layer to capture information such as values entered or selected in a form, metadata associated with a video that the visitor is playing, the color of a product (e.g. a car) customized by the visitor, the destination URLs of clicked links, etc.

As with events, this functionality is accomplished by calling the the push() API to add or replace data layer variables in the data layer. The basic syntax for setting dynamic data layer variables, then, is as follows:

dataLayer.push({'variable_name': 'variable_value'});

Where variable_name is a string indicating the name of the data layer variable to be set, and variable_value is a string indicating the value of the data layer variable to be set or replaced.

As an example, to set a data layer variable with a color preference when the visitor engages with a car customization widget, you might push the following dynamic data layer variable:

dataLayer.push({'color': 'red'});

One Push, Multiple Variables

Instead of using dataLayer.push() for each variable and event, you can push multiple variables and events at once. Here's an example of how to do this:

  'color': 'red',
  'conversionValue': 50,
  'event': 'customizeCar'

You can use the same technique within a link event handler:

<a href="#"
     'color': 'red',
     'conversionValue': 50,
     'event': 'customizeCar'});">Customize Color</a>

It's important to note that pushing a variable of the same name as an existing variable to the data layer will cause the existing value to be overwritten by the new value. For example, if upon clicking the above link, there were already a variable named color with a value of blue declared within the data layer, that value would be overwritten moving forward with the new value of red.

How the Asynchronous Syntax Works

Google Tag Manager is an asynchronous tag, meaning that when it executes, it does not block other elements from rendering on the page. It also causes the other tags that are deployed via Google Tag Manager to be deployed asynchronously, meaning that a slow loading tag won't block other tracking tags.

The dataLayer object is what makes the asynchronous syntax possible. It acts as a queue, which is a first-in,first-out data structure that collects API calls and tags are fired according to those API calls. To add something to the queue, use the dataLayer.push method. The dataLayer.push method can be used to pass in extra metadata to Google Tag Manager via macros and can be used to specify events.

The creation of the dataLayer object can either be specified before the the Google Tag Manager snippet, or it will be created by Google Tag Manager if the dataLayer object hasn't already been defined.

For more information on the asynchronous syntax, Read the Tracking Reference for the dataLayer.push method.

Avoiding Common Pitfalls

When implementing Google Tag Manager, keep the following in mind:

The Data Layer object name is case-sensitive

If you try to push a variable or event without the proper casing, the push will not work. Examples:

datalayer.push({'pageTitle': 'Home'});    // Won't work
dataLayer.push({'pageTitle': 'Home'});    // Better

Variable names should be enclosed in quotes

While quotes are not strictly required for variable names that consist of only letters, numbers, and underscores, and which are not reserved words (e.g. function, export, native, etc.), to avoid issues, it's recommended that all variable names be enclosed in quotes. Examples:

dataLayer.push({new-variable: 'value'});    // Won't work
dataLayer.push({'new-variable': 'value'});    // Better

Variable names should be kept consistent across pages

If you use different variable names for the same variables on different pages, GTM will be unable to consistently fire tags in all desired locations. Examples:

Won't work
// Homepage:
dataLayer.push({'visitorType': 'low-value'});

// Checkout Page:
dataLayer.push({'visitor_type': 'high-value'});
// Homepage:
dataLayer.push({'visitorType': 'low-value'});

// Checkout Page:
dataLayer.push({'visitorType': 'high-value'});

Any information needed to fire tags on a page load must be declared in the data layer above the container snippet.

In order to fire tags on a page load matching some condition (e.g. on pages marked as having a pageCategory of sports), the pageCategory must be defined in the data layer above the container snippet (e.g. 'pageCategory': 'sports'). Variables pushed to the data layer (i.e. using dataLayer.push()) after the container snippet will not be able to fire tags on page loads with a matching condition.

Tags deployed with GTM should not be left hard-coded or deployed by another tool as well

Any tags that are fired from Google Tag Manager should be migrated to GTM, not just duplicated (for more information about migrating tags, see Migrating Tags to Google Tag Manager). Deploying tags both with Google Tag Manager and through other systems or hard-coded on your site may result in inflation of data (and other data integrity issues) resulting from those tags. For example, if you migrate your Google Analytics tracking code to fire from Google Tag Manager, the hard-coded Google Analytics tracking code should be removed from your site.

Renaming the Data Layer

By default, the data layer initiated and referenced by Google Tag Manager will be called dataLayer. If you'd prefer to use a different name for your data layer, you may do so by replacing the data layer parameter value (highlighted below) in your container snippet with the name of your choice.

<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
<!-- End Google Tag Manager -->

Then, all references to your data layer (i.e. when declaring the data layer above the snippet and when pushing events or dynamic Data Layer Variables to the data layer with the push() API) should also be adjusted to reflect your custom data layer name:

  myNewName = [{
    // ...
  myNewName.push({'variable_name': 'variable_value'});

Migrating Tags to Google Tag Manager

In order to gain the most value from Google Tag Manager, we recommend that you migrate most of your existing tags into Google Tag Manager (tags that are not supported should not be migrated). This section describes a best practice migration workflow. The process has 5 main steps:

  1. Map your site (optional)

    To begin your migration, you'll want to think about which tags you currently have deployed on your site and what data you're trying to collect. For data collection think about what actions you want to track (events) and what additional data from the page you'll want to collect (variables). Create a map of tags, the data you want those tags to collect, and which events or pages you want to associate with those tags.

  2. Implement standard Google Tag Manager snippet

    Once you've mapped your site, you'll want to install just the single Google Tag Manager snippet on your site (empty) and deploy it. See Quick Start for more information.

  3. Add Events and Variables

    Customize your Google Tag Manager installation using the methods outlined in the Add Events and Variables section.

  4. Add tags with associated firing rules in Google Tag Manager's management interface

    After you've completed setting up the site with the Google Tag Manager snippet and data collection APIs, you should add your site tags to the user interface. DO NOT publish at this time. Simply add and configure the tags from your site in the Google Tag Manager management interface using the appropriate templates and set up the firing rules appropriately (more information about how to do this in our Help Center Rules article).

  5. Final migration swap

    The last step is where you simultaneously swap out your old tags and publish your tags in Google Tag Manager. Within a few minutes of each other, you'll want to:

    • Remove your site tags in a single code push
    • Once you know this push is successful, press the “Publish” button for your container version.

    This method might cause a small gap in data, but once the initial swap occurs, no more data gaps will appear. Alternatively, you could swap the order here and publish shortly before your site changes go live. This might cause minor, one-time data duplication instead of a small data gap.

After you've completed the initial migration to Google Tag Manager, any subsequent tagging needs you have can be handled without site code changes via the Google Tag Manager interface.

Multiple Domains

While you can use the same container for multiple websites it's recommended that each separate web property that you manage be deployed with its own container. This separation will prevent changes specific to one website from having undesired effects on other websites using the same container. In some situations, however, when multiple Top Level Domains or subdomains are considered to be members of the same website, it may be beneficial to manage their tags through the same Google Tag Manager container.

When choosing to use a single container across multiple domains, it's important to carefully configure your tags and rules within Google Tag Manager. Using the default “All pages” rule in Google Tag Manager (i.e. $url matches RegEx .*) will fire tags on all pages of all domains on which your container snippet is deployed. Since some tags have configurations or purposes specific to the domain on which they're deployed, you may need to create custom rules (or even remove the “All pages” rule) to fire tags on all pages of one or each domain individually.

For example, you may choose to deploy your Google Analytics tracking code through GTM with configurations to support GA tracking across multiple domains or subdomains.

Image showing multiple domains

In such a case, you would add a line of code to your GA tracking code to manually set the first-party domain on which to set the GA cookies (e.g. on www.example-petstore.com and dogs.example-petstore.com, you might set the cookies to the common domain, .example-petstore.com). However, on the secondary site, www.my-example-blogsite.com, you might set the cookies to .my-example-blogsite.com. Therefore, you would want one of two GA tracking code tags (one set to .example-petstore.com, and one set to .my-example-blogsite.com) to fire on each of the two domains. If both domains were sharing a common GTM container, using the default “All pages” rule in Google Tag Manager, would cause each tag to fire on all pages of both domains.

Flash / Actionscript

To enable Google Tag Manager to fire tags based on content or interactions in a Flash movie, it is possible to utilize the ActionScript ExternalInterface method to push events and dynamic data layer variables to the data layer on the container page from the SWF movie. To achieve this functionality, the Google Tag Manager container snippet should be implemented within the HTML of the SWF's parent page as described in the Quick Start guide.

Events and dynamic data layer variables may then be pushed from the Flash component to Google Tag Manager by calling the push method via ExternalInterface. For example, to trigger an event upon click of a button mybutton_btn using ActionScript 3, you could implement the following code within your SWF:

import flash.display.*;
import flash.events.*;
import flash.external.*;
mybutton_btn.addEventListener(MouseEvent.MOUSE_UP, onButtonClick);
function onButtonClick( Event:MouseEvent ):void {
  var name:String= "FLASH_EVENT";
  if (ExternalInterface.available) {
    ExternalInterface.call('dataLayer.push',{'event': name});

For the ExternalInterface method to function properly, please ensure that when embedding your SWF, the allowscriptaccess attribute is set to always:

<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'
        width='300' height='300' id='player1' name='player1'>
  <param name='movie' value='file.swf'>
  <param name='allowfullscreen' value='true'>
  <param name='allowscriptaccess' value='always'>
  <param name='flashvars' value='file=playlist.xml'>
  <embed id='player1' name='player1'
         width='300' height='300'

Adding Data Layer Variables for Devices without JavaScript Support

In order to accommodate visitors who have JavaScript disabled or are visiting from devices that don't support JavaScript Google Tag Manager includes a <noscript> tag to deploy non-JavaScript dependent tags even when the primary GTM JavaScript cannot load.

It's important to note, however, that the data layer (containing the data layer variables declared on page load) and any events or dynamic data layer variables pushed to the data layer all rely on JavaScript to function. Therefore, if any of the rules to fire your non-JavaScript dependent tags (that you want to fire even when JavaScript can't load) depend on data layer variables, you must pass those Data Layer Variables to the <noscript> iframe as query parameters. For example, to fire a tag when the pageCategory is sports and the visitorType is returning, you would modify the container snippet on the given page as follows:

<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXX&pageCategory=sports&visitorType=returning" height="0"
                  width="0" style="display:none;visibility:hidden"></iframe></noscript>
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
<!-- End Google Tag Manager -->

Where each data layer variable is appended to the end of the iframe's source URL as plain text query parameters separated by ampersands.


Google Tag Manager is protocol relative, meaning that it will work on secure and non-secure pages alike. While most of the tag templates in GTM are also protocol relative, it's important to make sure that, when setting up custom tags to fire on secure pages, those tags are also either protocol relative or secure.

Restricting tag deployment

Although it's not recommended to restrict the types of tags deployed using Google Tag Manager, for various reasons it might be necessary to restrict the tag types deployed on a site. For instance, some site-owners might not want Google Tag Manager users to be able to add certain tags to their site for code stability or data collection reasons. As such, we've added a tag blacklist feature to Google Tag Manager that can be controlled at snippet installation.

To control which tags and macros are allowed on a page, use the gtm.whitelist and/or gtm.blacklist keys in your data layer. These keys will override any and all configuration in the container. When properly blacklisted, tags and macros will not fire even if they have been configured to fire in the Google Tag Manager UI.

The following example demonstrates how to initialize the data layer with both a whitelist and a blacklist. Both lists are optional, and you can use them seperately or at the same time (as shown). Both lists must be of type Array, and the values in the list must be of type String:

dataLayer = [{
  'gtm.whitelist': ['<ID>', '<ID>', ...]
  'gtm.blacklist': ['<ID>', '<ID>', '<ID>', ...]

Each ID in the list corresponds to a specific tag or macro type, or to a class of types. Classes represent groups of tags and macros that have the same capabilities. For example, all tags and macros that can send pixels to non-Google domains will have the class nonGooglePixels. Classes are useful for blocking capabilities in current and future tags and macros.

It's important to understand the rules that govern whitelists and blacklists:

  1. Whitelists
    When a whitelist has been set, tags and macros will only execute if they are in the whitelist, either explicitly (by type ID), or implicitly (by having all of their classes in the list).
  2. Blacklists
    When a blacklist has been set, tags and macros will only execute if they are not in the blacklist, either explicitly (by type ID), or implicitly (by having any of their classes in the list).
  3. Blacklists Override Whitelists
    When both have been set, blacklists take precedence. You can whitelist a class of tags and blacklist a specific tag in that class, but the reverse is not true. You cannot blacklist a class of tags and whitelist a specific tag in that class.
  4. Classes Have Relationships
    Some classes have relationships with other classes. For example, tags that can run non-Google scripts can (by definition) send non-Google pixels. For this reason, blocking nonGooglePixels will also automatically block nonGoogleScripts. All tags and macros that belong to either group will be blocked.

The following table provides a listing of the available tags and macros, their types, and the classes that they belong to:

Name in Tag Manager UI ID Classes
AdAdvisor Tag ta nonGoogleScripts
AdRoll Smart Pixel Tag asp nonGoogleScripts
AdWords Conversion Tracking Tag awct google
AdWords Remarketing Tag sp google
Bizo Insight Tag bzi nonGoogleScripts
ClickTale Standard Tracking Tag cts nonGoogleScripts
comScore Unified Digital Measurement Tag csm nonGoogleScripts
Custom HTML Tag html customScripts
Custom Image Tag img customPixels
Custom JavaScript Macro jsm customScripts
DoubleClick Floodlight Counter Tag flc  
DoubleClick Floodlight Sales Tag fls  
Google Analytics Tag ga google
Marin Software Tag ms nonGoogleScripts
Mediaplex - IFRAME MCT Tag mpm nonGoogleIframes
Mediaplex - Standard IMG ROI Tag mpr nonGooglePixels
Media6Degrees Universal Pixel Tag m6d nonGooglePixels
Turn Conversion Tracking Tag tc nonGoogleScripts
Turn Data Collection Tag tdc nonGoogleScripts
Universal Analytics Tag ua google
1st Party Cookie Macro k  
DOM Element Macro d google
Constant Macro c google
Event Name Macro e google
JavaScript Variable Macro j google
DataLayer Variable Macro v google
Random Number Macro r google
Referrer Macro f google
URL Macro u google
Auto-Event Variable Macro v google

The following table provides a listing of the available classes and their relationships to other classes. The Whitelisted Automatically column represents the list of classes that will be implicitly whitelisted when the class from that row is whitelisted. Likewise, the Blacklisted Automatically column respresents the list of classes that will be implicitly blacklisted when the class from that row is blacklisted.

Class Description Whitelisted Automatically Blacklisted Automatically
customPixels Capable of sending pixels to URLs defined by the user. nonGooglePixels customScripts
customScripts Capable of running JavaScript code provided by the user. html
google Only capable of running Google hosted scripts and sending pixels to Google.    
html Alias for customScripts. Note that this is also the ID for the Custom HTML tag. This ensures that legacy users also get the benefits of the customScripts class. customScripts
nonGooglePixels Capable of sending pixels to non-Google domains.   customPixels
nonGoogleScripts Capable of running scripts not provided by Google. nonGooglePixels
nonGoogleIframes Capable of injecting iframes from non-Google domains. nonGooglePixels