Android v3 (Legacy) - Overview

This developer guide describes how to implement Google Tag Manager in a mobile application.

Introduction

Google Tag Manager enables developers to change configuration values in their mobile applications using the Google Tag Manager interface without having to rebuild and resubmit application binaries to app marketplaces.

This is useful for managing any configuration values or flags in your application that you may need to change in the future, including:

  • Various UI settings and display strings
  • Sizes, locations, or types of ads served in your application
  • Game settings

Configuration values may also be evaluated at runtime using rules, enabling dynamic configurations such as:

  • Using screen size to determine ad banner size
  • Using language and location to configure UI elements

Google TagManager also enables the dynamic implementation of tracking tags and pixels in applications. Developers can push important events into a data layer and decide later which tracking tags or pixels should be fired. TagManager currently supports the following tags:

  • Google Mobile App Analytics
  • Custom Function Call tag

Before you Begin

Before using this getting started guide, you'll need the following:

If you're new to Google Tag Manager, we recommend that you learn more about containers, macros, and rules (Help Center) before continuing this guide.

Getting Started

This section will guide developers through a typical Tag Manager workflow:

  1. Add the Google Tag Manager SDK to your project
  2. Set Default Container Values
  3. Open the Container
  4. Get Configuration Values from the Container
  5. Push Events to the DataLayer
  6. Preview & Publish the Container

1. Adding the Google Tag Manager SDK to Your Project

Before using the Google Tag Manager SDK, you'll need to unzip the SDK package and add the library to the build path of your project and add permissions to your AndroidManifest.xml file.

First, add the Google Tag Manager library to the /libs folder of your project.

Next, update your AndroidManifest.xml file to use the following permissions:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

2. Adding a Default Container File to your Project

Google Tag Manager uses a default container on the first run of your application. The default container will be used until the app is able to retrieve a fresh container over the network.

To download and add a default container binary to your application, follow these steps:

  1. Sign in to the Google Tag Manager web interface.
  2. Select the Versionof the container you'd like to download.
  3. Click the Downloadbutton to retrieve the container binary.
  4. Add the binary file to the following path: < project-root >/assets/tagmanager/

The default filename should be the container ID (for example GTM-1234 ). Once you've downloaded the binary file, be sure to remove the version suffix from the filename to ensure you follow the correct naming convention.

Although using the binary file is recommended, if your container does not contain rules or tags, you may choose to use a simple JSON file instead. The file must be located in a new /assets/tagmanager folder of your Android project and should follow this naming convention: <Container_ID>.json . For example, if your container ID is GTM-1234 , you should add your default container values to /assets/tagmanager/GTM-1234.json .

3. Opening a Container

Before retrieving values from a container, your application needs to open the container. Opening a container will load it from disk (if available), or will request it from the network (if needed).

The easiest way to open a container on Android is by using ContainerOpener.openContainer(..., Notifier notifier) , as in the following example:

 import 
  
 com.google.tagmanager.Container 
 ; 
 import 
  
 com.google.tagmanager.ContainerOpener 
 ; 
 import 
  
 com.google.tagmanager.ContainerOpener.OpenType 
 ; 
 import 
  
 com.google.tagmanager.TagManager 
 ; 
 import 
  
 android.app.Activity 
 ; 
 import 
  
 android.os.Bundle 
 ; 
 public 
 class 
  
 RacingGame 
 { 
 // 
 Add 
 your 
 public 
 container 
 ID 
 . 
 private 
 static 
 final 
 String 
 CONTAINER_ID 
 = 
 "GTM-YYYY" 
 ; 
 volatile 
 private 
 Container 
 mContainer 
 ; 
 @Override 
 public 
 void 
 onCreate 
 ( 
 Bundle 
 savedInstanceState 
 ) 
 { 
 super 
 . 
 onCreate 
 ( 
 savedInstanceState 
 ); 
 TagManager 
 mTagManager 
 = 
 TagManager 
 . 
 getInstance 
 ( 
 this 
 ); 
 // 
 The 
 container 
 is 
 returned 
 to 
 containerFuture 
 when 
 available 
 . 
 ContainerOpener 
 . 
 openContainer 
 ( 
 mTagManager 
 , 
 // 
 TagManager 
 instance 
 . 
 CONTAINER_ID 
 , 
 // 
 Tag 
 Manager 
 Container 
 ID 
 . 
 OpenType 
 . 
 PREFER_NON_DEFAULT 
 , 
 // 
 Prefer 
 not 
 to 
 get 
 the 
 default 
 container 
 , 
 but 
 stale 
 is 
 OK 
 . 
 null 
 , 
 // 
 Time 
 to 
 wait 
 for 
 saved 
 container 
 to 
 load 
 ( 
 ms 
 ) 
 . 
 Default 
 is 
 2000 
 ms 
 . 
 new 
 ContainerOpener 
 . 
 Notifier 
 () 
 { 
 // 
 Called 
 when 
 container 
 loads 
 . 
 @Override 
 public 
 void 
 containerAvailable 
 ( 
 Container 
 container 
 ) 
 { 
 // 
 Handle 
 assignment 
 in 
 callback 
 to 
 avoid 
 blocking 
 main 
 thread 
 . 
 mContainer 
 = 
 container 
 ; 
 } 
 } 
 ); 
 // 
 Rest 
 of 
 your 
 onCreate 
 code 
 . 
 } 
 } 

