代碼和代碼管理工具的最佳做法

Katie Hempenius
Katie Hempenius

發布日期:2021 年 7 月 29 日

代碼是插入網站的第三方程式碼片段,通常會透過代碼管理工具插入。代碼最常用於行銷和數據分析。

代碼和代碼管理工具對網站效能的影響程度差異很大。代碼管理工具可視為信封:代碼管理工具提供容器,但您要填入什麼內容,以及如何使用,則取決於您。

本文將說明如何針對成效和 Core Web Vitals 最佳化代碼和代碼管理工具。雖然本文參照 Google 代碼管理工具,但許多討論的概念也適用於其他代碼管理工具。

對 Core Web Vitals 的影響

代碼管理工具通常會消耗網頁載入速度和回應速度所需的資源,進而間接影響 Core Web Vitals。頻寬可用於下載網站的代碼管理工具 JavaScript,或後續的呼叫。主要執行緒的 CPU 時間可用於評估及執行代管器和代碼中包含的 JavaScript。

在網頁載入時間的關鍵期間,最大內容繪製 (LCP) 容易受到頻寬內容競爭的影響。此外,封鎖主執行緒可能會延遲 LCP 轉譯時間

累計版面配置轉移 (CLS) 可能會受到影響,原因可能是在首次轉譯前延遲載入重要資源,或是標記管理工具將內容插入網頁。

Interaction to Next Paint (INP) 容易受到主執行緒上的 CPU 競爭影響,我們發現代碼管理工具的大小與 INP 分數較低之間存在關聯。

選擇合適的代碼類型

廣告代碼對成效的影響會因廣告代碼類型而異。一般來說,圖片代碼 (「像素」) 的效能最高,其次是自訂範本,最後是自訂 HTML 代碼。供應商代碼會因允許的功能而異。

請注意,標記的使用方式會對成效產生重大影響。「像素」的效能極高,主要是因為這個代碼類型的特性會嚴格限制其使用方式;自訂 HTML 代碼不一定會影響效能,但由於它們為使用者提供的自由度較高,因此很容易遭到濫用,進而影響效能。

在考量代碼時,請留意規模:單一代碼的成效影響可能微乎其微,但如果同一個網頁使用數十或數百個代碼,成效影響就可能變得相當顯著。

並非所有程式輔助函式都應透過代碼管理工具載入

代碼管理工具通常不是載入資源的最佳方式,因為這類資源會實作使用者體驗的即時視覺或功能面向,例如 Cookie 通知、主圖片或網站功能。使用代碼管理工具載入這些資源通常會延遲傳送。這會影響使用者體驗,也可能會增加 LCP 和 CLS 等指標。

此外,部分使用者會封鎖代碼管理工具。使用代碼管理工具導入使用者體驗功能,可能會導致部分使用者無法存取網站。

使用自訂 HTML 標記時請小心

自訂 HTML 標記已存在多年,且在大多數網站上廣泛使用。您可以使用自訂 HTML 代碼輸入自己的程式碼,且限制較少,因為這個代碼的主要用途是將自訂 <script> 元素新增至網頁,而非如其名稱所示。

自訂 HTML 標記的用途多元,成效影響也大不相同。評估網站效能時,請注意,大多數工具會將自訂 HTML 代碼的效能影響歸因於插入代碼的代碼管理工具,而非代碼本身。

在 Google 代碼管理工具中建立自訂代碼

自訂 HTML 代碼可將元素插入周圍網頁。在網頁中插入元素的動作可能會導致效能問題,在某些情況下也會造成版面配置變動。

  • 在大多數情況下,如果元素插入頁面,瀏覽器就必須重新計算頁面上每個項目的大小和位置。這項程序稱為「版面配置」。單一版面的效能影響程度不大,但如果過度使用,就可能導致效能問題。這種現象對低階裝置和含有大量 DOM 元素的網頁影響較大。
  • 如果在周圍區域已轉譯完成後,將可見的網頁元素插入 DOM,可能會導致版面配置位移。這種現象並非標記管理工具獨有,但由於標記通常會比網頁的其他部分晚載入,因此通常會在周圍網頁已轉譯後才插入 DOM。

