Guia de iniciação para Objective-C

Este guia para desenvolvedores descreve como implementar o Google Tag Manager em um aplicativo para dispositivos móveis.

Introdução

O Google Tag Manager permite que os desenvolvedores mudem os valores de configuração nos aplicativos para dispositivos móveis usando a interface do Google Tag Manager sem precisar recriar e reenviar os binários de aplicativos aos marketplaces.

Isso é útil para gerenciar valores ou flags de configuração no aplicativo que você pode precisar mudar no futuro, incluindo:

  • Várias configurações de interface e strings de exibição
  • Tamanhos, locais ou tipos de anúncios veiculados no aplicativo
  • Configurações de jogos

Os valores de configuração também podem ser avaliados no tempo de execução usando regras, permitindo configurações dinâmicas, como:

  • Usar o tamanho da tela para determinar o tamanho do banner de anúncio
  • Usar o idioma e o local para configurar elementos da interface

O Google Tag Manager também permite a implementação dinâmica de tags e pixels de acompanhamento em aplicativos. Os desenvolvedores podem enviar eventos importantes para uma camada de dados e decidir mais tarde quais tags ou pixels de acompanhamento precisam ser disparados. O Tag Manager oferece suporte às seguintes tags:

  • Google Mobile App Analytics
  • Tag de chamada de função personalizada

Antes de começar

Antes de usar este guia de introdução, você vai precisar do seguinte:

Se você não conhece o Google Tag Manager, recomendamos que saiba mais sobre contêineres, macros e regras (Central de Ajuda) antes de continuar com este guia.

Primeiros passos

Esta seção orienta os desenvolvedores em um fluxo de trabalho típico do Tag Manager:

  1. Adicionar o SDK do Google Tag Manager ao seu projeto
  2. Definir valores de contêiner padrão
  3. Abrir o contêiner
  4. Receber valores de configuração do contêiner
  5. Enviar eventos para a camada de dados
  6. Visualizar e publicar o contêiner

1. Adicionar o SDK do Google Tag Manager ao seu projeto

Antes de usar o SDK do Google Tag Manager, adicione libGoogleAnalyticsServices.a e os arquivos de cabeçalho do Google Tag Manager (GTM) do diretório Library do pacote do SDK ao seu projeto.

Em seguida, adicione o seguinte às bibliotecas vinculadas do destino do aplicativo, se elas ainda não estiverem presentes:

  • CoreData.framework
  • SystemConfiguration.framework
  • libz.dylib
  • libsqlite3.dylib
  • libGoogleAnalyticsServices.a

Se você quiser que o aplicativo acesse o identificador para anunciantes (IDFA) e a flag de acompanhamento fornecida por essa estrutura usando as macros do SDK do Google Tag Manager, também será necessário vincular estas bibliotecas adicionais:

  • libAdIdAccess.a
  • AdSupport.framework

2. Adicionar um arquivo de contêiner padrão ao seu projeto

O Google Tag Manager usa um contêiner padrão na primeira execução do aplicativo. O contêiner padrão será usado até que o app possa recuperar um novo contêiner pela rede.

Para fazer o download e adicionar um binário de contêiner padrão ao aplicativo, siga estas etapas:

  1. Faça login na interface da Web do Google Tag Manager.
  2. Selecione a versão do contêiner que você quer baixar.
  3. Clique no botão Fazer download para recuperar o binário do contêiner.
  4. Adicione o arquivo binário ao diretório raiz do projeto e à pasta "Supporting Files" no projeto.

O nome de arquivo padrão precisa ser o ID do contêiner (por exemplo GTM-1234). Depois de baixar o arquivo binário, remova o sufixo da versão do nome do arquivo para garantir que você siga a convenção de nomenclatura correta.

Embora o uso do arquivo binário seja recomendado, se o contêiner não contiver regras ou tags, você poderá usar uma lista de propriedades ou um arquivo JSON. O arquivo precisa estar no pacote principal e seguir esta convenção de nomenclatura: <Container_ID>.<plist|json>. Por exemplo, se o ID do contêiner for GTM-1234, você poderá especificar os valores do contêiner padrão em um arquivo de lista de propriedades chamado GTM-1234.plist.

