Android v3 (레거시) - 개요

이 개발자 가이드에서는 모바일 애플리케이션에서 Google 태그 관리자를 구현하는 방법을 설명합니다.

소개

개발자는 Google 태그 관리자를 사용하면 애플리케이션 바이너리를 다시 빌드하고 앱 마켓에 다시 제출할 필요 없이 Google 태그 관리자 인터페이스를 사용하여 모바일 애플리케이션의 구성 값을 변경할 수 있습니다.

이는 다음과 같이 향후 변경해야 할 수 있는 애플리케이션의 구성 값 또는 플래그를 관리하는 데 유용합니다.

  • 다양한 UI 설정 및 표시 문자열
  • 애플리케이션에 게재되는 광고의 크기, 위치 또는 유형
  • 게임 설정

구성 값은 규칙을 사용하여 런타임에 평가할 수도 있으므로 다음과 같은 동적 구성을 사용할 수 있습니다.

  • 화면 크기를 사용하여 광고 배너 크기 결정
  • 언어 및 위치를 사용하여 UI 요소 구성

Google 태그 관리자를 사용하면 애플리케이션에서 추적 태그 및 픽셀을 동적으로 구현할 수도 있습니다. 개발자는 중요한 이벤트를 데이터 영역으로 푸시하고 실행할 추적 태그 또는 픽셀을 나중에 결정할 수 있습니다. 태그 관리자는 다음 태그를 지원합니다.

  • Google 모바일 앱 웹로그 분석
  • 커스텀 함수 호출 태그

시작하기 전에

이 시작 가이드를 사용하기 전에 다음이 필요합니다.

Google 태그 관리자를 처음 사용하는 경우 이 가이드를 계속하기 전에 컨테이너, 매크로, 규칙 (고객센터)에 대해 자세히 알아보는 것이 좋습니다.

시작하기

이 섹션에서는 개발자에게 일반적인 태그 관리자 워크플로를 안내합니다.

  1. 프로젝트에 Google 태그 관리자 SDK 추가
  2. 기본 컨테이너 값 설정
  3. 컨테이너 열기
  4. 컨테이너에서 구성 값 가져오기
  5. DataLayer로 이벤트 푸시
  6. 컨테이너 미리보기 및 게시

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 태그 관리자는 애플리케이션을 처음 실행할 때 기본 컨테이너를 사용합니다. 기본 컨테이너는 앱이 네트워크를 통해 새 컨테이너를 가져올 수 있을 때까지 사용됩니다.

기본 컨테이너 바이너리를 다운로드하고 애플리케이션에 추가하려면 다음 단계를 따르세요.

  1. Google 태그 관리자 웹 인터페이스에 로그인합니다.
  2. 다운로드할 컨테이너의 버전 을 선택합니다.
  3. 다운로드 버튼을 클릭하여 컨테이너 바이너리를 가져옵니다.
  4. 바이너리 파일을 다음 경로에 추가합니다. <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
}

이제 웹 인터페이스에서 이 규칙( equals "openScreen")을 만들어 각 화면 조회에 대해 실행할 태그(예: Google 애널리틱스 태그) 를 만들 수 있습니다. 화면 이름을 이러한 태그 중 하나에 전달하려면 데이터 영역에서 "screenName" 키를 참조하는 데이터 영역 매크로를 만듭니다. equals "openScreen" && equals "ConfirmationScreen" 규칙을 만들어 특정 화면 조회에 대해서만 실행할 태그(예: Google Ads 전환 픽셀)를 만들 수도 있습니다.

6. 컨테이너 미리보기 및 게시

매크로 값은 항상 현재 게시된 버전에 해당합니다. 컨테이너의 최신 버전을 게시하기 전에 임시 컨테이너를 미리 볼 수 있습니다.

컨테이너를 미리 보려면 Google 태그 관리자 웹 인터페이스에서 미리 볼 컨테이너 의 버전을 선택한 후 Preview를 선택하여 미리보기 URL을 생성합니다. 이후 단계에서 필요하므로 이 미리보기 URL을 저장합니다.

미리보기 URL은 태그 관리자 웹 인터페이스의 미리보기 창에서 사용할 수 있습니다.
그림 1: 태그 관리자 웹 인터페이스에서 미리보기 URL 가져오기

그런 다음 애플리케이션의 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 분류할 수 없는 오류가 발생했습니다.

기본이 아닌 새 컨테이너를 여는 메서드

ContainerOpenerTagManager.openContainer() 를 래핑하고 컨테이너를 여는 두 가지 편의 메서드( ContainerOpener.openContainer(..., Notifier notifier)ContainerOpener.openContainer(..., Long timeoutInMillis))를 제공합니다.

이러한 각 메서드는 기본이 아닌 컨테이너 또는 새 컨테이너를 요청하는 열거형을 사용합니다.

OpenType.PREFER_NON_DEFAULT 는 대부분의 애플리케이션에 권장되며 컨테이너가 12시간보다 오래된 경우에도 지정된 제한 시간 내에 디스크 또는 네트워크에서 사용 가능한 첫 번째 기본이 아닌 컨테이너를 반환하려고 시도합니다. 오래된 저장된 컨테이너를 반환하는 경우 새 컨테이너에 대한 비동기식 네트워크 요청도 실행합니다. OpenType.PREFER_NON_DEFAULT를 사용하는 경우 다른 컨테이너를 사용할 수 없거나 제한 시간이 초과되면 기본 컨테이너가 반환됩니다.