In this example, ContainerOpener.openContainer(..., Notifier notifier) is used to request a saved container from local storage. By handling the assignment of mContainer in the containerAvailable callback, we ensure that the main thread is not blocked. If the saved container is older than 12 hours, the call will also schedule a request to asynchronously retrieve a fresh container over the network.

This sample implementation represents the simplest way to open and retrieve values from a container using the ContainerOpener convenience class. For more advanced implementation options, see Advanced Configuration .

4. Getting Configuration Values from the Container

Once the container is open, configuration values may be retrieved using the get<type>Value() methods:

 // Retrieving a configuration value from a Tag Manager Container. 
 // Get the configuration value by key. 
 String 
  
 title 
  
 = 
  
 mContainer 
 . 
 getStringValue 
 ( 
 "title_string" 
 ); 

Requests made with a non-existent key will return a default value appropriate to the type requested:

 // Empty keys will return a default value depending on the type requested. 
 // Key does not exist. An empty string is returned. 
 string 
  
 subtitle 
  
 = 
  
 container 
 . 
 getStringValue 
 ( 
 "Non-existent-key" 
 ); 
 subtitle 
 . 
 equals 
 ( 
 "" 
 ); 
  
 // Evaluates to true. 

5. Pushing Values to the DataLayer

The DataLayer is a map that enables runtime information about your app, such as touch events or screen views, to become available to Tag Manager macros and tags in a container.

For example, by pushing information about screen views into the DataLayer map, you can set up tags in the Tag Manager web interface to fire conversion pixels and tracking calls in response to those screenviews without needing to hard code them into your app.

Events are pushed to the DataLayer using push() and the DataLayer.mapOf() helper method:

 // 
 // 
 MainActivity 
 . 
 java 
 // 
 Pushing 
 an 
 openScreen 
 event 
 with 
 a 
 screen 
 name 
 into 
 the 
 data 
 layer 
 . 
 // 
 import 
  
 com.google.tagmanager.TagManager 
 ; 
 import 
  
 com.google.tagmanager.DataLayer 
 ; 
 import 
  
 android.app.Activity 
 ; 
 import 
  
 android.os.Bundle 
 ; 
 public 
 MainActivity 
 extends 
 Activity 
 { 
 public 
 void 
 onCreate 
 ( 
 Bundle 
 savedInstanceState 
 ) 
 { 
 super 
 . 
 onCreate 
 ( 
 savedInstanceState 
 ); 
 } 
 // 
 This 
 screen 
 becomes 
 visible 
 when 
 Activity 
 . 
 onStart 
 () 
 is 
 called 
 . 
 public 
 void 
 onStart 
 () 
 { 
 super 
 . 
 onStart 
 (); 
 // 
 The 
 container 
 should 
 have 
 already 
 been 
 opened 
 , 
 otherwise 
 events 
 pushed 
 to 
 // 
 the 
 DataLayer 
 will 
 not 
 fire 
 tags 
 in 
 that 
 container 
 . 
 DataLayer 
 dataLayer 
 = 
 TagManager 
 . 
 getInstance 
 ( 
 this 
 ) 
 . 
 getDataLayer 
 (); 
 dataLayer 
 . 
 push 
 ( 
 DataLayer 
 . 
 mapOf 
 ( 
 "event" 
 , 
 "openScreen" 
 , 
 // 
 The 
 event 
 type 
 . 
 This 
 value 
 should 
 be 
 used 
 consistently 
 for 
 similar 
 event 
 types 
 . 
 "screenName" 
 , 
 // 
 Writes 
 a 
 key 
 "screenName" 
 to 
 the 
 dataLayer 
 map 
 . 
 "Home Screen" 
 ) 
 // 
 Writes 
 a 
 value 
 "Home Screen" 
 for 
 the 
 "screenName" 
 key 
 . 
 ); 
 } 
 // 
 Rest 
 of 
 the 
 Activity 
 implementation 
 } 

