如何建立伺服器代碼

您也可以參閱「伺服器端代碼簡介」一文,概略瞭解代碼管理工具中的伺服器端代碼。您已經瞭解用戶端的用途和用途:用戶端會從使用者裝置接收事件資料,並調整資料以供容器的其餘部分使用。本文說明如何在伺服器端代碼中處理這項資料。

在伺服器容器中,標記會從用戶端接收傳入的事件資料、轉換這些資料,然後再傳回資料進行收集和分析。標記可將資料傳送至任何位置。只要目的地接受 HTTP 要求,也可接受來自伺服器容器的資料。

伺服器容器有三個內建標記,無需自訂設定即可使用:

  • Google Analytics (分析) 4
  • Google Analytics (分析):通用 Analytics (分析)
  • HTTP 要求

如果您想在 Google Analytics (分析) 以外的地方傳送資料,或需要的功能比 HTTP 要求標記提供的更多功能,就需要使用其他標記。您可以在社群範本庫中找到其他標記,也可以自行撰寫標記。本教學課程說明為伺服器容器撰寫標記的基本概念。

目標

  • 瞭解有哪些 API 可用來讀取事件資料、傳送 HTTP 要求,以及在瀏覽器中設定 Cookie。
  • 瞭解設計代碼設定選項的最佳做法。
  • 瞭解使用者指定資料和自動收集的資料之間的差異,以及兩者之間的區別的重要性。
  • 瞭解代碼在伺服器容器中扮演的角色。瞭解標記應
  • 瞭解將標記範本提交至社群範本庫的時機。

必備條件

Baz Analytics 代碼

在這個教學課程中,您會建立代碼,將評估資料傳送至名為 Baz Analytics 的服務。

Baz Analytics 是簡易的假設分析服務,可透過對 https://example.com/baz_analytics 的 HTTP GET 要求擷取資料。其中包含下列參數:

參數 範例 說明
ID BA-1234 Baz Analytics (分析) 帳戶的 ID
en click 這是指活動名稱。
l https://www.google.com/search?q=sgtm 發生事件的網頁網址。
u 2384294892 執行動作的使用者 ID。用於將多個動作連結至單一使用者。

代碼設定

首先,請建立代碼範本。前往容器的「Templates」部分,然後按一下「Tag Templates」區段中的「New」。為標記輸入名稱和說明。

接著,前往範本編輯器的「欄位」部分,為代碼新增不同的設定選項。另一個顯而易見的問題是:你需要哪些選項?您可以選擇透過以下三種方式建立代碼:

  1. 「Total Configuration」:新增每個參數的設定欄位。要求使用者明確設定所有項目。
  2. 不設定:完全無法設定代碼。所有資料都是直接從事件取得。
  3. 部分設定:包含部分參數的欄位,其他參數則沒有。

每個參數都擁有欄位非常靈活,可讓使用者完全掌控其代碼設定。但在實務上,這通常會導致許多重複的工作。特別是,內含網頁網址的 Baz Analytics l 參數這類明確通用。每次設定標記時,請務必輸入相同的不變資料,因為是電腦最理想的情況。

也許答案是,某個代碼只擷取事件資料。對使用者而言,這是最簡單的設定標記,因為使用者完全不需要做到。另一方面,這也是最限制也最脆弱的選項。就算使用者需要,他們也無法變更代碼的行為。 舉例來說,他們可能會在自家網站和 Google Analytics (分析) 中呼叫事件 purchase,但 Baz Analytics 將事件命名為 buy。或者,也許假設代碼所得出的接收事件資料結構實際上與事實不符。不論是哪一種情況,使用者都會卡住。

如同許多事情,答案在這兩個極限之間。有些資料一律可以從事件中取得。其他資料則應由使用者設定。該如何決定何者?為了回答這個問題,我們需要進一步瞭解傳入容器的資料。

資料來源

Google Analytics (分析) 4 代碼傳入伺服器容器的資料大致可分為兩類:使用者指定資料和自動收集的資料。

