Android v3 (устаревшая версия) – Обзор

В этом руководстве для разработчиков описывается, как интегрировать Google Tag Manager в мобильное приложение.

Введение

Google Tag Manager позволяет разработчикам изменять параметры конфигурации в своих мобильных приложениях с помощью интерфейса Google Tag Manager без необходимости пересобирать и повторно отправлять бинарные файлы приложений в магазины приложений.

Это полезно для управления любыми значениями конфигурации или флагами в вашем приложении, которые вам может потребоваться изменить в будущем, включая:

  • Различные настройки пользовательского интерфейса и строки отображения.
  • Размеры, расположение или типы рекламных объявлений, показываемых в вашем приложении.
  • Настройки игры

Значения конфигурации также могут оцениваться во время выполнения с помощью правил, что позволяет создавать динамические конфигурации, такие как:

  • Размер экрана используется для определения размера рекламного баннера.
  • Использование языка и местоположения для настройки элементов пользовательского интерфейса.

Google TagManager также позволяет динамически внедрять теги и пиксели отслеживания в приложения. Разработчики могут передавать важные события в слой данных и позже решать, какие теги или пиксели отслеживания должны быть активированы. TagManager поддерживает следующие теги:

  • Google Mobile App Analytics
  • Метка вызова пользовательской функции

Прежде чем начать

Перед использованием данного руководства вам потребуется следующее:

Если вы новичок в Google Tag Manager, мы рекомендуем вам ознакомиться с информацией о контейнерах, макросах и правилах (Справочный центр), прежде чем продолжить изучение этого руководства.

Начиная

В этом разделе разработчики ознакомятся с типичным рабочим процессом менеджера тегов:

  1. Добавьте SDK Google Tag Manager в свой проект.
  2. Установить значения контейнера по умолчанию
  3. Откройте контейнер
  4. Получение значений конфигурации из контейнера
  5. Передача событий в DataLayer
  6. Предварительный просмотр и публикация контейнера

1. Добавление SDK Google Tag Manager в ваш проект

Перед использованием SDK Google Tag Manager вам необходимо распаковать пакет SDK, добавить библиотеку в путь сборки вашего проекта и добавить разрешения в файл AndroidManifest.xml .

Сначала добавьте библиотеку Google Tag Manager в папку /libs вашего проекта.

Далее обновите файл AndroidManifest.xml, указав следующие разрешения:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

2. Добавление файла контейнера по умолчанию в ваш проект

Google Tag Manager использует контейнер по умолчанию при первом запуске вашего приложения. Этот контейнер будет использоваться до тех пор, пока приложение не сможет получить новый контейнер по сети.

Чтобы загрузить и добавить в ваше приложение исполняемый файл контейнера по умолчанию, выполните следующие действия:

  1. Войдите в веб-интерфейс Google Tag Manager.
  2. Выберите версию контейнера, которую хотите загрузить.
  3. Нажмите кнопку «Загрузить» , чтобы получить исполняемый файл контейнера.
  4. Добавьте исполняемый файл по следующему пути: < project-root >/assets/tagmanager/

По умолчанию имя файла должно совпадать с идентификатором контейнера (например, GTM-1234 ). После загрузки бинарного файла обязательно удалите суффикс версии из имени файла, чтобы обеспечить соблюдение правильного соглашения об именовании.

Хотя рекомендуется использовать бинарный файл, если ваш контейнер не содержит правил или тегов, вы можете использовать вместо него JSON-файл. Файл должен находиться в новой папке /assets/tagmanager вашего Android-проекта и должен соответствовать следующему соглашению об именовании: <Container_ID>.json . Например, если идентификатор вашего контейнера — 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) ​​используется для запроса сохраненного контейнера из локального хранилища. Обработка присвоения значения mContainer в коллбэке containerAvailable гарантирует, что основной поток не будет заблокирован. Если сохраненный контейнер старше 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 — это карта, которая позволяет предоставлять макросам и тегам Tag Manager в контейнере информацию о вашем приложении в режиме реального времени, например, о событиях касания или просмотрах экрана.