使用自訂範本

自訂範本支援與自訂 HTML 標記相同的部分作業,但是以沙箱版 JavaScript 建構而成,可提供API,用於指令碼插入和像素插入等常見用途。顧名思義,這類範本可由進階使用者建立,他們可以考量效能來建構範本。非技術人員就能使用這個範本。這通常比提供完整的自訂 HTML 存取權更安全。

由於自訂範本受到更多限制,因此這些代碼不太可能出現效能或安全性問題。基於相同原因,自訂範本無法適用於所有用途。

Google 代碼管理工具中的自訂範本

正確插入指令碼

使用代碼管理工具插入指令碼是相當常見的用途。建議您使用自訂範本和 injectScript API。

如要瞭解如何使用 injectScript API 轉換現有的自訂 HTML 代碼,請參閱「轉換現有代碼」一文。

如果您必須使用自訂 HTML 標記,請注意以下事項:

  • 載入資料庫和大型第三方指令碼時,應使用可下載外部檔案的指令碼標記 (例如 <script src="external-scripts.js">),而非直接將指令碼內容複製貼上至標記。雖然不使用 <script> 標記可避免單獨的來回連線,以便下載指令碼的內容,但這項做法會增加容器大小,並防止瀏覽器單獨快取指令碼。
  • 許多供應商建議將 <script> 標記放在 <head> 的頂端。不過,如果是透過代碼管理工具載入的指令碼,通常就不需要這麼做。在大多數情況下,在代碼管理工具執行時,瀏覽器已完成剖析 <head>

使用像素

有時,第三方指令碼可以用圖片或 iframe 像素取代。與以指令碼為基礎的對應項目相比,像素可能支援的功能較少,因此通常不太受歡迎。不過,如果在代碼管理工具中使用像素,則像素的動態性會更高,因為像素可以根據觸發條件觸發並傳遞不同的變數。

像素是效能最高且最安全的代碼類型,因為在觸發後不會執行 JavaScript。像素的資源大小非常小 (小於 1 KB),也不會造成版面配置變動。

請洽詢第三方供應商,進一步瞭解他們支援的像素。此外,您也可以嘗試檢查程式碼是否有 <noscript> 標記。如果供應商支援像素,通常會在 <noscript> 標記中加入像素。

Google 代碼管理工具中的自訂圖片代碼

像素的替代方案

像素廣告的主要原因是,在伺服器回應不相關的情況下 ( 例如傳送資料給數據分析供應商),像素廣告是當時最便宜且最可靠的 HTTP 要求方式之一。navigator.sendBeacon()fetch() keepalive API 的設計目的是因應相同用途,但可說比 Pixel 更可靠。

繼續使用像素並無不妥,因為像素受到良好支援,且對效能影響極小。不過,如果您要建構自己的訊號發射器,建議您考慮使用其中一個 API。

sendBeacon()

navigator.sendBeacon() API 設計用於在伺服器回應不重要時,將少量資料傳送至網路伺服器。

const url = "https://example.com/analytics";
const data = JSON.stringify({
    event: "checkout",
    time: performance.now()
});

navigator.sendBeacon(url, data);

sendBeacon() 的 API 功能有限:只支援提出 POST 要求,不支援設定自訂標頭。所有新式瀏覽器都支援這項功能。

Fetch API keepalive

keepalive 是一種旗標,可讓您使用 Fetch API 提出事件報表和分析等非阻斷式要求。使用方式是在傳遞至 fetch() 的參數中加入 keepalive: true

const url = "https://example.com/analytics";
const data = JSON.stringify({
  event: "checkout",
  time: performance.now()
});

fetch(url, {
    method: 'POST',
    body: data,
    keepalive: true
});

