本開發人員指南說明如何在行動應用程式中導入 Google 代碼管理工具。
簡介
有了 Google 代碼管理工具,開發人員就能使用 Google 代碼管理工具介面更改行動應用程式的設定值,而不用重新建構應用程式二進位檔並重新提交到應用程式市集。
這適合用來管理應用程式中可能需要變更的任何設定值或標記,包括:
- 各種 UI 設定和顯示字串
- 在應用程式中放送的廣告大小、位置或類型
- 遊戲設定
此外,也可使用規則在執行階段評估設定值,例如啟用下列動態設定:
- 以螢幕大小決定廣告橫幅大小
- 使用語言和位置設定 UI 元素
此外,Google 代碼管理工具還能夠在應用程式中動態導入追蹤代碼和像素。開發人員可以將重要事件推送到資料層,稍後再決定要觸發哪些追蹤代碼或像素。TagManager 目前支援下列代碼:
- Google 行動應用程式分析
- 自訂函式呼叫代碼
事前準備
使用本入門指南前,您必須備妥以下項目:
- Google 代碼管理工具帳戶
- 新的代碼管理工具 容器和值收集巨集
- 可導入 Google 代碼管理工具的 Android 行動應用程式
- Google Analytics (分析) Services SDK,其中包含代碼管理工具程式庫。
如果您是 Google 代碼管理工具新手,建議您先 進一步瞭解容器、巨集和規則 (說明中心),再繼續本指南。
入門課程
本節將引導開發人員完成一般的代碼管理工具工作流程:
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 代碼管理工具會在首次執行應用程式時使用預設容器。在應用程式能夠透過網路擷取新的容器之前,系統會使用預設容器。
如要下載預設容器二進位檔並新增至應用程式,請按照下列步驟操作:
- 登入 Google 代碼管理工具網頁介面。
- 選取要下載的容器「版本」。
- 點選「下載」按鈕即可擷取容器二進位檔。
- 請將二進位檔案新增至下列路徑:
<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. 將值推送到資料層
資料層是一種地圖,可啟用應用程式的執行階段資訊 (例如觸控事件或畫面瀏覽),以便用於容器中的代碼管理工具巨集和代碼。
舉例來說,您可以將畫面瀏覽的相關資訊推送至資料層地圖,在「代碼管理工具」網頁介面中設定代碼來觸發轉換像素,並根據這些畫面瀏覽追蹤呼叫,完全不需要以硬式編碼的方式將代碼導入應用程式。
系統會使用 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 Ads 轉換像素),方法是建立規則,其中 等於 "openScreen" && 等於 "ConfirmationScreen"。
6. 預覽及發布容器
巨集值一律會對應至目前發布的版本。在發布最新版本的容器之前,您可以預覽容器草稿容器。
如要預覽容器,請在 Google 代碼管理工具網頁介面中產生預覽網址,方法是選取要預覽的容器版本,然後選取 Preview
。請耐心等候這個預覽網址,因為後續步驟會用到。
接著,將下列活動新增至應用程式的 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
|
發生無法分類的錯誤, |
開啟非預設容器和新容器的方法
ContainerOpener
會納入 TagManager.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
毫秒。
使用規則在執行階段評估巨集
容器可在執行階段使用規則評估值。可根據裝置語言、平台或任何其他巨集值等條件建立規則。例如,規則可用於根據執行階段的裝置語言,選取本地化的顯示字串。您可使用以下規則進行設定:
接著,您可以建立每種語言的值收集巨集,並為每個巨集加入這項規則,並插入正確的語言代碼。此容器發布後,應用程式將可根據使用者裝置在執行階段的語言,顯示本地化的顯示字串。
請注意,如果您的預設容器需要規則,您必須使用二進位檔容器檔案做為預設容器。
二進位檔預設容器檔案
需要規則的預設容器應使用二進位容器檔案,而不是 JSON 檔案做為預設容器。二進位檔容器可讓您使用 Google 代碼管理工具規則,判斷執行階段的巨集值,JSON 檔案則不支援這項功能。
二進位容器檔案可從 Google 代碼管理工具網頁介面下載,且應加入專案的 /assets/tagmanager/
資料夾並採用以下模式:/assets/tagmanager/GTM-XXXX
,其中檔案名稱代表容器 ID。
如果存在 JSON 檔案和二進位容器檔案,SDK 會使用二進位容器檔案做為預設容器。
使用函式呼叫巨集
函式呼叫巨集是設為應用程式中指定函式傳回值的巨集。函式呼叫巨集可用於將執行階段值與 Google 代碼管理工具規則整合,例如根據裝置設定的語言和貨幣,決定在執行階段向使用者顯示的價格。
如何設定函式呼叫巨集:
- 在 Google 代碼管理工具網頁介面中定義函式呼叫巨集。 可選擇將引數設為鍵/值組合。
- 使用
Container.registerFunctionCallMacroHandler()
和您在 Google 代碼管理工具網頁介面中設定的函式名稱註冊FunctionCallMacroHandler
,並覆寫其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
時,函式呼叫代碼就會執行預先註冊的函式。
如何設定函式呼叫代碼:
- 在 Google 代碼管理工具網頁介面中定義函式呼叫代碼。 可選擇將引數設為鍵/值組合。
- 使用
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 預設會在記錄中顯示錯誤和警告。
啟用更詳細的記錄有助於偵錯,您可以使用 TagManager.setLogger
實作自己的 Logger
,如以下範例所示:
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)
來設定現有 Logger 的 LogLevel,如以下範例所示:
// Change the LogLevel to INFO to enable logging at INFO and higher levels. TagManager tagManager = TagManager.getInstance(this); tagManager.getLogger().setLogLevel(LogLevel.INFO);