Например, передавая информацию о просмотрах экранов в карту DataLayer, вы можете настроить теги в веб-интерфейсе Tag Manager для запуска пикселей конверсии и вызовов отслеживания в ответ на эти просмотры экранов, без необходимости жестко прописывать их в коде вашего приложения.

События передаются в DataLayer с помощью push() и вспомогательного метода DataLayer.mapOf() :

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

В веб-интерфейсе теперь можно создавать теги (подобные тегам Google Analytics), которые срабатывают для каждого просмотра экрана, создав следующее правило: equals "openScreen". Чтобы передать имя экрана одному из этих тегов, создайте макрос слоя данных, который ссылается на ключ "screenName" в слое данных. Вы также можете создать тег (подобный пикселю конверсии Google Ads), который срабатывает только для определенных просмотров экрана, создав правило, где equals "openScreen" && equals "ConfirmationScreen".

6. Предварительный просмотр и публикация контейнера

Значения макросов всегда будут соответствовать текущей опубликованной версии. Перед публикацией последней версии контейнера вы можете предварительно просмотреть черновой вариант контейнера.

Чтобы просмотреть содержимое контейнера, сгенерируйте URL-адрес предварительного просмотра в веб-интерфейсе Google Tag Manager, выбрав версию контейнера, которую вы хотите просмотреть, а затем нажав Preview . Сохраните этот URL-адрес предварительного просмотра, так как он понадобится вам на последующих шагах.

Предварительные URL-адреса доступны в окне предварительного просмотра веб-интерфейса Tag Manager.
Рисунок 1: Получение URL-адреса предварительного просмотра из веб-интерфейса Tag Manager.

Далее добавьте следующую Activity в файл 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 Tag Manager для мобильных устройств предлагает ряд расширенных параметров конфигурации, позволяющих выбирать значения на основе условий выполнения с помощью правил, вручную обновлять контейнер и получать дополнительные параметры для открытия контейнеров. В следующих разделах описаны несколько наиболее распространенных расширенных настроек.

Расширенные параметры открытия контейнеров

SDK Google Tag Manager предоставляет несколько методов открытия контейнеров, которые позволяют лучше контролировать процесс загрузки:

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 Ошибка ввода-вывода помешала обновлению контейнера.
Container.Callback.NO_NETWORK Отсутствует сетевое соединение.
Container.Callback.NETWORK_ERROR Произошла сетевая ошибка.
Container.Callback.SERVER_ERROR Произошла ошибка на сервере.
Container.Callback.UNKNOWN_ERROR Произошла ошибка, которую невозможно классифицировать.

Методы открытия контейнеров, отличных от стандартных, и новых контейнеров.

ContainerOpener является оберткой TagManager.openContainer() и предоставляет два удобных метода для открытия контейнеров: ContainerOpener.openContainer(..., Notifier notifier) ​​и ContainerOpener.openContainer(..., Long timeoutInMillis) .

Каждый из этих методов принимает перечисление, запрашивающее либо нестандартный, либо новый контейнер.

OpenType.PREFER_NON_DEFAULT рекомендуется для большинства приложений и пытается вернуть первый доступный контейнер, отличный от контейнера по умолчанию, в течение заданного периода ожидания, либо с диска, либо из сети, даже если этому контейнеру более 12 часов. Если он возвращает устаревший сохраненный контейнер, он также отправит асинхронный сетевой запрос на получение нового. При использовании OpenType.PREFER_NON_DEFAULT будет возвращен контейнер по умолчанию, если других контейнеров нет или если превышен период ожидания.

OpenType.PREFER_FRESH пытается вернуть новый контейнер либо с диска, либо из сети в течение заданного периода ожидания. Она возвращает сохраненный контейнер, если сетевое соединение недоступно и/или превышен период ожидания.

Не рекомендуется использовать OpenType.PREFER_FRESH в местах, где увеличение времени запроса может заметно повлиять на удобство использования, например, при работе с флагами пользовательского интерфейса или строками отображения. Вы также можете в любое время использовать Container.refresh() для принудительного запроса сетевого контейнера.

