本开发者指南介绍了如何在移动应用中实现 Google 跟踪代码管理器。
简介
通过使用 Google 跟踪代码管理器界面,开发者可在其移动应用中更改配置值,而无需重新生成应用二进制文件并将其重新提交到应用市场。
这对于管理应用中您日后可能需要更改的任何配置值或标志非常有用,包括:
- 各种界面设置和显示字符串
- 应用中投放的广告的尺寸、位置或类型
- 游戏设置
配置值也可以在运行时使用规则进行评估,从而实现动态配置,例如:
- 使用屏幕尺寸确定广告横幅尺寸
- 使用语言和位置配置界面元素
Google 跟踪代码管理器还支持在应用中动态实现跟踪代码 和像素。开发者可以将重要事件推送到数据 层,然后决定应触发哪些跟踪代码或像素。 跟踪代码管理器支持以下代码:
- Google 移动应用分析
- 自定义函数调用代码
准备工作
在使用本使用入门指南之前,您需要做好以下准备:
- 一个 Google 跟踪代码管理器账号
- 新的跟踪代码管理器 容器和值集合宏
- 用于实现 Google 跟踪代码管理器的 Android 移动应用
- Google Analytics 服务 SDK,其中包含跟踪代码管理器库。
如果您是 Google 跟踪代码管理器的新用户,建议您先 详细了解容器、宏和规则(帮助中心),然后再继续阅读本指南。
使用入门
本部分将引导开发者了解典型的跟踪代码管理器工作流程:
1. 将 Google 跟踪代码管理器 SDK 添加到您的项目中
在使用 Google 跟踪代码管理器 SDK 之前,您需要提取 SDK 软件包,并将该库添加到项目的构建路径,然后将权限添加到 AndroidManifest.xml 文件。
首先,将 Google 跟踪代码管理器库添加到项目的 /libs 文件夹。
接下来,更新 AndroidManifest.xml 文件以使用以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
2. 将默认容器文件添加到您的项目中
Google 跟踪代码管理器会在应用首次运行时使用默认容器。在应用能够通过网络检索新容器之前,系统将使用默认 容器。
如需下载默认容器二进制文件并将其添加到您的应用,请按以下步骤操作:
- 登录 Google 跟踪代码管理器网页界面。
- 选择要下载的容器的版本 。
- 点击下载 按钮以检索容器二进制文件。
- 将二进制文件添加到以下路径:
<project-root>/assets/tagmanager/
默认文件名应为容器 ID(例如 GTM-1234)。下载二进制文件后,请务必从文件名中移除版本后缀,以确保您遵循正确的命名惯例。
虽然建议使用二进制文件,但如果您的容器不包含规则或代码,
您可以选择改用 JSON 文件。该文件必须位于 Android 项目的新 /assets/tagmanager
文件夹中,并且应遵循以下命名惯例:
<Container_ID>.json。例如,如果您的容器 ID
为 GTM-1234,您应将默认容器值添加到
/assets/tagmanager/GTM-1234.json。
3. 打开容器
在从容器检索值之前,您的应用需要打开该容器。打开容器会从磁盘加载容器(如果可用),或从网络请求容器(如果需要)。
在 Android 上打开容器的最简单方法是使用 ContainerOpener.openContainer(..., Notifier notifier),如以下示例所示:
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 2000ms. 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. } }
在此示例中,ContainerOpener.openContainer(..., Notifier notifier) 用于从本地存储空间请求已保存的容器。 通过处理 containerAvailable 回调中的 mContainer 的分配,我们确保主线程不会被阻塞。如果已保存的容器超过 12 小时,该调用还会安排请求以异步方式通过网络检索新容器。
此示例实现展示了使用 ContainerOpener 便利类打开容器并从中检索值的最简单方法。
如需了解更多高级实现选项,请参阅高级配置。
4. 从容器获取配置值
打开容器后,可以使用
get<type>Value() 方法检索配置值:
// Retrieving a configuration value from a Tag Manager Container. // Get the configuration value by key. String title = mContainer.getStringValue("title_string");
使用不存在的键发出的请求将返回适合所请求类型的默认值 :
// 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. 将值推送到 DataLayer
DataLayer 是一个映射,可让容器中的跟踪代码管理器宏和代码获取有关应用的运行时信息,例如触摸 事件或屏幕浏览。
例如,通过将有关屏幕浏览的信息推送到 DataLayer 映射, 您可以在跟踪代码管理器网页界面中设置代码,以触发转化像素 和跟踪调用来响应那些屏幕浏览,而无需将它们硬 编码到应用中。
事件使用 push() 和
DataLayer.mapOf() 辅助方法推送到 DataLayer:
// // 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 }
在网页界面中,您现在可以创建代码(例如 Google Analytics 代码) 以便通过创建以下规则为每次屏幕浏览量触发代码: 等于“openScreen”。如需将屏幕名称 传递给其中一个代码,请创建一个数据层宏,该宏引用数据层中的“screenName” 键。您还可以创建一个代码 (例如 Google Ads 转化像素),以便仅针对特定屏幕浏览触发代码,方法是 创建规则,其中 等于“openScreen” && 等于“ConfirmationScreen”。
6. 预览和发布容器
宏值将始终与当前已发布版本对应。 在发布最新版本的容器之前,您可以预览容器草稿。
如需预览容器,请在 Google 跟踪代码管理器网页界面中选择要预览的容器版本,然后选择 Preview,从而生成预览网址。保存此预览网址,因为您将在后续步骤中需要它。
接下来,将以下 Activity 添加到应用的 AndroidManifest.xml 文件:
<!-- 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>
在模拟器或实体设备上打开该链接,即可预览应用中的容器草稿。
高级配置
移动版 Google 跟踪代码管理器提供了许多高级配置选项,可让您使用规则根据运行时条件选择值、手动刷新容器,以及获取用于打开容器的其他选项。以下部分概述了几个最常见的高级配置。
用于打开容器的高级选项
Google 跟踪代码管理器 SDK 提供了多种用于打开容器的方法,可让您更好地控制加载过程:
TagManager.openContainer()
TagManager.openContainer() 是用于打开容器的最低级别且最灵活的 API。它会立即返回默认容器,并且还会异步从磁盘或网络加载容器(如果不存在已保存的容器,或者已保存的容器不是最新的容器,即超过 12 小时)。
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. }
在整个加载过程中,TagManager.openContainer() 会发出多个生命周期回调,以便您的代码可以了解加载请求何时开始、是否失败以及失败或成功的原因,以及容器最终是从磁盘还是网络加载的。
除非您的应用可以使用默认值,否则您需要使用这些回调来了解已保存的容器或网络容器何时加载。请注意,如果这是应用首次运行且没有网络连接,您将无法加载已保存的容器或网络容器。
TagManager.openContainer() 会将以下 enum 值作为实参传递给这些回调:
RefreshType
| 值 | 说明 |
|---|---|
Container.Callback.SAVED
|
刷新请求正在加载本地保存的容器。 |
Container.Callback.NETWORK
|
刷新请求正在通过网络加载容器。 |
RefreshFailure
| 值 | 说明 |
|---|---|
Container.Callback.NO_SAVED_CONTAINER
|
没有可用的已保存容器。 |
Container.Callback.IO_ERROR
|
I/O 错误阻止了容器刷新。 |
Container.Callback.NO_NETWORK
|
没有可用的网络连接。 |
Container.Callback.NETWORK_ERROR
|
发生了网络错误。 |
Container.Callback.SERVER_ERROR
|
服务器上发生了错误。 |
Container.Callback.UNKNOWN_ERROR
|
发生了无法分类的错误。 |
用于打开非默认容器和新容器的方法
ContainerOpener 封装了 TagManager.openContainer()
并提供了两种用于打开容器的便利方法:
ContainerOpener.openContainer(..., Notifier notifier) 和
ContainerOpener.openContainer(..., Long timeoutInMillis)。
每种方法都采用枚举,请求非默认容器或新容器。
对于大多数应用,建议使用 OpenType.PREFER_NON_DEFAULT,它会尝试在给定的超时期限内从磁盘或网络返回第一个可用的非默认容器,即使该容器超过 12 小时也是如此。如果它返回过时的已保存容器,还会异步发出网络请求以获取新容器。
使用 OpenType.PREFER_NON_DEFAULT 时,如果没有其他容器可用,或者超时期限已过,系统将返回默认容器。
OpenType.PREFER_FRESH 会尝试在给定的超时期限内从磁盘或网络返回新容器。
如果网络连接不可用和/或超时期限已过,它会返回已保存的容器。
不建议在请求时间较长可能会明显影响用户体验的地方使用 OpenType.PREFER_FRESH,例如界面标志或显示字符串。您还可以随时使用
Container.refresh()
强制发出网络容器请求。
这两种便利方法都是非阻塞的。
ContainerOpener.openContainer(..., Long timeoutInMillis) 会返回一个
ContainerOpener.ContainerFuture 对象,其 get 方法会在加载后立即返回
Container(但在此之前会阻塞)。
ContainerOpener.openContainer(..., Notifier notifier) 方法采用单个回调(在容器可用时调用),可用于防止阻塞主线程。这两种方法的默认超时期限均为 2000 毫秒。
在运行时使用规则评估宏
容器可以在运行时使用规则评估值。规则可以基于设备语言、平台或任何其他宏值等条件。例如,规则可用于在运行时根据设备的语言选择本地化的显示字符串。您可以使用以下规则进行配置:
然后,您可以为每种语言创建值集合宏,并将此规则添加到每个宏,并插入相应的语言代码。发布此容器后,您的应用将能够根据用户设备在运行时的语言显示本地化的显示字符串。
请注意,如果您的默认容器需要规则,您必须使用 a 二进制容器文件作为您的默认 容器。
二进制默认容器文件
需要规则的默认容器应使用二进制容器文件 而不是 JSON 文件 作为默认容器。二进制容器支持使用 Google 跟踪代码管理器规则在运行时确定 宏值,而 JSON 文件不支持。
二进制容器文件可以从 Google 跟踪代码管理器 web
界面下载,应添加到项目的
/assets/tagmanager/ 文件夹,并遵循以下模式:
/assets/tagmanager/GTM-XXXX,其中文件名表示您的
容器 ID。
如果同时存在 JSON 文件和二进制容器文件,SDK 将使用二进制容器文件作为默认容器。
使用函数调用宏
函数调用宏是指设置为应用中指定函数的返回值的宏。函数调用宏可用于将运行时值与 Google 跟踪代码管理器规则结合使用,例如在运行时根据设备的配置语言和货币确定向用户显示的价格。
如需配置函数调用宏,请执行以下操作:
- 在 Google 跟踪代码管理器网页界面中定义函数调用宏。 您可以选择将实参配置为键值对。
- 使用
Container.registerFunctionCallMacroHandler()和您在 Google 跟踪代码管理器网页界面中配置的函数名称在应用中注册FunctionCallMacroHandler,并替换其getValue()方法:/** * 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; } });
使用函数调用代码
每当事件被推送到数据层且代码规则
评估为 true 时,函数调用代码都会执行预注册函数。
如需配置函数调用代码,请执行以下操作:
- 在 Google 跟踪代码管理器网页界面中定义函数调用代码。 您可以选择将实参配置为键值对。
- 使用
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. } } });
设置自定义刷新周期
如果当前容器的有效期超过 12 小时,Google 跟踪代码管理器 SDK 将尝试检索新容器。如需设置自定义容器刷新周期,请使用 Timer,如以下示例所示:
timer.scheduleTask(new TimerTask() { @Override public void run() { mContainer.refresh(); } }, delay, <new_period_in milliseconds>);
使用 Logger 进行调试
默认情况下,Google 跟踪代码管理器 SDK 会将错误和警告输出到日志。
启用更详细的日志记录有助于调试,您可以通过
实现自己的 Logger 来启用更详细的日志记录,如以下示例所示:TagManager.setLogger
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. });
或者,您可以使用
TagManager.getLogger().setLogLevel(LogLevel)
设置现有 Logger 的 LogLevel,
如以下示例所示:
// Change the LogLevel to INFO to enable logging at INFO and higher levels. TagManager tagManager = TagManager.getInstance(this); tagManager.getLogger().setLogLevel(LogLevel.INFO);