Google Tag Manager for Android
This reference article covers how to initialize, configure, and implement the Google Tag manager into your Android or FireOS app.
Initializing the SDK
The Braze Android SDK can be initialized and controlled by tags configured within Google Tag Manager.
As a prerequisite for this implementation, your Android SDK integration must be complete.
Configuring your Google Tag Manager
In this example, we’ll pretend we are a music streaming app that wants to log different events as users listen to songs. Using Google Tag Manager for Android, we can control which of our 3rd party vendors receive this event, and create tags specific to Braze.
Custom events
Custom events are logged with actionType
set to logEvent
. The Braze custom tag provider in our example is expecting the custom event name to be set using eventName
.
To get started, create a trigger that looks for an “Event Name” that equals played song
Next, create a new tag (“Function Call”) and enter the class path of your custom tag provider described later in this article.
This tag will be triggered when you log the played song
event we just created.
In our tag’s custom parameters (key-value pairs), we’ve set eventName
to played song
- which will be the custom event name logged to Braze.
When sending a custom event, be sure to set actionType
to logEvent
, and set a value for eventName
as shown in the following screenshot.
The custom tag provider in our example will use these key to determine what action to take, and what event name to send to Braze when it receives data from Google Tag Manager.
You can also include additional key-value pair arguments to the tag, which will be sent as custom event properties to Braze. eventName
and actionType
will not be ignored for custom event properties. In the following example tag, we’ll pass in genre
which was defined using a tag variable in Google Tag Manager - sourced from the custom event we logged in our app.
The genre
event property is sent to Google Tag Manager as a “Firebase - Event Parameter” variable since Google Tag Manager for Android uses Firebase as the data layer.
Lastly, when a user plays a song in our app, we will log an event through Firebase and Google Tag Manager using the Firebase analytics event name that matches our tag’s trigger name, played song
:
1
2
3
4
Bundle params = new Bundle();
params.putString("genre", "pop");
params.putInt("number of times listened", 42);
mFirebaseAnalytics.logEvent("played song", params);
1
2
3
4
val params = Bundle()
params.putString("genre", "pop")
params.putInt("number of times listened", 42);
mFirebaseAnalytics.logEvent("played song", params)
Logging custom attributes
Custom attributes are set via an actionType
set to customAttribute
. The Braze custom tag provider is expecting the custom attribute key-value to be set via customAttributeKey
and customAttributeValue
:
1
2
3
4
Bundle params = new Bundle();
params.putString("customAttributeKey", "favorite song");
params.putString("customAttributeValue", "Private Eyes");
mFirebaseAnalytics.logEvent("customAttribute", params);
1
2
3
4
val params = Bundle()
params.putString("customAttributeKey", "favorite song")
params.putString("customAttributeValue", "Private Eyes")
mFirebaseAnalytics.logEvent("customAttribute", params)
Calling changeUser
Calls to changeUser()
are made via an actionType
set to changeUser
. The Braze custom tag provider is expecting the Braze user ID to be set via an externalUserId
key-value pair within your tag:
1
2
3
Bundle params = new Bundle();
params.putString("externalUserId", userId);
mFirebaseAnalytics.logEvent("changeUser", params);
1
2
3
val params = Bundle()
params.putString("externalUserId", userId)
mFirebaseAnalytics.logEvent("changeUser", params)
Braze SDK custom tag provider
With the tags and triggers set up, you will also need to implement Google Tag Manager in your Android app which can be found in Google’s documentation.
Once Google Tag Manager is installed in your app, add a custom tag provider to call Braze SDK methods based on the tags you’ve configured within Google Tag Manager.
Be sure to note the “Class Path” to the file - this is what you’ll enter when setting up a Tag in the Google Tag Manager console.
This example shows one of many ways to structure your custom tag provider, where we determine which Braze SDK method to call based on the actionType
key-value pair sent down from the GTM Tag.
The actionType
we’ve supported in our example are logEvent
, customAttribute
, and changeUser
, but you may prefer to change how your tag provider handles data from Google Tag Manager.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
public class BrazeGtmTagProvider implements CustomTagProvider {
private static final String TAG = BrazeLogger.getBrazeLogTag(BrazeGtmTagProvider.class);
private static final String ACTION_TYPE_KEY = "actionType";
// Custom Events
private static final String LOG_EVENT_ACTION_TYPE = "logEvent";
private static final String EVENT_NAME_VARIABLE = "eventName";
// Custom Attributes
private static final String CUSTOM_ATTRIBUTE_ACTION_TYPE = "customAttribute";
private static final String CUSTOM_ATTRIBUTE_KEY = "customAttributeKey";
private static final String CUSTOM_ATTRIBUTE_VALUE_KEY = "customAttributeValue";
// Change User
private static final String CHANGE_USER_ACTION_TYPE = "changeUser";
private static final String CHANGE_USER_ID_VARIABLE = "externalUserId";
private static Context sApplicationContext;
/**
* Must be set before calling any of the following methods
* so that the proper application context is available when needed.
*
* Recommended to be called in your {@link Application#onCreate()}.
*/
public static void setApplicationContext(Context applicationContext) {
if (applicationContext != null) {
sApplicationContext = applicationContext.getApplicationContext();
}
}
@Override
public void execute(Map<String, Object> map) {
BrazeLogger.i(TAG, "Got google tag manager parameters map: " + map);
if (sApplicationContext == null) {
BrazeLogger.w(TAG, "No application context provided to this tag provider.");
return;
}
if (!map.containsKey(ACTION_TYPE_KEY)) {
BrazeLogger.w(TAG, "Map does not contain the Braze action type key: " + ACTION_TYPE_KEY);
return;
}
String actionType = String.valueOf(map.remove(ACTION_TYPE_KEY));
switch (actionType) {
case LOG_EVENT_ACTION_TYPE:
logEvent(map);
break;
case CUSTOM_ATTRIBUTE_ACTION_TYPE:
setCustomAttribute(map);
break;
case CHANGE_USER_ACTION_TYPE:
changeUser(map);
break;
default:
BrazeLogger.w(TAG, "Got unknown action type: " + actionType);
break;
}
}
private void logEvent(Map<String, Object> tagParameterMap) {
String eventName = String.valueOf(tagParameterMap.remove(EVENT_NAME_VARIABLE));
Braze.getInstance(sApplicationContext).logCustomEvent(eventName, parseMapIntoProperties(tagParameterMap));
}
private BrazeProperties parseMapIntoProperties(Map<String, Object> map) {
BrazeProperties brazeProperties = new BrazeProperties();
for (Map.Entry<String, Object> entry : map.entrySet()) {
final Object value = entry.getValue();
final String key = entry.getKey();
if (value instanceof Boolean) {
brazeProperties.addProperty(key, (Boolean) value);
} else if (value instanceof Integer) {
brazeProperties.addProperty(key, (Integer) value);
} else if (value instanceof Date) {
brazeProperties.addProperty(key, (Date) value);
} else if (value instanceof Long) {
brazeProperties.addProperty(key, (Long) value);
} else if (value instanceof String) {
brazeProperties.addProperty(key, (String) value);
} else if (value instanceof Double) {
brazeProperties.addProperty(key, (Double) value);
} else {
BrazeLogger.w(TAG, "Failed to parse value into an BrazeProperties "
+ "accepted type. Key: '" + key + "' Value: '" + value + "'");
}
}
return brazeProperties;
}
private void setCustomAttribute(Map<String, Object> tagParameterMap) {
String key = String.valueOf(tagParameterMap.get(CUSTOM_ATTRIBUTE_KEY));
Object value = tagParameterMap.get(CUSTOM_ATTRIBUTE_VALUE_KEY);
Braze.getInstance(sApplicationContext).getCurrentUser(new IValueCallback<BrazeUser>() {
@Override
public void onSuccess(BrazeUser brazeUser) {
if (value instanceof Boolean) {
brazeUser.setCustomUserAttribute(key, (Boolean) value);
} else if (value instanceof Integer) {
brazeUser.setCustomUserAttribute(key, (Integer) value);
} else if (value instanceof Long) {
brazeUser.setCustomUserAttribute(key, (Long) value);
} else if (value instanceof String) {
brazeUser.setCustomUserAttribute(key, (String) value);
} else if (value instanceof Double) {
brazeUser.setCustomUserAttribute(key, (Double) value);
} else if (value instanceof Float) {
brazeUser.setCustomUserAttribute(key, (Float) value);
} else {
BrazeLogger.w(TAG, "Failed to parse value into a custom "
+ "attribute accepted type. Key: '" + key + "' Value: '" + value + "'");
}
}
});
}
private void changeUser(Map<String, Object> tagParameterMap) {
String userId = String.valueOf(tagParameterMap.get(CHANGE_USER_ID_VARIABLE));
Braze.getInstance(sApplicationContext).changeUser(userId);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
class BrazeGtmTagProvider : CustomTagProvider {
override fun execute(map: MutableMap<String, Any>) {
BrazeLogger.i(TAG, "Got google tag manager parameters map: $map")
if (sApplicationContext == null) {
BrazeLogger.w(TAG, "No application context provided to this tag provider.")
return
}
if (!map.containsKey(ACTION_TYPE_KEY)) {
BrazeLogger.w(TAG, "Map does not contain the Braze action type key: $ACTION_TYPE_KEY")
return
}
val actionType = map.remove(ACTION_TYPE_KEY).toString()
when (actionType) {
LOG_EVENT_ACTION_TYPE -> logEvent(map)
CUSTOM_ATTRIBUTE_ACTION_TYPE -> setCustomAttribute(map)
CHANGE_USER_ACTION_TYPE -> changeUser(map)
else -> BrazeLogger.w(TAG, "Got unknown action type: $actionType")
}
}
private fun logEvent(tagParameterMap: MutableMap<String, Any>) {
val eventName = tagParameterMap.remove(EVENT_NAME_VARIABLE).toString()
Braze.getInstance(sApplicationContext).logCustomEvent(eventName, parseMapIntoProperties(tagParameterMap))
}
private fun parseMapIntoProperties(map: Map<String, Any>): BrazeProperties {
val brazeProperties = BrazeProperties()
map.forEach { param ->
val key = param.key
val value = param.value
when (value) {
is Boolean -> brazeProperties.addProperty(key, value)
is Int -> brazeProperties.addProperty(key, value)
is Date -> brazeProperties.addProperty(key, value)
is Long -> brazeProperties.addProperty(key, value)
is String -> brazeProperties.addProperty(key, value)
is Double -> brazeProperties.addProperty(key, value)
else -> BrazeLogger.w(TAG, "Failed to parse value into an BrazeProperties "
+ "accepted type. Key: '" + key + "' Value: '" + value + "'")
}
}
return brazeProperties
}
private fun setCustomAttribute(tagParameterMap: Map<String, Any>) {
val key = tagParameterMap[CUSTOM_ATTRIBUTE_KEY].toString()
val value = tagParameterMap[CUSTOM_ATTRIBUTE_VALUE_KEY]
Braze.getInstance(sApplicationContext).getCurrentUser { brazeUser ->
when (value) {
is Boolean -> brazeUser.setCustomUserAttribute(key, value)
is Int -> brazeUser.setCustomUserAttribute(key, value)
is Long -> brazeUser.setCustomUserAttribute(key, value)
is String -> brazeUser.setCustomUserAttribute(key, value)
is Double -> brazeUser.setCustomUserAttribute(key, value)
is Float -> brazeUser.setCustomUserAttribute(key, value)
else -> BrazeLogger.w(
TAG, "Failed to parse value into a custom "
+ "attribute accepted type. Key: '" + key + "' Value: '" + value + "'"
)
}
}
}
private fun changeUser(tagParameterMap: Map<String, Any>) {
val userId = tagParameterMap[CHANGE_USER_ID_VARIABLE].toString()
Braze.getInstance(sApplicationContext).changeUser(userId)
}
companion object {
private val TAG = BrazeLogger.getBrazeLogTag(BrazeGtmTagProvider::class.java)
private val ACTION_TYPE_KEY = "actionType"
// Custom Events
private val LOG_EVENT_ACTION_TYPE = "logEvent"
private val EVENT_NAME_VARIABLE = "eventName"
// Custom Attributes
private val CUSTOM_ATTRIBUTE_ACTION_TYPE = "customAttribute"
private val CUSTOM_ATTRIBUTE_KEY = "customAttributeKey"
private val CUSTOM_ATTRIBUTE_VALUE_KEY = "customAttributeValue"
// Change User
private val CHANGE_USER_ACTION_TYPE = "changeUser"
private val CHANGE_USER_ID_VARIABLE = "externalUserId"
private var sApplicationContext: Context? = null
/**
* Must be set before calling any of the following methods so
* that the proper application context is available when needed.
*
* Recommended to be called in your [Application.onCreate].
*/
fun setApplicationContext(applicationContext: Context?) {
if (applicationContext != null) {
sApplicationContext = applicationContext.applicationContext
}
}
}
}
In your Application.onCreate()
be sure to add the following initialization for the previous snippet:
1
BrazeGtmTagProvider.setApplicationContext(this.getApplicationContext());
1
BrazeGtmTagProvider.setApplicationContext(this.applicationContext)