Objective-C 入门指南

本开发者指南将介绍如何在 Google 跟踪代码管理器中 。

简介

借助 Google 跟踪代码管理器,开发者可以更改配置 通过 Google 跟踪代码管理器在移动应用中植入 而无需重新生成应用二进制文件并将其重新提交给应用 市场。

这对于管理任何配置值非常有用 或标志(将来可能需要更改的标志), 包括:

  • 各种界面设置和显示字符串
  • 应用中投放的广告的尺寸、位置或类型
  • 游戏设置

也可以在运行时使用规则评估配置值 启用动态配置,例如:

  • 根据屏幕尺寸确定横幅广告尺寸
  • 使用语言和位置配置界面元素

Google 跟踪代码管理器还支持动态实现跟踪代码 和像素。开发者可以将重要事件推送到数据中, 层,并决定应触发哪些跟踪代码或像素。 跟踪代码管理器目前支持以下代码:

  • Google移动应用分析
  • 自定义函数调用代码

准备工作

在使用本入门指南之前,您需要做好以下准备:

如果您刚开始接触 Google 跟踪代码管理器,我们建议您 请先详细了解容器、宏和规则(帮助中心),然后再继续本指南。

使用入门

本部分将指导开发者完成典型的跟踪代码管理器工作流程:

  1. 将 Google 跟踪代码管理器 SDK 添加到您的项目中
  2. 设置默认容器值
  3. 打开容器
  4. 从容器获取配置值
  5. 将事件推送到 DataLayer
  6. 预览和发布容器

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 跟踪代码管理器会在您的应用首次运行时使用默认容器。默认 系统将使用容器,直到应用能够通过容器检索到 。

如需下载默认容器二进制文件并将其添加到您的应用,请按以下步骤操作:

  1. 登录 Google 跟踪代码管理器网页界面。
  2. 选择您要下载的容器的版本
  3. 点击下载按钮,获取容器二进制文件。
  4. 将二进制文件添加到 项目的根目录下的“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。请稍候 此预览网址,因为您在后续步骤中会用到它。

您可以在代码的预览窗口中找到预览网址
           经理网页界面
图 1:从跟踪代码管理器网页界面获取预览网址。

如需启用容器预览,您必须向应用添加代码 委托实现文件并定义 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">
</ph> 在您应用的
                属性列表文件。
图 3 :添加跟踪代码管理器预览网址架构 添加到应用的属性列表文件中。

在模拟器或实体设备上打开链接 在应用中预览草稿容器。

准备好将草稿配置值提供给您的 应用程序, 发布容器

高级配置

移动版 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 秒。

使用规则在运行时评估宏

容器可以在运行时使用规则评估值。规则可能 例如设备语言、平台或任何其他宏值对于 例如,可以使用规则根据 设备的语言。您可以使用 以下规则:

使用规则根据设备语言选择显示字符串,
            runtime: language 等于 es。此规则使用预定义的语言
            宏和两个字符的 ISO 639-1 语言代码。
图 1:添加规则以仅针对设备启用值收集宏 已设为使用西班牙语。

然后,您可以为每种语言创建值集合宏,并将此 规则,插入相应的语言代码。这个容器 发布后,您的应用将能够在 字符串,具体取决于用户设备在运行时的语言。

请注意,如果您的默认容器需要规则,您必须使用 二进制文件容器文件 容器。

详细了解如何配置规则(帮助中心)。

默认二进制文件容器文件

需要规则的默认容器应使用二进制容器文件 而不是属性列表文件或 JSON 文件作为默认容器。二元容器支持确定 宏值,而 属性列表或 JSON 文件不能。

二进制容器文件可从 Google 跟踪代码管理器网站下载 和 应按照以下命名惯例添加到您的主应用软件包中: GTM-XXXX,其中文件名表示您的 容器 ID。

在属性列表文件和/或 JSON 文件的情况下 以及二进制容器文件存在时,SDK 将使用二进制容器 文件作为默认容器。

使用函数调用宏

函数调用宏是设置为 指定函数函数调用宏可用于 将运行时值纳入您的 Google 跟踪代码管理器规则中,例如 在运行时根据配置的 设备的语言和货币

如需配置函数调用宏,请执行以下操作:

  1. 在 Google 跟踪代码管理器网页界面中定义函数调用宏。 您可以选择将参数配置为键值对。
  2. 定义一个实现 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
    
  3. 使用 TAGContainer::registerFunctionCallMacroHandler:forMacro: 和函数名称注册处理程序 在 Google 跟踪代码管理器界面中指定:
  4. //
    // 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

如需配置函数调用代码,请执行以下操作:

  1. 在 Google 跟踪代码管理器网页界面中定义函数调用代码。 您可以选择将参数配置为键值对。
  2. 实现 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
    
  3. 使用在 Google 跟踪代码管理器网页界面:
  4. //
    // 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];