如何建立伺服器代碼

在「伺服器端代碼簡介」一文中,您已瞭解代碼管理工具中的伺服器端代碼。您已瞭解用戶端的定義和用途:用戶端會接收使用者裝置的事件資料,並將資料轉換成其他容器可用的格式。本文將說明如何在伺服器端代碼中處理這類資料。

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

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

  • Google Analytics 4
  • HTTP 要求

如果您想將資料傳送至 Google Analytics 以外的位置,或是需要比 HTTP 要求代碼提供的更多功能,就必須使用其他代碼。您可以在社群範本庫中找到其他代碼,也可以自行編寫。本教學課程將教您為伺服器容器編寫自己的標記。

目標

  • 瞭解要在瀏覽器中讀取事件資料、傳送 HTTP 要求及設定 Cookie 時,應使用哪些 API。
  • 瞭解設計代碼設定選項的最佳做法。
  • 瞭解使用者指定資料與自動收集的資料之間的差異,以及這種區別的重要性。
  • 瞭解代碼在伺服器容器中的角色。瞭解代碼的使用方式和注意事項。
  • 瞭解何時應考慮將代碼範本提交至社群範本庫

必要條件

Baz Analytics 代碼

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

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

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

代碼設定

首先,請建立標記範本。前往容器的「範本」部分,然後點選「代碼範本」部分中的「新增」。為代碼新增名稱和說明。

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

  1. 總設定:為每個參數新增設定欄位。使用者必須明確設定所有屬性。
  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 參數直接取得。不過,由於其值是由使用者定義,因此建議您提供覆寫名稱的功能 (如有需要)。
  • Page URL l這個值可以從 page_location 參數取得,Google Analytics GA4 瀏覽器代碼會自動收集每個事件的資料。因此,您不應要求使用者手動輸入值。
  • 使用者 ID,u在 Baz Analytics 伺服器代碼中,u 參數既不是使用者指定,也不是由網頁上的代碼自動收集。而是儲存在瀏覽器 Cookie 中,方便在使用者多次造訪網站時識別使用者。如您在以下實作中所見,Baz Analytics 伺服器代碼會使用 setCookie API 設定 Cookie。換句話說,您只能透過 Baz Analytics 標記得知 Cookie 的儲存位置和方式。和 l 一樣,系統應該自動收集 u 參數。

設定代碼設定後,應該會如下所示:

Baz Analytics 代碼的代碼設定快照。

導入廣告代碼

代碼設定完成後,您就可以在沙箱機制的 JavaScript 中實作代碼行為。

代碼需要執行四項操作:

  1. 從代碼設定取得事件名稱。
  2. 從事件的 page_location 屬性取得網頁網址。
  3. 計算使用者 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。
  • 為代碼設計設定選項的最佳做法。
  • 使用者指定資料和自動收集資料的差異,以及為何這項區別相當重要。
  • 標記在容器中的角色,以及標記應做和不應做的事。
  • 將代碼範本提交至社群範本庫的時間和方式。