使用者指定資料是指使用者放入 gtag.js event 指令中的所有資料,舉例來說,指令如下:

gtag('event', 'search', {
  search_term: 'beets',
});

這會在伺服器容器中產生下列參數:

{
  event_name: 'search',
  search_term: 'beets',
}

這很簡單,但從標記的角度來看,很難使用。由於這項資料是由使用者輸入,因此可以是任何內容。如上所述,使用者只會透過建議事件和參數傳送,但不需要這麼做。除了 event_name 參數的位置 (而非值!) 以外,使用者無法保證使用者資料的形式或結構。

幸好,容器無法取得使用者輸入的資料。此外,Google Analytics (分析) 4 代碼也會在瀏覽器中自動收集一系列資料。其中包括:

  • ip_override
  • language
  • page_location
  • page_referrer
  • page_title
  • screen_resolution
  • user_agent

此外,如果伺服器要求是來自網路瀏覽器,系統也可能會透過 getCookieValue API 取得瀏覽器 Cookie 資料。

這兩者共同構成了上述自動收集的資料。通常這是包含通用且語意明確的資料。如果要求來自瀏覽器的 GA4 代碼,系統一律會提供這項資料,且格式會一律相同。如要進一步瞭解這些參數,請參閱事件參考資料

這個分類可提供我們實用的工具,用來判斷應由使用者設定哪些資料,以及標記中應指定哪些資料。自動收集的資料可以安全地從事件中讀取。所有其他設定則應由使用者自行設定。

瞭解這點後,請再次查看 Baz Analytics 代碼的參數。

  • 評估 ID,id:由於系統不會自動收集這項資料,因此使用者在設定代碼時應輸入這個值的明確範例。
  • 事件名稱 en如上所述,事件名稱一律可直接從 event_name 參數取得。不過,由於其值是由使用者定義,因此我們會建議您視需要提供覆寫名稱的功能。
  • 網頁網址、l此值可從 page_location 參數取得,Google Analytics (分析) GA4 瀏覽器代碼會在每個事件中自動收集這個參數。因此,您不用要求使用者手動輸入值。
  • User ID、u在 Baz Analytics 伺服器代碼中,u 參數不是使用者指定參數,也是由網頁上的代碼自動收集。而是儲存在瀏覽器 Cookie 中,因此使用者即使多次造訪網站,也無法識別使用者。如下方實作所示,這是使用 setCookie API 設定 Cookie 的 Baz Analytics 伺服器代碼。也就是說,Baz Analytics (分析) 代碼是唯一知道 Cookie 儲存位置和方式的資訊。和 l 一樣,系統應自動收集 u 參數。

完成代碼設定後,看起來會像這樣:

Baz Analytics 代碼設定的快照。

導入廣告代碼

現在,代碼的設定將消失,可以繼續在沙箱 JavaScript 中導入代碼行為。

代碼必須做到以下四件事:

  1. 根據代碼的設定取得事件名稱。
  2. 從事件的 page_location 資源取得網頁網址。
  3. 計算 User-ID。代碼會在名為 _bauid 的 Cookie 中尋找使用者 ID。如果 Cookie 不存在,代碼會計算新的值並儲存該值,以供日後要求使用。
  4. 建立網址並向 Baz Analytics 收集伺服器提出要求。

另外,也建議您花點時間思考標記在容器中扮演何種角色。不同容器元件扮演的角色不同,因此代碼功能也不一定相同。您的代碼:

  • 不應檢查事件來確定是否應執行。這就是觸發條件的用途
  • 不應使用 runContainer API 執行容器。這就是用戶端的工作
  • 除了 Cookie 以外,不應嘗試直接與要求或回應互動。這也是客戶的工作。

如果您撰寫的標記範本執行了上述任一操作,可能會導致代碼使用者出現混淆的行為。舉例來說,如果標記向傳入要求傳送回應,用戶端就無法執行相同動作。這會導致使用者無法預期容器的行為。