In the web interface, you can now create tags (like Google Analytics tags) to fire for each screen view by creating this rule: {{ event }} equals "openScreen". To pass the screen name to one of these tags, create a data layer macro that references the "screenName" key in the data layer. You can also create a tag (like a Google Ads conversion pixel) to fire only for specific screen views, by creating a rule where {{ event }} equals "openScreen" && {{ screenName }} equals "ConfirmationScreen".

6. Previewing & Publishing a Container

Macro values will always correspond to the current published version. Before publishing the latest version of a container, you can preview your draft container.

To preview a container, generate a preview URL in the Google Tag Manager web interface by selecting the version of the container you'd like to preview, and then selecting Preview . Hang on to this preview URL as you'll need it in later steps.

Preview URLs are available in the preview window of the Tag
           Manager web interface
Figure 1:Getting a preview URL from the Tag Manager web interface.

Next, add the following Activity to your application's AndroidManifest.xml file:

< ! 
 -- 
  
 Google 
  
 Tag 
  
 Manager 
  
 Preview 
  
 Activity 
  
 -- 
>
< activity 
  
 android 
 : 
 name 
 = 
 "com.google.tagmanager.PreviewActivity" 
  
 android 
 : 
 label 
 = 
 "@string/app_name" 
  
 android 
 : 
 noHistory 
 = 
 "true" 
 > 
< ! 
 -- 
  
 Optional 
 , 
  
 removes 
  
 the 
  
 PreviewActivity 
  
 from 
  
 activity 
  
 stack 
 . 
  
 -- 
>  
< intent 
 - 
 filter 
>  
< data 
  
 android 
 : 
 scheme 
 = 
 "tagmanager.c. application_package_name 
" 
  
 / 
>  
< action 
  
 android 
 : 
 name 
 = 
 "android.intent.action.VIEW" 
  
 / 
>  
< category 
  
 android 
 : 
 name 
 = 
 "android.intent.category.DEFAULT" 
  
 / 
>  
< category 
  
 android 
 : 
 name 
 = 
 "android.intent.category.BROWSABLE" 
 / 
>  
< / 
 intent 
 - 
 filter 
>
< / 
 activity 
>  

Open the link on an emulator or physical device to preview the draft container in your app.

When you're ready to make your draft configuration values available to your application, publish the container .

Advanced Configuration

Google Tag Manager for Mobile has a number of advanced configuration options that allow you to select values based on runtime conditions using rules, manually refresh the container, and get additional options for opening containers. The following sections outline several of the most common advanced configurations.

Advanced Options for Opening Containers

The Google Tag Manager SDK provides several methods for opening containers that can give you more control over the loading process:

TagManager.openContainer()