如果 fetch() keepalivesendBeacon() 看起來很相似,那是因為它們確實相似。事實上,在 Chromium 瀏覽器中,sendBeacon() 目前是建構在 fetch() keepalive 之上。

在選擇 fetch() keepalivesendBeacon() 時,請務必考量所需的功能和瀏覽器支援情形。fetch() API 的彈性更高,但 keepalive 的瀏覽器支援sendBeacon() 少。

瞭解標記的作用

代碼通常會按照第三方供應商提供的指引建立。如果不清楚廠商的程式碼的作用,建議您向相關人員洽詢。取得第二意見有助於判斷代碼是否可能造成效能或安全性問題。

建議您在代碼管理工具中為代碼加上擁有者標籤。很容易忘記標記的擁有者,導致擔心移除標記會導致某些項目發生問題!

觸發條件

大致來說,要最佳化代碼觸發事件,通常就是確保不會觸發過多不必要的代碼,並選擇能平衡業務需求和成效成本的觸發事件。

觸發事件是 JavaScript 程式碼,會增加代碼管理工具的大小和執行成本。雖然大部分的觸發事件都很小,但累積起來的影響可能會相當可觀。舉例來說,如果有許多點擊事件或計時器觸發條件,代碼管理工具的工作負載可能會大幅增加。

選擇適當的觸發事件

代碼對效能造成的影響可能有所不同。一般來說,代碼觸發的時間越早,對效能造成的影響就越大。資源通常會在初始頁面載入期間受到限制,因此載入或執行特定資源 (或標記) 會將資源從其他位置移除。

雖然為所有代碼選擇適當的觸發條件很重要,但對於載入大型資源或執行長時間指令碼的代碼來說,這點尤其重要。

代碼可在網頁瀏覽 (通常為 Page load、on DOM Ready、on Window Loaded) 或自訂事件觸發。為避免影響網頁載入作業,請在 Window Loaded 之後觸發非必要的代碼。

使用自訂事件

使用自訂事件觸發條件,回應 Google 代碼管理工具內建觸發條件未涵蓋的網頁事件。舉例來說,許多代碼都會使用網頁瀏覽觸發事件。不過,DOM ReadyWindow Loaded 之間的時間可能很長,因此很難精確調整代碼觸發的時機。自訂事件可以解決這個問題。

首先,請建立自訂事件觸發條件,並更新代碼以使用這個觸發條件。

Google 代碼管理工具中的自訂事件觸發條件

如要觸發觸發條件,請將對應事件推送至資料層。

// Custom event trigger that fires after 2 seconds
setTimeout(() => {
  dataLayer.push({
    'event' : 'my-custom-event'
  });
}, 2000);

使用特定的觸發條件

定義特定觸發條件,避免在不需要時觸發代碼。其中一種最簡單且有效的方法,就是確保代碼只在實際使用的網頁上觸發。

Google 代碼管理工具中的觸發條件

內建變數可納入觸發條件,以限制代碼的觸發。

在適當時間載入代碼管理工具

您可以調整代碼管理工具的載入時間,改善成效。無論觸發條件如何設定,都必須在代碼管理工具載入後才能觸發。請嘗試調整載入代碼管理工具的時機,因為這可能會產生相同或更大的影響。這項決定會影響網頁上的所有代碼。

將代碼管理工具的載入作業延後,可避免不小心過早載入代碼,進而避免日後發生效能問題。

變數

使用變數讀取網頁中的資料。這類變數可用於觸發條件和代碼本身。

與觸發條件一樣,變數會在代碼管理工具中加入 JavaScript 程式碼,因此可能會導致效能問題。變數可以相對較小,例如用於讀取網址、Cookie、資料層或 DOM 部分的程式碼。也可以包含無限制功能 (和大小) 的自訂 JavaScript。

請盡量減少變數用量,因為代碼管理工具會持續評估變數。移除不再使用的舊變數,以縮減代碼管理工具指令碼的大小和處理時間。

標記管理

有效使用這些標記可降低效能問題的風險。

使用資料層