瞭解這些概念後,以下是沙箱 JS 中的註解實作。

const encodeUriComponent = require('encodeUriComponent');
const generateRandom = require('generateRandom');
const getCookieValues = require('getCookieValues');
const getEventData = require('getEventData');
const logToConsole = require('logToConsole');
const makeString = require('makeString');
const sendHttpGet = require('sendHttpGet');
const setCookie = require('setCookie');

const USER_ID_COOKIE = '_bauid';
const MAX_USER_ID = 1000000000;

// The event name is taken from either the tag's configuration or from the
// event. Configuration data comes into the sandboxed code as a predefined
// variable called 'data'.
const eventName = data.eventName || getEventData('event_name');

// page_location is automatically collected by the Google Analytics 4 tag.
// Therefore, it's safe to take it directly from event data rather than require
// the user to specify it. Use the getEventData API to retrieve a single data
// point from the event. There's also a getAllEventData API that returns the
// entire event.
const pageLocation = getEventData('page_location');
const userId = getUserId();

const url = 'https://www.example.com/baz_analytics?' +
    'id=' + encodeUriComponent(data.measurementId) +
    'en=' + encodeUriComponent(eventName) +
    (pageLocation ? 'l=' + encodeUriComponent(pageLocation) : '') +
    'u=' + userId;

// The sendHttpGet API takes a URL and returns a promise that resolves with the
// result once the request completes. You must call data.gtmOnSuccess() or
// data.gtmOnFailure() so that the container knows when the tag has finished
// executing.
sendHttpGet(url).then((result) => {
  if (result.statusCode >= 200 && result.statusCode < 300) {
    data.gtmOnSuccess();
  } else {
    data.gtmOnFailure();
  }
});

// The user ID is taken from a cookie, if present. If it's not present, a new ID
// is randomly generated and stored for later use.
//
// Generally speaking, tags should not interact directly with the request or
// response. This prevents different tags from conflicting with each other.
// Cookies, however, are an exception. Tags are the only container entities that
// know which cookies they need to read or write. Therefore, it's okay for tags
// to interact with them directly.
function getUserId() {
  const userId = getCookieValues(USER_ID_COOKIE)[0] || generateRandom(0, MAX_USER_ID);
  // The setCookie API adds a value to the 'cookie' header on the response.
  setCookie(USER_ID_COOKIE, makeString(userId), {
    'max-age': 3600 * 24 * 365 * 2,
    domain: 'auto',
    path: '/',
    httpOnly: true,
    secure: true,
  });

  return userId;
}

因此代碼就會導入。您需要正確設定標記的 API 權限,才能使用該標記。前往範本編輯器的「Permissions」(權限) 分頁,並指定下列權限:

  • 讀取 Cookie 值:_bauid
  • 讀取事件資料:event_namepage_location
  • 傳送 HTTP 要求:https://www.example.com/*
  • 設定 Cookie:_bauid

此外,您也應該為代碼撰寫測試。如要進一步瞭解範本測試,請參閱範本開發人員指南的測試一節。

最後,請至少嘗試使用「Run Code」按鈕執行代碼。這樣可以防止許多簡單的錯誤發生到您的伺服器。

您已檢查完所有建立、測試和部署新代碼的作業,因此沒有理由保留標記內容。如果您認為新標記對其他使用者有幫助,請考慮將標記提交到社群範本庫。

結語

在本教學課程中,您已瞭解撰寫伺服器容器標記的基本概念。並瞭解:

  • 要使用哪些 API 讀取事件資料、傳送 HTTP 要求,以及在瀏覽器上設定 Cookie。
  • 設計代碼設定選項的最佳做法。
  • 使用者指定資料和自動收集的資料之間的差異,以及兩者之間的區別的重要性。
  • 代碼在容器中的角色,其正確和不可行。
  • 將標記範本提交至社群範本庫的時機和方式。