Оба этих вспомогательных метода являются неблокирующими. ContainerOpener.openContainer(..., Long timeoutInMillis) возвращает объект ContainerOpener.ContainerFuture , метод get которого возвращает Container сразу после его загрузки (но до этого момента выполнение будет блокироваться). Метод ContainerOpener.openContainer(..., Notifier notifier) ​​принимает одну функцию обратного вызова, вызываемую, когда контейнер становится доступным, и может использоваться для предотвращения блокировки основного потока. Оба метода имеют период ожидания по умолчанию в 2000 миллисекунд.

Оценка макросов во время выполнения с использованием правил

Контейнеры могут оценивать значения во время выполнения с помощью правил. Правила могут основываться на таких критериях, как язык устройства, платформа или любое другое макрозначение. Например, правила могут использоваться для выбора локализованной строки отображения на основе языка устройства во время выполнения. Это можно настроить с помощью следующего правила:

Для выбора отображаемых строк в зависимости от языка устройства во время выполнения используется правило: language equals es. Это правило использует предопределенный макрос языка и двухсимвольный код языка ISO 639-1.
Рисунок 1: Добавление правила для включения макроса сбора значений только для устройств, настроенных на использование испанского языка.

Затем вы можете создать макросы сбора значений для каждого языка и добавить это правило в каждый макрос, вставив соответствующий код языка. После публикации этого контейнера ваше приложение сможет отображать локализованные строки в зависимости от языка устройства пользователя во время выполнения.

Обратите внимание, что если вашему контейнеру по умолчанию требуются правила, вы должны использовать бинарный файл контейнера в качестве контейнера по умолчанию.

Узнайте больше о настройке правил (Справочный центр).

Двоичные файлы контейнера по умолчанию

Для контейнеров по умолчанию, требующих правил, следует использовать бинарный файл контейнера вместо файла JSON . Бинарные контейнеры поддерживают определение значений макросов во время выполнения с помощью правил Google Tag Manager, в отличие от файлов JSON.

Бинарные файлы контейнеров можно загрузить из веб-интерфейса Google Tag Manager и добавить в папку /assets/tagmanager/ вашего проекта, следуя следующему шаблону: /assets/tagmanager/GTM-XXXX , где имя файла представляет собой идентификатор вашего контейнера.

В случаях, когда присутствует как JSON-файл, так и бинарный файл-контейнер, SDK будет использовать бинарный файл-контейнер в качестве контейнера по умолчанию.

Использование макросов вызова функций

Макросы вызова функций — это макросы, которые задаются возвращаемым значением указанной функции в вашем приложении. Макросы вызова функций можно использовать для включения значений, отображаемых во время выполнения, в правила Google Tag Manager, например, для определения во время выполнения, какую цену отображать пользователю в зависимости от настроенного языка и валюты устройства.

Для настройки макроса вызова функции:

  1. Определите макрос вызова функции в веб-интерфейсе Google Tag Manager. Аргументы могут быть дополнительно настроены в виде пар ключ-значение.
  2. Зарегистрируйте FunctionCallMacroHandler в своем приложении, используя Container.registerFunctionCallMacroHandler() и имя функции, которое вы настроили в веб-интерфейсе Google Tag Manager, переопределив ее метод 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 Tag Manager. Аргументы могут быть дополнительно настроены в виде пар ключ-значение.
  2. Зарегистрируйте обработчик вызовов функций в вашем приложении, используя 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.
        }
      }
    });

Настройка пользовательского периода обновления

SDK Google Tag Manager попытается получить новый контейнер, если возраст текущего контейнера превышает 12 часов. Чтобы установить пользовательский период обновления контейнера, используйте Timer , как показано в следующем примере:

timer.scheduleTask(new TimerTask() {
  @Override
  public void run() {
    mContainer.refresh();
  }
}, delay, <new_period_in milliseconds>);

Отладка с помощью Logger

В стандартном SDK Google Tag Manager ошибки и предупреждения по умолчанию записываются в журналы. Включение более подробного логирования может быть полезно для отладки и возможно путем реализации собственного Logger с помощью TagManager.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) , как в этом примере:

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