TagManager.openContainer() is the lowest level and most flexible API for opening a container. It returns immediately with a default container and also asynchronously loads a container from disk or the network if no saved container exists, or if the saved container is not fresh (> 12 hours old).

 mContainer 
  
 = 
  
 tagManager 
 . 
 openContainer 
 ( 
 CONTAINER_ID 
 , 
  
 new 
  
 Container 
 . 
 Callback 
 () 
  
 { 
  
 // Called when a refresh is about to begin for the given refresh type. 
  
 @ 
 Override 
  
 public 
  
 void 
  
 containerRefreshBegin 
 ( 
 Container 
  
 container 
 , 
  
 RefreshType 
  
 refreshType 
 ) 
  
 { 
  
 // Notify UI that the Container refresh is beginning. 
  
 } 
  
 // Called when a successful refresh occurred for the given refresh type. 
  
 @ 
 Override 
  
 public 
  
 void 
  
 containerRefreshSuccess 
 ( 
 Container 
  
 container 
 , 
  
 RefreshType 
  
 refreshType 
 ]) 
  
 { 
  
 // Notify UI that Container is ready. 
  
 } 
  
 // Called when a refresh failed for the given refresh type. 
  
 @ 
 Override 
  
 public 
  
 void 
  
 containerRefreshFailure 
 ( 
 Container 
  
 container 
 , 
  
 RefreshType 
  
 refreshType 
 , 
  
 RefreshFailure 
  
 refreshFailure 
 ) 
  
 { 
  
 // Notify UI that the Container refresh has failed. 
  
 } 

Throughout the loading process, TagManager.openContainer() issues several lifecycle callbacks so that your code can find out when the loading request begins, whether and why it fails or succeeds, and whether the container was ultimately loaded from disk or network.

Unless it is acceptable for your application to use the default values, you will need to use these callbacks to know when a saved or network container has loaded. Note that you will be unable to load a saved or network container if this is the first time the app is run and there's no network connection.

TagManager.openContainer() passes the following enum values as arguments to these callbacks:

RefreshType

Value Description
Container.Callback.SAVED The refresh request is loading a locally saved container.
Container.Callback.NETWORK The refresh request is loading a container over the network.

RefreshFailure

Value Description
Container.Callback.NO_SAVED_CONTAINER There is no saved container available.
Container.Callback.IO_ERROR An I/O error prevented refreshing the container.
Container.Callback.NO_NETWORK There is no network connection available.
Container.Callback.NETWORK_ERROR A network error has occurred.
Container.Callback.SERVER_ERROR An error on the server has occurred.
Container.Callback.UNKNOWN_ERROR An error that can't be categorized has occurred.

Methods for Opening Non-Default and Fresh Containers

ContainerOpener wraps TagManager.openContainer() and provides two convenience methods for opening containers: ContainerOpener.openContainer(..., Notifier notifier) and ContainerOpener.openContainer(..., Long timeoutInMillis) .

Each of these methods takes an enumeration requesting either a non-default or fresh container.

OpenType.PREFER_NON_DEFAULT is recommended for most applications and attempts to return the first available non-default container within a given timeout period, either from disk or network, even if that container is greater than 12 hours old. If it returns a stale saved container, it will also make an asynchronous network request for a fresh one. When using OpenType.PREFER_NON_DEFAULT , a default container will be returned if no other container is available, or if the timeout period is exceeded.

OpenType.PREFER_FRESH attempts to return a fresh container from either disk or network within the given timeout period. It returns a saved container if a network connection is unavailable and/or the timeout period is exceeded.

It is not recommended to use OpenType.PREFER_FRESH in places where a longer request time may noticeably affect user experience, such as with UI flags or display strings. You may also use Container.refresh() at any time to force a network container request.

Both of these convenience methods are non-blocking. ContainerOpener.openContainer(..., Long timeoutInMillis) returns a ContainerOpener.ContainerFuture object, whose get method returns a Container as soon as it has loaded (but that will block until then). The ContainerOpener.openContainer(..., Notifier notifier) method takes a single callback, called when the container is available, which can be used to prevent blocking the main thread. Both methods have a default timeout period of 2000 milliseconds.

Evaluating Macros at Runtime using Rules

Containers can evaluate values at runtime using rules. Rules may be based on criteria like device language, platform, or any other macro value. For example, rules can be used to select a localized display string based on the language of the device at runtime. This can be configured by using the following rule:

A rule is used to select display strings based on device language at
            runtime: language equals es. This rule uses the pre-defined language
            macro and a two character ISO 639-1 language code.
Figure 1:Adding a rule to enable a value collection macro only for devices configured to use the Spanish language.

You can then create value collection macros for each language, and add this rule to each macro, inserting the appropriate language code. When this container is published, your application will be able to display localized display strings, depending on the language of the user's device at runtime.

Note that if your default container needs rules, you must use a binary container file as your default container.

Learn more about configuring rules (Help Center).

Binary Default Container Files

Default containers that need rules should use a binary container file instead of a JSON file as the default container. Binary containers offer support for determining macro values at runtime with Google Tag Manager rules, whereas JSON files do not.

Binary container files may be downloaded from the Google Tag Manager web interface and should be added to your project's /assets/tagmanager/ folder and follow this pattern: /assets/tagmanager/GTM-XXXX , where the filename represents your container ID.

In cases where a JSON file as well as a binary container file are present, the SDK will use the binary container file as the default container.

Using Function Call Macros

Function Call Macros are macros that are set to the return value of a specified function in your application. Function Call Macros can be used to incorporate runtime values with your Google Tag Manager rules, such as determine at runtime which price to display to a user based on the configured language and currency of a device.

To configure a function call macro:

  1. Define the function call macro in the Google Tag Manager web interface. Arguments may optionally be configured as key-value pairs.
  2. Register a FunctionCallMacroHandler in your application using Container.registerFunctionCallMacroHandler() and the function name you configured in the Google Tag Manager web interface, overriding its getValue() method:
     /** 
      
     * 
      
     Registers 
      
     a 
      
     function 
      
     call 
      
     macro 
      
     handler 
     . 
      
     * 
      
     * 
      
     @ 
     param 
      
     functionName 
      
     The 
      
     function 
      
     name 
      
     field 
     , 
      
     as 
      
     defined 
      
     in 
      
     the 
      
     Google 
      
     Tag 
      
     * 
      
     Manager 
      
     web 
      
     interface 
     . 
      
     */ 
     mContainer 
     . 
     registerFunctionCallMacroHandler 
     ( 
     functionName 
     , 
      
     new 
      
     FunctionCallMacroHandler 
     () 
      
     { 
      
     /** 
      
     * 
      
     This 
      
     code 
      
     will 
      
     execute 
      
     when 
      
     any 
      
     custom 
      
     macro 
     ' 
     s 
      
     rule 
     ( 
     s 
     ) 
      
     evaluate 
      
     to 
      
     true 
     . 
      
     * 
      
     The 
      
     code 
      
     should 
      
     check 
      
     the 
      
     functionName 
      
     and 
      
     process 
      
     accordingly 
     . 
      
     * 
      
     * 
      
     @ 
     param 
      
     functionName 
      
     Corresponds 
      
     to 
      
     the 
      
     function 
      
     name 
      
     field 
      
     defined 
      
     * 
      
     in 
      
     the 
      
     Google 
      
     Tag 
      
     Manager 
      
     web 
      
     interface 
     . 
      
     * 
      
     @ 
     param 
      
     parameters 
      
     An 
      
     optional 
      
     map 
      
     of 
      
     parameters 
      
     * 
      
     as 
      
     defined 
      
     in 
      
     the 
      
     Google 
      
     Tag 
      
     Manager 
      
     web 
      
     interface 
     . 
      
     */ 
      
     @ 
     Override 
      
     public 
      
     Object 
      
     getValue 
     ( 
     String 
      
     functionName 
     , 
      
     Map<String 
     , 
      
     Object 
    >  
     parameters 
     )) 
      
     { 
      
     if 
      
     ( 
     functionName 
     . 
     equals 
     ( 
     "myConfiguredFunctionName" 
     )) 
      
     { 
      
     // Process and return the calculated value of this macro accordingly. 
      
     return 
      
      macro_value 
     
      
     } 
      
     return 
      
     null 
     ; 
      
     } 
     }); 
    

