本开发者指南将介绍如何在 Google 跟踪代码管理器中 。
简介
借助 Google 跟踪代码管理器,开发者可以更改配置 通过 Google 跟踪代码管理器在移动应用中植入 而无需重新生成应用二进制文件并将其重新提交给应用 市场。
这对于管理任何配置值非常有用 或标志(将来可能需要更改的标志), 包括:
- 各种界面设置和显示字符串
- 应用中投放的广告的尺寸、位置或类型
- 游戏设置
也可以在运行时使用规则评估配置值 启用动态配置,例如:
- 根据屏幕尺寸确定横幅广告尺寸
- 使用语言和位置配置界面元素
Google 跟踪代码管理器还支持动态实现跟踪代码 和像素。开发者可以将重要事件推送到数据中, 层,并决定应触发哪些跟踪代码或像素。 跟踪代码管理器目前支持以下代码:
- Google移动应用分析
- 自定义函数调用代码
准备工作
在使用本入门指南之前,您需要做好以下准备:
- 一个 Google 跟踪代码管理器账号
- 新的跟踪代码管理器 容器和值收集宏
- iOS 版移动应用,其中实现 Google 跟踪代码管理器
- Google Analytics 服务 SDK,其中包含跟踪代码管理器库。
如果您刚开始接触 Google 跟踪代码管理器,我们建议您 请先详细了解容器、宏和规则(帮助中心),然后再继续本指南。
使用入门
本部分将指导开发者完成典型的跟踪代码管理器工作流程:
1. 将 Google 跟踪代码管理器 SDK 添加到您的项目中
在使用 Google 跟踪代码管理器 SDK 之前,您需要将
libGoogleAnalyticsServices.a
以及 Library
中的 Google 跟踪代码管理器 (GTM) 头文件
目录中。
接下来,将以下内容添加到应用目标的关联库中(如果它们 :
CoreData.framework
SystemConfiguration.framework
libz.dylib
libsqlite3.dylib
libGoogleAnalyticsServices.a
如果您希望应用访问 广告客户 (IDFA) 和跟踪标记, Google 跟踪代码管理器 SDK 宏,那么您还需要关联下面这些额外的库:
libAdIdAccess.a
AdSupport.framework
2. 将默认容器文件添加到项目中
Google 跟踪代码管理器会在您的应用首次运行时使用默认容器。默认 系统将使用容器,直到应用能够通过容器检索到 。
如需下载默认容器二进制文件并将其添加到您的应用,请按以下步骤操作:
- 登录 Google 跟踪代码管理器网页界面。
- 选择您要下载的容器的版本。
- 点击下载按钮,获取容器二进制文件。
- 将二进制文件添加到 项目的根目录下的“Supporting Files”文件夹中的文件
默认文件名应为容器 ID(例如 GTM-1234
)。安装
下载了二进制文件,请务必从文件名中移除版本后缀
以确保遵循正确的命名惯例。
虽然我们建议使用二进制文件,但如果您的容器不包含规则或代码,
则可以选择使用简单的
属性列表或 JSON
文件。
该文件应位于主 bundle 中,且应跟随路径
命名惯例:<Container_ID>.<plist|json>
。
例如,如果您的容器 ID 为 GTM-1234
,则可以指定
并将默认容器值存储在名为
GTM-1234.plist
。
3. 打开容器
在从容器中检索值之前,您的应用需要打开 容器。打开容器将从磁盘加载该容器(如果有),或者 将向网络请求该标识符(如果需要)。
要在 iOS 上打开容器,最简单的方法是使用
openContainerWithId:tagManager:openType:timeout:notifier:
,如以下示例所示:
// MyAppDelegate.h // This example assumes this file is using ARC. #import <UIKit/UIKit.h> @class TAGManager; @class TAGContainer; @interface MyAppDelegate : UIResponder <UIApplicationDelegate> @property (nonatomic, strong) TAGManager *tagManager; @property (nonatomic, strong) TAGContainer *container; @end // MyAppDelegate.m // This example assumes this file is using ARC. #import "MyAppDelegate.h" #import "TAGContainer.h" #import "TAGContainerOpener.h" #import "TAGManager.h" @interface MyAppDelegate ()<TAGContainerOpenerNotifier> @end @implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.tagManager = [TAGManager instance]; // Optional: Change the LogLevel to Verbose to enable logging at VERBOSE and higher levels. [self.tagManager.logger setLogLevel:kTAGLoggerLogLevelVerbose]; /* * Opens a container. * * @param containerId The ID of the container to load. * @param tagManager The TAGManager instance for getting the container. * @param openType The choice of how to open the container. * @param timeout The timeout period (default is 2.0 seconds). * @param notifier The notifier to inform on container load events. */ [TAGContainerOpener openContainerWithId:@"GTM-XXXX" // Update with your Container ID. tagManager:self.tagManager openType:kTAGOpenTypePreferFresh timeout:nil notifier:self]; // Method calls that don't need the container. return YES; } // TAGContainerOpenerNotifier callback. - (void)containerAvailable:(TAGContainer *)container { // Note that containerAvailable may be called on any thread, so you may need to dispatch back to // your main thread. dispatch_async(dispatch_get_main_queue(), ^{ self.container = container; }); } // The rest of your app delegate implementation.
4. 从容器中获取配置值
容器打开后,可以使用
该
<type>ForKey:
方法:
// Retrieving a configuration value from a Tag Manager Container. MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate]; TAGContainer *container = appDelegate.container; // Get the configuration value by key. NSString *title = [container stringForKey:@"title_string"];
使用不存在的键发出的请求将返回相应的默认值 更改为请求的类型:
// Empty keys will return a default value depending on the type requested. // Key does not exist. An empty string is returned. NSString subtitle = [container stringForKey:@"Non-existent-key"]; [subtitle isEqualToString:@""]; // Evaluates to true.
5. 将值推送到 DataLayer
DataLayer 是一个地图,可启用有关应用的运行时信息,例如触摸 事件或屏幕浏览事件,以提供给跟踪代码管理器宏和代码, 容器。
例如,将有关屏幕浏览的信息推送到 DataLayer 地图, 则可以在跟踪代码管理器网页界面中设置代码以触发转化像素 并跟踪调用以响应这些屏幕浏览量, 将其编码到应用中
使用 push:
将事件推送到数据层
// // ViewController.m // Pushing an openScreen event with a screen name into the data layer. // #import "MyAppDelegate.h" #import "TAGDataLayer.h" #import "ViewController.h" @implementation ViewController - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // The container should have already been opened, otherwise events pushed to // the data layer will not fire tags in that container. TAGDataLayer *dataLayer = [TAGManager instance].dataLayer; [dataLayer push:@{@"event": @"openScreen", @"screenName": @"Home Screen"}]; } // Rest of the ViewController implementation @end
在网页界面中,您现在可以创建代码(例如 Google Analytics 代码) 创建以下规则来针对每个屏幕浏览触发: 为“openScreen”。传递屏幕名称 添加到上述某个代码中,请创建一个引用“screenName”参数的数据层宏, 键。你还可以创建代码 (如 Google Ads 转化像素)设置为仅针对特定屏幕浏览触发,具体方法是: 创建一条规则,其中为“openScreen” && 为“ConfirmationScreen”。
6. 预览与发布容器
宏值将始终与当前发布的版本相对应。 在发布容器的最新版本之前,您可以预览 草稿容器
要预览容器,请在 Google
跟踪代码管理器网页界面:选择容器版本
您想预览的内容,然后选择Preview
。请稍候
此预览网址,因为您在后续步骤中会用到它。
如需启用容器预览,您必须向应用添加代码 委托实现文件并定义 Google 跟踪代码管理器预览网址 架构。
首先,将以下加粗的代码段添加到应用委托文件中:
@implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.tagManager = [TAGManager instance]; // Add the code in bold below to preview a Google Tag Manager container. // IMPORTANT: This code must be called before the container is opened. NSURL *url = [launchOptions valueForKey:UIApplicationLaunchOptionsURLKey]; if (url != nil) { [self.tagManager previewWithUrl:url]; } id<TAGContainerFuture> future = [TAGContainerOpener openContainerWithId:@"GTM-XXXX" // Placeholder Container ID. tagManager:self.tagManager openType:kTAGOpenTypePreferNonDefault timeout:nil]; // The rest of your method implementation. self.container = [future get]; return YES; } // Add the code in bold below preview a Google Tag Manager container. - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if ([self.tagManager previewWithUrl:url]) { return YES; } // Code to handle other urls. return NO; }
接下来,在 应用属性列表文件的网址类型键:
URL identifier: your.package_name URL scheme: tagmanager.c.your.package.name<ph type="x-smartling-placeholder">。
在模拟器或实体设备上打开链接 在应用中预览草稿容器。
准备好将草稿配置值提供给您的 应用程序, 发布容器。
高级配置
移动版 Google 跟踪代码管理器提供一系列高级配置, 可让您根据运行时条件选择值, 手动刷新容器,并获取用于打开 容器以下各部分概述了一些最常用的高级方法, 配置。
打开容器的高级选项
Google 跟踪代码管理器 SDK 提供了多种方法来打开 容器,可让您更好地控制加载过程:
openContainerById:callback:
openContainerById:callback:
是最低级别且最灵活的 API,用于
容器。它会立即返回一个默认容器,
还会异步从磁盘或网络加载容器,
容器是否存在,或者保存的容器不是最新的(超过 12 小时)。
@interface ContainerCallback : NSObject<TAGContainerCallback> @end @implementation ContainerCallback /** * Called before the refresh is about to begin. * * @param container The container being refreshed. * @param refreshType The type of refresh which is starting. */ - (void)containerRefreshBegin:(TAGContainer *)container refreshType:(TAGContainerCallbackRefreshType)refreshType { // Notify UI that container refresh is beginning. } /** * Called when a refresh has successfully completed for the given refresh type. * * @param container The container being refreshed. * @param refreshType The type of refresh which completed successfully. */ - (void)containerRefreshSuccess:(TAGContainer *)container refreshType:(TAGContainerCallbackRefreshType)refreshType { // Notify UI that container is available. } /** * Called when a refresh has failed to complete for the given refresh type. * * @param container The container being refreshed. * @param failure The reason for the refresh failure. * @param refreshType The type of refresh which failed. */ - (void)containerRefreshFailure:(TAGContainer *)container failure:(TAGContainerCallbackRefreshFailure)failure refreshType:(TAGContainerCallbackRefreshType)refreshType { // Notify UI that container request has failed. } @end
在整个加载过程中,存在openContainerById:callback:
个问题
多个生命周期回调,以便您的代码发现
加载请求开始,是否失败或成功及其原因,以及是否
容器最终是从磁盘或网络加载的。
除非您的应用允许使用默认值 您需要使用这些回调来了解 容器加载完成请注意,您将无法加载已保存的 网络容器(如果这是首次运行该应用,并且没有 网络连接。
openContainerById:callback:
会将以下 enum
值作为参数传递给这些回调:
RefreshType
值 | 说明 |
---|---|
kTAGContainerCallbackRefreshTypeSaved
|
刷新请求正在加载保存在本地的容器。 |
kTAGContainerCallbackRefreshTypeNetwork
|
刷新请求通过网络加载容器。 |
RefreshFailure
值 | 说明 |
---|---|
kTAGContainerCallbackRefreshFailureNoSavedContainer
|
没有可用的已保存容器。 |
kTAGContainerCallbackRefreshFailureIoError
|
I/O 错误阻止刷新容器。 |
kTAGContainerCallbackRefreshFailureNoNetwork
| 没有可用的网络连接。 |
kTAGContainerCallbackRefreshFailureNetworkError
|
出现网络错误。 |
kTAGContainerCallbackRefreshFailureServerError
|
服务器上出现错误。 |
kTAGContainerCallbackRefreshFailureUnknownError
|
发生了无法分类的错误。 |
打开非默认容器和最新容器的方法
TAGContainerOpener
封装 openContainerById:callback:
提供两种打开容器的便捷方法:
openContainerWithId:tagManager:openType:timeout:notifier:
和
openContainerWithId:tagManager:openType:timeout:
。
这些方法均采用枚举,用于请求非默认或 容器。
建议为大多数应用使用 kTAGOpenTypePreferNonDefault
,
尝试返回指定的给定容器中第一个可用的非默认容器
超时期限(磁盘或网络),即使该容器
超过 12 小时。如果它返回过时的已保存容器,
异步网络请求
使用 kTAGOpenTypePreferNonDefault
时,
如果没有其他容器可用,或者超时期限已过,则返回容器。
超出上限。
kTAGOpenTypePreferFresh
尝试从
磁盘或网络的流量。
如果某个广告网络
连接不可用和/或已超过超时期限。
不建议使用 kTAGOpenTypePreferFresh
在请求时间较长可能会明显影响用户体验的情况下,
例如使用界面标记或显示字符串您还可以使用
TAGContainer::refresh
(不限时间)
来强制执行网络容器请求
这两种便捷方法都是非阻塞的。
openContainerWithId:tagManager:openType:timeout:
会返回
TAGContainerFuture
对象,其 get
方法会返回
TAGContainer
(但在此之前,该操作将阻塞)。
openContainerWithId:tagManager:openType:timeout:notifier:
方法接受单个回调,
在容器可用时调用的方法。
两种方法的默认超时期限均为
2.0
秒。
使用规则在运行时评估宏
容器可以在运行时使用规则评估值。规则可能 例如设备语言、平台或任何其他宏值对于 例如,可以使用规则根据 设备的语言。您可以使用 以下规则:
然后,您可以为每种语言创建值集合宏,并将此 规则,插入相应的语言代码。这个容器 发布后,您的应用将能够在 字符串,具体取决于用户设备在运行时的语言。
请注意,如果您的默认容器需要规则,您必须使用 二进制文件容器文件 容器。
默认二进制文件容器文件
需要规则的默认容器应使用二进制容器文件 而不是属性列表文件或 JSON 文件作为默认容器。二元容器支持确定 宏值,而 属性列表或 JSON 文件不能。
二进制容器文件可从 Google 跟踪代码管理器网站下载
和
应按照以下命名惯例添加到您的主应用软件包中:
GTM-XXXX
,其中文件名表示您的
容器 ID。
在属性列表文件和/或 JSON 文件的情况下 以及二进制容器文件存在时,SDK 将使用二进制容器 文件作为默认容器。
使用函数调用宏
函数调用宏是设置为 指定函数函数调用宏可用于 将运行时值纳入您的 Google 跟踪代码管理器规则中,例如 在运行时根据配置的 设备的语言和货币
如需配置函数调用宏,请执行以下操作:
- 在 Google 跟踪代码管理器网页界面中定义函数调用宏。 您可以选择将参数配置为键值对。
- 定义一个实现
TAGFunctionCallMacroHandler
的处理程序 协议:// MyFunctionCallMacroHandler.h #import "TAGContainer.h" // The function name field of the macro, as defined in the Google Tag Manager // web interface. extern NSString *const kMyMacroFunctionName; @interface MyFunctionCallMacroHandler : NSObject<TAGFunctionCallMacroHandler> @end // MyFunctionCallMacroHandler.m #import "MyFunctionCallMacroHandler.h" // Corresponds to the function name field in the Google Tag Manager interface. NSString *const kMyMacroFunctionName = @"myConfiguredFunctionName"; @implementation MacroHandler - (id)valueForMacro:(NSString *)functionName parameters:(NSDictionary *)parameters { if ([functionName isEqualToString:kMyMacroFunctionName]) { // Process and return the calculated value of this macro accordingly. return macro_value; } return nil; } @end
- 使用 TAGContainer::registerFunctionCallMacroHandler:forMacro: 和函数名称注册处理程序 在 Google 跟踪代码管理器界面中指定:
// // MyAppDelegate.h // #import <UIKit/UIKit.h> @interface MyAppDelegate : UIResponder <UIApplicationDelegate> @end // // MyAppDelegate.m // #import "MyAppDelegate.h" #import "MyFunctionCallMacroHandler.h" #import "TAGContainer.h" #import "TAGContainerOpener.h" #import "TAGManager.h" @implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Open the container. id<TAGContainerFuture> future = [TAGContainerOpener openContainerWithId:@"GTM-XXXX" // Placeholder Container ID. tagManager:[TAGManager instance] openType:kTAGOpenTypePreferNonDefault timeout:nil]; // Method calls that don't need the container. self.container = [future get]; // Register a function call macro handler using the macro name defined // in the Google Tag Manager web interface. [self.container registerFunctionCallMacroHandler:[[MyFunctionCallMacroHandler alloc] init] forMacro:kMyMacroFunctionName]; } @end
使用函数调用标记
借助函数调用代码,每当用户调用预注册函数时,
将事件推送到数据层和代码规则
求得的值为 true
。
如需配置函数调用代码,请执行以下操作:
- 在 Google 跟踪代码管理器网页界面中定义函数调用代码。 您可以选择将参数配置为键值对。
- 实现
TAGFunctionCallTagHandler
协议:// // MyFunctionCallTagHandler.h // #import "TAGContainer.h" extern NSString *const kMyTagFunctionName; @interface MyFunctionCallTagHandler : NSObject<TAGFunctionCallTagHandler> @end // // MyFunctionCallTagHandler.m // // Corresponds to the function name field in the Google Tag Manager interface. NSString *const kMyTagFunctionName = @"myConfiguredFunctionName"; @implementation MyFunctionCallTagHandler /** * This method will be called when any custom tag's rule(s) evaluate to true and * should check the functionName and process accordingly. * * @param functionName corresponds to the function name field, not tag * 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. */ - (void)execute:(NSString *)functionName parameters:(NSDictionary *)parameters { if ([functionName isEqualToString:kMyTagFunctionName]) { // Process accordingly. } } @end
- 使用在 Google 跟踪代码管理器网页界面:
// // MyAppDelegate.h // #import <UIKit/UIKit.h> @interface MyAppDelegate : UIResponder <UIApplicationDelegate> @end // // MyAppDelegate.m // #import "MyAppDelegate.h" #import "MyFunctionCallTagHandler.h" #import "TAGContainer.h" #import "TAGContainerOpener.h" #import "TAGManager.h" @implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Open the container. id<TAGContainerFuture> future = [TAGContainerOpener openContainerWithId:@"GTM-XXXX" // Placeholder Container ID. tagManager:[TAGManager instance] openType:kTAGOpenTypePreferNonDefault timeout:nil]; // Method calls that don't need the container. self.container = [future get]; // Register a function call tag handler using the function name of the tag as // defined in the Google Tag Manager web interface. [self.container registerFunctionCallTagHandler:[[MyFunctionCallTagHandler alloc] init] forTag:kMyTagFunctionName]; } @end
设置自定义刷新周期
Google 跟踪代码管理器 SDK 将尝试
一个新容器(如果当前容器的存在时间超过 12 小时)。要设置
自定义容器刷新周期,请使用
NSTimer
,如
示例:
- (void)refreshContainer:(NSTimer *)timer { [self.container refresh]; } self.refreshTimer = [NSTimer scheduledTimerWithTimeInterval:<refresh_interval> target:self selector:@selector(refreshContainer:) userInfo:nil repeats:YES];
使用 Logger 调试
默认情况下,Google 跟踪代码管理器 SDK 会将错误和警告输出到日志中。
启用更详细的日志记录有助于进行调试,
实现自己的 Logger
,如以下示例所示:
// MyAppDelegate.h // This example assumes this file is using ARC. // This Logger class will print out not just errors and warnings (as the default // logger does), but also info, debug, and verbose messages. @interface MyLogger: NSObject<TAGLogger> @end @implementation MyLogger - (void)error:(NSString *)message { NSLog(@"Error: %@", message); } - (void)warning:(NSString *)message { NSLog(@"Warning: %@", message); } - (void)info:(NSString *)message { NSLog(@"Info: %@", message); } - (void)debug:(NSString *)message { NSLog(@"Debug: %@", message); } - (void)verbose:(NSString *)message { NSLog(@"Verbose: %@", message); } @end // MyAppDelegate.m // This example assumes this file is using ARC. @implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.tagManager = [TAGManager instance]; self.tagManager.logger = [[MyLogger alloc] init]; // Rest of Tag Manager and method implementation. return YES; } // Rest of app delegate implementation. @end
或者,你可以使用
TagManager::logger::setLogLevel
,
如以下示例中所示:
// Change the LogLevel to INFO to enable logging at INFO and higher levels. self.tagManager = [TAGManager instance]; [self.tagManager.logger setLogLevel:kTAGLoggerLogLevelInfo];