구글 태그매니저 사용하기

구글 태그매니저란?

GTM(Google Tag Manager)은 GA(Google Analytics)를 비롯한 여러 모니터링/마케팅 플랫폼들과 연동할 수 있는 중간자 적인 역할을 하는 플랫폼이다. 바로가기: https://developers.google.com/tag-manager/

앱/웹을 재배포 하지 않고도 태그매니저내부의 설정값 변경 만으로 이미 배포되어있는 앱/웹의 설정 또는 조건식 들을 동적으로 변경할 수 있도록 기능을 지원하기때문에 사용자 액션에 따라서 좀더 유연한 마케팅/로깅을 할 수 있다.(ex: 200달러 이상 구매 고객일 경우에만 리마케팅을 수행 등)

용어 정리

GTM의 가장 작은 구성단위부터 점점 큰 순서대로 설명하면 다음과 같다.

1. 변수(Variable)

  • 태그매니저 구버전에서는 매크로(Macros)였음
  • 앱의 버전, 앱의 이름, 화면 해상도, 언어코드 등이 미리 정의되어있음.
  • 모바일 SDK를 이용해서 앱에 정의되어있는 함수를 호출 해서 받아온 값 또한 변수로 사용할 수 있다.
  • 사용자 정의 변수 영역에 상수를 지정할 경우 해당 상수값을 모바일 SDK를 통해 앱에서 접근하는것 또한 가능하다.
  • 데이터 영역(DataLayer) 변수의 경우 앱/웹으로 부터 push 받은 값을 변수로 사용가능하다.

2. 트리거(Trigger)

  • 태그매니저 구버전에서는 규칙(Rule)이었음
  • 특정 화면에 진입한다던지, 특정 url에 액세스 한다던지, 버전이 1.x인 앱사용자가 앱을 기동했다던지 등, 여러 변수(Variable)에 대한 조건식들을 조합하여 특정 이벤트를 정의해놓은 것을 말한다. 사용자가 특정 상황에서 발생시키는 이벤트 라고 생각하면 쉽게 이해 할수 있다.

3. 태그(Tag)

  • 트리거가 발생했을때 어떤 액션을 취할 것인지에 대해 정의한다.
  • 트리거가 발생시 Google Analytics나 AdWords쪽으로 로그를 전송해서 이벤트 기록, 전환율 업데이트, 리마케팅 등의 동작을 취할 수 있으며, 모바일 SDK를 이용해서 앱에 정의된 사용자 정의 함수를 호출하면 App의 동작을 런타임중에 동적으로 변경하는것도 가능하다.

4. 컨테이너(Container)

  • 위에 명시한 변수/트리거/태그들을 포함하고있는 상위 개념으로 일반적인경우 웹사이트/앱 마다 하나의 컨테이너를 사용하면 된다.
  • 웹용/모바일용으로 컨테이너 타입이 따로 나누어져있다.
  • 한 컨테이너 내에서도 버전관리가 가능하기때문에, 앱 또는 웹을 버전업 하면서 같이 컨테이너 또한 버전업해서 편리한 사용이 가능하다.

적용 방법

앱/웹에 기존에 GA가 적용이 되어있더라도 동시에 적용하는것이 가능하다. 자세한 가이드는 다음 페이지를 참고하면된다.

WEB

모바일 앱 SDK

기본 동작 방식

  • 앱/웹이 처음 로딩될때 GTM에 정의된 컨테이너를 내려받게되고, 해당 컨테이너안에 정의된 변수, 트리거, 태그 등이 모두 로드된다. 따라서 컨테이너를 내려 받은 이후에는 다음번 컨테이너 refresh까지는 GTM쪽과 통신할 필요가 없다. (GTM은 이 컨테이너를 생성하기 위한 관리 인터페이스 정도로 생각하면 된다.)

  • 모바일SDK에서 GTM이 컨테이너의 새 버전으로 refresh 주기는 변경가능하다 (디폴트값은 12시간)

  • 원하는시점에 앱에서 GTM 버전을 수동으로 refresh도 가능하다.

동작 응용: GA와 연동

GA을 사용할경우 기존에 특정 화면(viewController or web page) 진입시 GA로 로그를 send하는로직이 들어간다.
– 기존 방법: GA로 바로 로그를 send
– 태그매니저 이용 방법: DataLayer로 이벤트 종류 및 추가 키/밸류정보를 push하면, 해당 이벤트가 설정된 트리거에의해 GA로 로그를 보낸다, 참고: https://developers.google.com/tag-manager/ios/v3/ua#events

코드 예제 1 – 태그매니저에서 설정한 값을 모바일 앱에서 읽어들이기

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

코드 예제 2 – 모바일 앱에서 불러온 값을 태그매니저의 변수로 이용하기

// MyAppDelegate.m
@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


// 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 – 태그매니저에서 앱의 특정 함수를 실행하기

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

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

코드 예제 4 – 데이터 매니저를 사용하여 특정 이벤트 발생을 태그매니저로 Push

웹:

  • 미리 정의된 pageCategory, visitorType 값은 현재 페이지내에서 dataLayer.push를 할경우 디폴트로 포함된다.
  • push 시에 값을 overwrite 하는것도 가능.
  • dataLayer는 queue로 되어있으며, push 는 async 오퍼레이션.

    <body>
      <script>
        dataLayer = [{
          'pageCategory': 'signup',
          'visitorType': 'high-value'
        }];
      </script>
      <!-- Google Tag Manager -->
      ...
      <!-- End Google Tag Manager -->
    
    
    <a href="#" name="button1" onclick="dataLayer.push({'event': 'button1-click'});" >Button 1</a>

iOS:

  • dataLayer로 push를 할 경우에는 컨테이너가 먼저 초기화되어 open 상태가 되어있어야 값이 전달된다.

    @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