OpenType.PREFER_FRESH 는 지정된 제한 시간 내에 디스크 또는 네트워크에서 새 컨테이너를 반환하려고 시도합니다. 네트워크 연결을 사용할 수 없거나 제한 시간이 초과되면 저장된 컨테이너를 반환합니다.

UI 플래그 또는 표시 문자열과 같이 요청 시간이 길어지면 사용자 환경에 눈에 띄게 영향을 미칠 수 있는 위치에서는 OpenType.PREFER_FRESH를 사용하지 않는 것이 좋습니다. 언제든지 Container.refresh() 를 사용하여 네트워크 컨테이너 요청을 강제할 수도 있습니다.

이러한 두 가지 편의 메서드는 모두 차단되지 않습니다. ContainerOpener.openContainer(..., Long timeoutInMillis)ContainerOpener.ContainerFuture 객체를 반환하며, 이 객체의 get 메서드는 로드되는 즉시 Container를 반환합니다 (하지만 그때까지 차단됨). ContainerOpener.openContainer(..., Notifier notifier) 메서드는 컨테이너를 사용할 수 있을 때 호출되는 단일 콜백을 사용하며, 이 콜백은 기본 스레드를 차단하지 않는 데 사용할 수 있습니다. 두 메서드 모두 기본 제한 시간은 2000밀리초입니다.

규칙을 사용하여 런타임에 매크로 평가

컨테이너는 규칙을 사용하여 런타임에 값을 평가할 수 있습니다. 규칙은 기기 언어, 플랫폼 또는 기타 매크로 값과 같은 기준을 기반으로 할 수 있습니다. 예를 들어 규칙을 사용하여 런타임에 기기의 언어를 기반으로 현지화된 표시 문자열을 선택할 수 있습니다. 다음 규칙을 사용하여 이를 구성할 수 있습니다.

규칙은 런타임에 기기 언어에 따라 표시 문자열을 선택하는 데 사용됩니다(언어는 es와 같음). 이 규칙은 사전 정의된 언어 매크로와 2자리 ISO 639-1 언어 코드를 사용합니다.
그림 1:스페인어를 사용하도록 구성된 기기에 대해서만 값 수집 매크로를 사용 설정하는 규칙 추가

그런 다음 각 언어에 대한 값 수집 매크로를 만들고 각 매크로에 이 규칙을 추가하여 적절한 언어 코드를 삽입할 수 있습니다. 이 컨테이너가 게시되면 애플리케이션은 런타임에 사용자의 기기 언어에 따라 현지화된 표시 문자열을 표시할 수 있습니다.

기본 컨테이너에 규칙이 필요한 경우 바이너리 컨테이너 파일을 기본 컨테이너로 사용해야 합니다.

규칙 구성 (고객센터)에 대해 자세히 알아보세요.

바이너리 기본 컨테이너 파일

규칙이 필요한 기본 컨테이너는 기본 컨테이너로 JSON 파일 대신 바이너리 컨테이너 파일을 사용해야 합니다. 바이너리 컨테이너는 Google 태그 관리자 규칙을 사용하여 런타임에 매크로 값을 결정하는 기능을 지원하지만 JSON 파일은 지원하지 않습니다.

바이너리 컨테이너 파일은 Google 태그 관리자 웹 인터페이스에서 다운로드할 수 있으며 프로젝트의 /assets/tagmanager/ 폴더에 추가하고 다음 패턴을 따라야 합니다. /assets/tagmanager/GTM-XXXX 여기서 파일 이름은 컨테이너 ID를 나타냅니다.

JSON 파일과 바이너리 컨테이너 파일이 모두 있는 경우 SDK는 바이너리 컨테이너 파일을 기본 컨테이너로 사용합니다.

함수 호출 매크로 사용

함수 호출 매크로는 애플리케이션에서 지정된 함수의 반환 값으로 설정되는 매크로입니다. 함수 호출 매크로를 사용하면 런타임 값을 Google 태그 관리자 규칙에 통합할 수 있습니다. 예를 들어 런타임에 기기의 구성된 언어 및 통화를 기반으로 사용자에게 표시할 가격을 결정할 수 있습니다.

함수 호출 매크로를 구성하려면 다음 단계를 따르세요.

  1. Google 태그 관리자 웹 인터페이스에서 함수 호출 매크로를 정의합니다. 인수는 선택적으로 키-값 쌍으로 구성할 수 있습니다.
  2. `FunctionCallMacroHandler` 및 Google 태그 관리자 웹 인터페이스에서 구성한 함수 이름을 사용하여 애플리케이션에서 Container.registerFunctionCallMacroHandler()를 등록하고 해당 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로 평가될 때마다 사전 등록된 함수를 실행할 수 있습니다.

함수 호출 태그를 구성하려면 다음 단계를 따르세요.

  1. Google 태그 관리자 웹 인터페이스에서 함수 호출 태그를 정의합니다. 인수는 선택적으로 키-값 쌍으로 구성할 수 있습니다.
  2. `Container.registerFunctionCallTagHandler()`를 사용하여 애플리케이션에서 함수 호출 태그 핸들러를 등록합니다. 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는 기본적으로 로그에 오류와 경고를 출력합니다. 더 상세한 로깅을 사용 설정하면 디버깅에 도움이 될 수 있으며 자체 LoggerTagManager.setLogger로 구현하여 사용할 수 있습니다. 이 예와 같습니다.

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) 을 사용하여 기존 로거의 LogLevel을 설정할 수 있습니다.

// Change the LogLevel to INFO to enable logging at INFO and higher levels.
TagManager tagManager = TagManager.getInstance(this);
tagManager.getLogger().setLogLevel(LogLevel.INFO);