本开发者指南将介绍如何在移动应用中实现 Google 跟踪代码管理器。
简介
借助 Google 跟踪代码管理器,开发者可以使用 Google 跟踪代码管理器界面更改移动应用中的配置值,而无需重新生成应用二进制文件并将其重新提交到应用市场。
这对于管理应用中将来可能需要更改的任何配置值或标志非常有用,包括:
- 各种界面设置和显示字符串
- 您应用中投放的广告的尺寸、位置或类型
- 游戏设置
配置值也可以在运行时使用规则求值,以实现以下动态配置:
- 根据屏幕尺寸确定广告横幅的尺寸
- 使用语言和位置配置界面元素
Google 跟踪代码管理器还支持在应用中动态实现跟踪代码和像素。开发者可以将重要事件推送到数据层,稍后再决定应触发哪些跟踪代码或像素。 跟踪代码管理器目前支持以下代码:
- Google移动应用分析
- 自定义函数调用代码
准备工作
在使用此入门指南之前,您需要做好以下准备:
- Google 跟踪代码管理器帐号
- 新增了跟踪代码管理器 容器和值集合宏
- 一款适用于 Android 的移动应用,您可以在其中实现 Google 跟踪代码管理器
- 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
毫秒。
在运行时使用规则评估宏
容器可以在运行时使用规则评估值。规则可以基于设备语言、平台或任何其他宏值等条件。例如,您可以使用规则,根据运行时设备的语言选择本地化的显示字符串。这可以使用以下规则进行配置:
然后,您可以为每种语言创建值集合宏,并将此规则添加到每个宏中,并插入相应的语言代码。此容器发布后,您的应用将能够显示本地化的显示字符串,具体取决于运行时用户设备的语言。
请注意,如果您的默认容器需要规则,您必须使用二进制容器文件作为默认容器。
默认容器二进制文件
需要规则的默认容器应使用二进制容器文件(而不是 JSON 文件)作为默认容器。二进制容器支持在运行时使用 Google 跟踪代码管理器规则确定宏值,而 JSON 文件则不支持。
您可以从 Google 跟踪代码管理器网页界面下载二进制容器文件,这些文件应添加到项目的 /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>);
使用日志记录器进行调试
默认情况下,Google 跟踪代码管理器 SDK 会将错误和警告输出到日志中。启用更详细的日志记录有助于调试,并且可以通过使用 TagManager.setLogger
实现您自己的 Logger
来实现,如以下示例所示:
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);