3. Abrir um contêiner

Antes de recuperar valores de um contêiner, o aplicativo precisa abrir o contêiner. A abertura de um contêiner o carrega do disco (se disponível) ou o solicita da rede (se necessário).

A maneira mais fácil de abrir um contêiner no iOS é usando openContainerWithId:tagManager:openType:timeout:notifier:, como no exemplo a seguir:

// 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. Receber valores de configuração do contêiner

Depois que o contêiner estiver aberto, os valores de configuração poderão ser recuperados usando os <type>ForKey: métodos:

// 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"];

As solicitações feitas com uma chave inexistente vão retornar um valor padrão adequado ao tipo solicitado:

// 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. Enviar valores para a camada de dados

A camada de dados é um mapa que permite que informações de tempo de execução sobre seu app, como eventos de toque ou visualizações de tela, fiquem disponíveis para macros e tags do Tag Manager em um contêiner.

Por exemplo, ao enviar informações sobre visualizações de tela para o mapa da camada de dados, você pode configurar tags na interface da Web do Tag Manager para disparar pixels de conversão e chamadas de acompanhamento em resposta a essas visualizações de tela sem precisar codificá-las no app.

Os eventos são enviados para a camada de dados usando 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

Na interface da Web, agora é possível criar tags (como tags do Google Analytics) para disparar para cada visualização de tela criando esta regra: é igual a "openScreen". Para transmitir o nome da tela para uma dessas tags, crie uma macro de camada de dados que faça referência à chave "screenName" na camada de dados. Você também pode criar uma tag (como um pixel de conversão do Google Ads) para disparar apenas para visualizações de tela específicas, criando uma regra em que é igual a "openScreen" && é igual a "ConfirmationScreen".

6. Visualizar e publicar um contêiner

Os valores de macro sempre correspondem à versão publicada atual. Antes de publicar a versão mais recente de um contêiner, você pode visualizar o contêiner de rascunho.

Para visualizar um contêiner, gere um URL de visualização na interface da Web do Google Tag Manager. Para isso, escolha a versão do contêiner desejada e selecione Preview. Salve esse URL de visualização, porque ele será necessário nas etapas posteriores.

Os URLs de visualização estão disponíveis na janela de visualização da interface da Web do Gerenciador de tags.
Figura 1: como gerar um URL de visualização na interface da Web do Tag Manager.

Para ativar as visualizações de contêiner, adicione código ao arquivo de implementação do representante do app e defina o esquema de URL de visualização do Google Tag Manager na lista de propriedades do seu projeto.

Primeiro, adicione os seguintes snippets de código em negrito ao arquivo do representante do app:

@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;
}

Em seguida, registre o identificador e o esquema de URL a seguir na chave de tipos de URL do arquivo da lista de propriedades do aplicativo:

URL identifier: your.package_name
URL scheme: tagmanager.c.your.package.name
Registre o esquema de URL de visualização do Gerenciador de tags no arquivo da lista de propriedades do seu app.
Figura 3: como adicionar o esquema de URL de visualização do Tag Manager ao arquivo da lista de propriedades do seu aplicativo.

Abra o link em um emulador ou dispositivo físico para visualizar o contêiner de rascunho no app.

Quando estiver tudo pronto para disponibilizar os valores de configuração de rascunho para o aplicativo, publique o contêiner.

Configuração avançada

O Google Tag Manager para dispositivos móveis tem várias opções de configuração avançada que permitem selecionar valores com base em condições de tempo de execução usando regras, atualizar manualmente o contêiner e receber outras opções para abrir contêineres. As seções a seguir descrevem várias das configurações avançadas mais comuns.

Opções avançadas para abrir contêineres

O SDK do Google Tag Manager oferece vários métodos para abrir contêineres que podem oferecer mais controle sobre o processo de carregamento:

openContainerById:callback:

openContainerById:callback: é a API de nível mais baixo e mais flexível para abrir um contêiner. Ela retorna imediatamente com um contêiner padrão e também carrega de forma assíncrona um contêiner do disco ou da rede se nenhum contêiner salvo existir ou se o contêiner salvo não for novo (mais de 12 horas).