Using Function Call Tags

Function Call Tags enable pre-registered functions to be executed whenever an event is pushed into the data layer and the tag rules evaluate to true .

To configure a function call tag:

  1. Define the function call tag in the Google Tag Manager web interface. Arguments may optionally be configured as key-value pairs.
  2. Register a function call tag handler in your application using Container.registerFunctionCallTagHandler() :
     /** 
      
     * 
      
     Register 
      
     a 
      
     function 
      
     call 
      
     tag 
      
     handler 
     . 
      
     * 
      
     * 
      
     @ 
     param 
      
     functionName 
      
     The 
      
     function 
      
     name 
     , 
      
     which 
      
     corresponds 
      
     to 
      
     the 
      
     function 
      
     name 
      
     field 
      
     * 
      
     Google 
      
     Tag 
      
     Manager 
      
     web 
      
     interface 
     . 
      
     */ 
     mContainer 
     . 
     registerFunctionCallTagHandler 
     ( 
     functionName 
     , 
      
     new 
      
     FunctionCallTagHandler 
     () 
      
     { 
      
     /** 
      
     * 
      
     This 
      
     method 
      
     will 
      
     be 
      
     called 
      
     when 
      
     any 
      
     custom 
      
     tag 
     ' 
     s 
      
     rule 
     ( 
     s 
     ) 
      
     evaluates 
      
     to 
      
     true 
     . 
      
     * 
      
     The 
      
     code 
      
     should 
      
     check 
      
     the 
      
     functionName 
      
     and 
      
     process 
      
     accordingly 
     . 
      
     * 
      
     * 
      
     @ 
     param 
      
     functionName 
      
     The 
      
     functionName 
      
     passed 
      
     to 
      
     the 
      
     functionCallTagHandler 
     . 
      
     * 
      
     @ 
     param 
      
     parameters 
      
     An 
      
     optional 
      
     map 
      
     of 
      
     parameters 
      
     as 
      
     defined 
      
     in 
      
     the 
      
     Google 
      
     * 
      
     Tag 
      
     Manager 
      
     web 
      
     interface 
     . 
      
     */ 
      
     @ 
     Override 
      
     public 
      
     void 
      
     execute 
     ( 
     String 
      
     functionName 
     , 
      
     Map<String 
     , 
      
     Object 
    >  
     parameters 
     ) 
      
     { 
      
     if 
      
     ( 
     functionName 
     . 
     equals 
     ( 
     "myConfiguredFunctionName" 
     )) 
      
     { 
      
     // Process accordingly. 
      
     } 
      
     } 
     }); 
    