資料層是 JavaScript 物件陣列,其中包含網頁相關資訊。這些物件包含您要傳遞至 Google 代碼管理工具的所有資訊。

資料層也可用於觸發代碼。

// Contents of the data layer
window.dataLayer = [{
    'pageCategory': 'signup',
    'visitorType': 'high-value'
  }];

// Pushing a variable to the data layer
window.dataLayer.push({'variable_name': 'variable_value'});

// Pushing an event to the data layer
window.dataLayer.push({'event': 'event_name'});

雖然 Google 代碼管理工具不必搭配資料層就能使用,但我們強烈建議您使用資料層。資料層會將第三方指令碼可存取的資料整合到單一位置,進而提供更清晰的使用情形。這有助於減少不必要的變數計算和指令碼執行作業。

使用資料層,您就能控管代碼存取哪些資料,而非提供完整的 JavaScript 變數或 DOM 存取權。

由於更新資料層會導致 Google 代碼管理工具重新評估所有容器變數,並可能觸發代碼 (這會導致 JavaScript 執行),因此資料層的成效優勢可能不明顯。雖然資料層可能會遭到濫用,但一般來說,如果資料層似乎是效能問題的來源,容器本身可能就會有效能問題。資料層會讓這些問題更加明顯。

移除重複和未使用的代碼

除了透過代碼管理工具插入代碼,如果網頁的 HTML 標記中也包含代碼,就可能出現重複的代碼。

應暫停或移除未使用的代碼,而非使用觸發例外狀況來封鎖代碼。暫停或移除標記會從容器中移除程式碼,但封鎖不會。

移除未使用的代碼後,請檢查觸發條件和變數,判斷是否也能移除這些項目。

已暫停的代碼會影響容器大小,但總酬載量會比代碼處於啟用狀態時來得小。

使用允許和拒絕清單

使用允許和拒絕清單,針對網頁上允許的代碼、觸發條件和變數,設定精細的限制。這項功能可用於強制執行效能最佳做法和其他政策。

允許和拒絕清單會透過資料層設定。

window.dataLayer = [{
  'gtm.allowlist': ['<id>', '<id>', ...],
  'gtm.blocklist': ['customScripts']
}];

舉例來說,您可以禁止使用自訂 HTML 標記、JavaScript 變數或直接存取 DOM。這表示您只能使用像素和預先定義的代碼,並搭配資料層的資料。雖然這項限制較嚴格,但可實現更高效且安全的代碼管理工具導入方式。

考慮使用伺服器端代碼

建議您考慮改用伺服器端代碼,尤其是想進一步掌控資料的大型網站。伺服器端代碼會從用戶端移除供應商代碼,並將處理工作從用戶端卸載至伺服器。

舉例來說,使用用戶端代碼時,如果要將資料傳送至多個 Analytics 帳戶,就必須讓用戶端針對每個端點發出個別要求。使用伺服器端代碼時,用戶端會向伺服器端容器提出單一要求,而這項資料會從該容器轉送至不同的 Analytics 帳戶。

請注意,伺服器端代碼僅適用於部分代碼。廣告代碼的相容性會因供應商而異。

詳情請參閱「伺服器端標記簡介」。

容器

代碼管理工具通常會在設定中允許多個執行個體 (通常稱為「容器」)。您可以在一個代碼管理工具帳戶中控制多個容器。

每個網頁僅使用一個容器

單一頁面上的多個容器可能會造成嚴重的效能問題,因為這會引入額外的額外負擔和指令碼執行作業。至少,它會複製核心標記程式碼本身,而這類程式碼會作為容器的 JavaScript 的一部分提供,因此無法在容器之間重複使用。

多個容器很少能有效使用。不過,如果控制得宜,這麼做還是有用。例如:

  • 包括較輕的「早期載入」容器和較重的「後期載入」容器,而非一個大型容器。
  • 針對技術程度較低的使用者使用受限制的容器,針對較複雜的代碼使用較不受限制但控制較嚴格的容器。