@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

Durante todo o processo de carregamento, openContainerById:callback: emite vários callbacks de ciclo de vida para que o código possa descobrir quando a solicitação de carregamento começa, se e por que ela falha ou é bem-sucedida e se o contêiner foi carregado do disco ou da rede.

A menos que seja aceitável que o aplicativo use os valores padrão, você precisará usar esses callbacks para saber quando um contêiner salvo ou de rede foi carregado. Não será possível carregar um contêiner salvo ou de rede se esta for a primeira vez que o app é executado e não houver conexão de rede.

openContainerById:callback: transmite os seguintes valores enum como argumentos para esses callbacks:

RefreshType

ValorDescrição
kTAGContainerCallbackRefreshTypeSaved A solicitação de atualização está carregando um contêiner salvo localmente.
kTAGContainerCallbackRefreshTypeNetwork A solicitação de atualização está carregando um contêiner pela rede.

RefreshFailure

ValorDescrição
kTAGContainerCallbackRefreshFailureNoSavedContainer Não há contêiner salvo disponível.
kTAGContainerCallbackRefreshFailureIoError Um erro de E/S impediu a atualização do contêiner.
kTAGContainerCallbackRefreshFailureNoNetwork Não há conexão de rede disponível.
kTAGContainerCallbackRefreshFailureNetworkError Ocorreu um erro de rede.
kTAGContainerCallbackRefreshFailureServerError Ocorreu um erro no servidor.
kTAGContainerCallbackRefreshFailureUnknownError Ocorreu um erro que não pode ser categorizado.

Métodos para abrir contêineres não padrão e novos

TAGContainerOpener envolve openContainerById:callback: e oferece dois métodos de conveniência para abrir contêineres: openContainerWithId:tagManager:openType:timeout:notifier: e openContainerWithId:tagManager:openType:timeout:.

Cada um desses métodos usa uma enumeração que solicita um contêiner não padrão ou novo.

kTAGOpenTypePreferNonDefault é recomendado para a maioria dos aplicativos e tenta retornar o primeiro contêiner não padrão disponível dentro de um determinado período de tempo limite, do disco ou da rede, mesmo que esse contêiner tenha mais de 12 horas. Se ele retornar um contêiner salvo desatualizado, também fará uma solicitação de rede assíncrona para um novo. Ao usar kTAGOpenTypePreferNonDefault, um contêiner padrão será retornado se nenhum outro contêiner estiver disponível ou se o período de tempo limite for excedido.

kTAGOpenTypePreferFresh tenta retornar um contêiner novo do disco ou da rede dentro do período de tempo limite especificado. Ele retorna um contêiner salvo se uma conexão de rede não estiver disponível e/ou o período de tempo limite for excedido.

Não é recomendável usar kTAGOpenTypePreferFresh em locais em que um tempo de solicitação mais longo possa afetar consideravelmente a experiência do usuário, como com flags de interface ou strings de exibição. Você também pode usar TAGContainer::refresh a qualquer momento para forçar uma solicitação de contêiner de rede.

Esses dois métodos de conveniência não são bloqueadores. openContainerWithId:tagManager:openType:timeout: retorna um TAGContainerFuture objeto, cujo get método retorna um TAGContainer assim que ele é carregado (mas isso vai bloquear até então). O método openContainerWithId:tagManager:openType:timeout:notifier: usa um único callback, chamado quando o contêiner está disponível. Ambos os métodos têm um período de tempo limite padrão de 2.0 segundos.

Avaliar macros no tempo de execução usando regras

Os contêineres podem avaliar valores no tempo de execução usando regras. As regras podem ser baseadas em critérios como idioma do dispositivo, plataforma ou qualquer outro valor de macro. Por exemplo, as regras podem ser usadas para selecionar uma string de exibição localizada com base no idioma do dispositivo no tempo de execução. Isso pode ser configurado usando a seguinte regra:

Uma regra é usada para selecionar strings de exibição com base no idioma do dispositivo no
            tempo de execução: idioma igual a es. Essa regra usa a macro de idioma predefinida e um código de idioma ISO 639-1 de dois caracteres.