Setting a Custom Refresh Period

The Google Tag Manager SDK will attempt to retrieve a fresh container if the current container age exceeds 12 hours. To set a custom container refresh period, use Timer , as in the following example:

 timer 
 . 
 scheduleTask 
 ( 
 new 
  
 TimerTask 
 () 
  
 { 
  
 @Override 
  
 public 
  
 void 
  
 run 
 () 
  
 { 
  
 mContainer 
 . 
 refresh 
 (); 
  
 } 
 } 
 , 
  
 delay 
 , 
  
< new_period_in 
  
 milliseconds 
> ); 

Debugging with Logger

The Google Tag Manager SDK prints errors and warnings to logs by default. Enabling more verbose logging can be helpful for debugging and is possible by implementing your own Logger with TagManager.setLogger , as in this example:

 TagManager 
  
 tagManager 
  
 = 
  
 TagManager 
 . 
 getInstance 
 ( 
 this 
 ); 
 tagManager 
 . 
 setLogger 
 ( 
 new 
  
 Logger 
 () 
  
 { 
  
 final 
  
 String 
  
 TAG 
  
 = 
  
 "myGtmLogger" 
 ; 
  
 // Log output with verbosity level of DEBUG. 
  
 @ 
 Override 
  
 public 
  
 void 
  
 d 
 ( 
 String 
  
 arg0 
 ) 
  
 { 
  
 Log 
 . 
 d 
 ( 
 TAG 
 , 
  
 arg0 
 ); 
  
 } 
  
 // Log exceptions when provided. 
  
 @ 
 Override 
  
 public 
  
 void 
  
 d 
 ( 
 String 
  
 arg0 
 , 
  
 Throwable 
  
 arg1 
 ) 
  
 { 
  
 Log 
 . 
 d 
 ( 
 TAG 
 , 
  
 arg0 
 ); 
  
 arg1 
 . 
 printStackTrace 
 (); 
  
 } 
  
 // Rest of the unimplemented Logger methods. 
 }); 

Or, you can set the LogLevel of the existing Logger by using TagManager.getLogger().setLogLevel(LogLevel) , as in this example:

 // Change the LogLevel to INFO to enable logging at INFO and higher levels. 
 TagManager 
  
 tagManager 
  
 = 
  
 TagManager 
 . 
 getInstance 
 ( 
 this 
 ); 
 tagManager 
 . 
 getLogger 
 (). 
 setLogLevel 
 ( 
 LogLevel 
 . 
 INFO 
 ); 
Create a Mobile Website
View Site in Mobile | Classic
Share by: