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

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

Введение

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

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

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

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

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

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

  • Аналитика мобильных приложений Google
  • Тег вызова пользовательской функции

Прежде чем вы начнете

Прежде чем использовать это руководство по началу работы, вам понадобится следующее:

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

Начиная

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

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

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

Прежде чем использовать SDK Диспетчера тегов Google, вам необходимо разархивировать пакет 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/

Имя файла по умолчанию должно быть идентификатором контейнера (например 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 – это карта, которая позволяет получать доступ к макросам и тегам Диспетчера тегов в контейнере информации о вашем приложении во время выполнения, например о событиях касания или просмотрах экрана.

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

События передаются в 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), которые будут активироваться для каждого просмотра экрана, создав следующее правило: равно "openScreen". Чтобы передать экранное имя в один из этих тегов, создайте макрос уровня данных, который ссылается на ключ «screenName» на уровне данных. Вы также можете создать тег (например, пиксель конверсии Google Рекламы), который будет активироваться только для определенных просмотров экрана, создав правило, в котором равно "openScreen" && равно "ConfirmationScreen".

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

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

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

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

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

Менеджер тегов.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 в качестве аргументов этим обратным вызовам:

Тип обновления

Ценить Описание
Container.Callback.SAVED Запрос на обновление загружает локально сохраненный контейнер.
Container.Callback.NETWORK Запрос на обновление загружает контейнер по сети.

ОбновитьОшибка

Ценить Описание
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 миллисекунд.

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

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

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

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

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

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

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

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

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

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

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

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

Чтобы настроить макрос вызова функции:

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

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

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

SDK Диспетчера тегов Google по умолчанию печатает ошибки и предупреждения в журналах. Включение более подробного ведения журнала может быть полезно для отладки и возможно путем реализации собственного 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.

});

Или вы можете установить LogLevel существующего регистратора, используя 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);