Figura 1:como adicionar uma regra para ativar uma macro de coleta de valores apenas para dispositivos configurados para usar o idioma espanhol.

Em seguida, crie macros de coleta de valores para cada idioma e adicione essa regra a cada macro, inserindo o código de idioma apropriado. Quando esse contêiner for publicado, o aplicativo poderá mostrar strings de exibição localizadas, dependendo do idioma do dispositivo do usuário no tempo de execução.

Se o contêiner padrão precisar de regras, use um arquivo de contêiner binário como contêiner padrão.

Saiba mais sobre como configurar regras (Central de Ajuda).

Arquivos de contêiner padrão binários

Os contêineres padrão que precisam de regras precisam usar um arquivo de contêiner binário em vez de um arquivo de lista de propriedades ou JSON arquivo como contêiner padrão. Os contêineres binários oferecem suporte para determinar valores de macro no tempo de execução com regras do Google Tag Manager, enquanto os arquivos de lista de propriedades ou JSON não.

Os arquivos de contêiner binários podem ser baixados da interface da Web do Google Tag Manager e precisam ser adicionados ao pacote principal do aplicativo seguindo esta convenção de nomenclatura: GTM-XXXX, em que o nome do arquivo representa o ID do contêiner.

Nos casos em que um arquivo de lista de propriedades e/ou um arquivo JSON, bem como um arquivo de contêiner binário, estão presentes, o SDK vai usar o arquivo de contêiner binário como o contêiner padrão.

Usar macros de chamada de função

As macros de chamada de função são macros definidas como o valor de retorno de uma função especificada no aplicativo. As macros de chamada de função podem ser usadas para incorporar valores de tempo de execução com as regras do Google Tag Manager, como determinar no tempo de execução qual preço mostrar a um usuário com base no idioma e na moeda configurados de um dispositivo.

Para configurar uma macro de chamada de função:

  1. Defina a macro de chamada de função na interface da Web do Google Tag Manager. Os argumentos podem ser configurados opcionalmente como pares de chave-valor.
  2. Defina um gerenciador que implemente o TAGFunctionCallMacroHandler protocolo:
    // 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. Registre o gerenciador usando TAGContainer::registerFunctionCallMacroHandler:forMacro: e o nome da função especificada na interface do Google Tag Manager:
    //
    // 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

Usar tags de chamada de função

As tags de chamada de função permitem que funções pré-registradas sejam executadas sempre que um evento é enviado para a camada de dados e as regras de tag são avaliadas como true.

Para configurar uma tag de chamada de função:

  1. Defina a tag de chamada de função na interface da Web do Google Tag Manager. Os argumentos podem ser configurados opcionalmente como pares de chave-valor.
  2. Implemente o protocolo 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. Registre o gerenciador de tags de chamada de função usando o nome da tag configurado na interface da Web do Google Tag Manager:
    //
    // 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

Definir um período de atualização personalizado

O SDK do Google Tag Manager vai tentar recuperar um novo contêiner se a idade do contêiner atual exceder 12 horas. Para definir um período de atualização de contêiner personalizado, use NSTimer, como no exemplo a seguir:

- (void)refreshContainer:(NSTimer *)timer {
  [self.container refresh];
}

self.refreshTimer = [NSTimer scheduledTimerWithTimeInterval:<refresh_interval>
                                                     target:self
                                                   selector:@selector(refreshContainer:)
                                                   userInfo:nil
                                                    repeats:YES];

Depurar com o Logger

O SDK do Google Tag Manager imprime erros e avisos nos registros por padrão. Ativar o registro mais detalhado pode ser útil para depuração e é possível implementando seu próprio Logger, como neste exemplo:

// 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

Ou, você pode definir o LogLevel do Logger atual usando TagManager::logger::setLogLevel, como neste exemplo:

// Change the LogLevel to INFO to enable logging at INFO and higher levels.
self.tagManager = [TAGManager instance];
[self.tagManager.logger setLogLevel:kTAGLoggerLogLevelInfo];