如果每個網頁都必須使用多個容器,請按照 Google 代碼管理工具的說明設定多個容器

視需要使用不同的容器

如果您將代碼管理工具用於多個資源 (例如網頁應用程式和行動應用程式),使用的容器數量可能會影響工作流程的生產力。也會影響成效。

如果網站的用途和結構相似,單一容器就能有效地用於多個網站。舉例來說,雖然品牌的行動和網頁應用程式可能提供類似的功能,但應用程式的結構可能不同,因此透過個別容器管理會更有效率。

過度重複使用單一容器,可能會導致複雜的邏輯管理代碼和觸發條件,進而增加容器的複雜度和大小。

留意容器大小

容器的大小取決於其代碼、觸發條件和變數。雖然小型容器仍可能對網頁效能造成負面影響,但大型容器幾乎肯定會造成影響。

在最佳化代碼使用情形時,容器大小不應是最重要的指標。不過,容器大小過大通常是警訊,表示容器維護不當,且可能遭到濫用。

Google Tag Manager 會將容器大小限制為 300 KB,並在容器大小達到大小限制的 70% 時發出警告。

大多數網站應盡量將容器大小控制在限制以下。為方便比較,網站容器的中位數約為 50 KB。經過壓縮後,Google 代碼管理工具的程式庫大小約為 33 KB。

為容器版本命名

容器版本是容器內容在特定時間點的快照。使用有意義的名稱,並附上簡短說明內含的重要變更,有助於日後更輕鬆地偵錯成效問題。

標記工作流程

請務必管理代碼變更,避免對網頁成效造成負面影響。

部署前先測試

在部署前測試代碼,以便在發布前找出問題和效能問題等問題。

測試代碼時,請考量下列事項:

  • 代碼是否正常運作?
  • 標記是否會導致版面配置位移?
  • 標記是否會載入任何資源?這些資源的大小為何?
  • 標記是否會觸發長時間執行的指令碼?

預覽模式

預覽模式可讓您在實際網站上測試代碼變更,而無須先將其部署給大眾。預覽模式包含偵錯控制台,可提供代碼相關資訊。

在預覽模式下執行時,Google Tag Manager 的執行時間會有所不同 (稍微變慢),因為需要額外的額外負擔,才能在偵錯主控台中顯示資訊。因此,我們不建議比較在預覽模式和正式環境中收集的 Web Vitals 評量資料。不過,這項差異不應影響標記本身的執行行為。

獨立測試

另一種測試代碼的方法,是設定空白網頁,其中包含一個容器,並在容器中放入要測試的單一代碼。這項測試設定不太實際,而且不會偵測到某些問題 (例如標記是否會導致版面配置變更),但可以更輕鬆地隔離及評估標記對指令碼執行等事項的影響。請查看 Telegraph 如何使用這種隔離方法改善第三方程式碼的效能

監控代碼成效

您可以使用 Google 代碼管理工具的監控 API,收集特定代碼的執行時間相關資訊。這項資訊會回報至您選擇的端點。

詳情請參閱「如何建立 Google 代碼管理工具監控工具」。

需要核准容器變更

第一方程式碼通常會在部署前經過審查和測試。對待標記的方式相同。

新增兩步驟驗證功能,要求管理員核准容器變更,就是其中一種做法。或者,如果您不想要求使用者進行兩步驟驗證,但仍想密切留意變更,可以設定容器通知,以便收到您選擇的容器事件電子郵件快訊。

定期稽核標記使用情形

使用標記時,其中一個難題是標記往往會隨著時間累積:標記會新增,但很少會移除。定期稽核標記是扭轉這種趨勢的一種方法。理想的頻率取決於網站代碼更新的頻率。

標示每個標籤,讓擁有者一目瞭然,方便識別誰負責該標籤,並能指出是否仍需要該標籤。

稽核代碼時,請務必清理觸發條件和變數。這類問題也經常會導致效能問題。

詳情請參閱「控制第三方指令碼」。