Terra 如何運用預先擷取功能,將廣告點閱率提升 30%,並加速最大內容繪製速度。

預先擷取資源可加快網頁載入時間,並改善業務指標。

Guilherme Moser de Souza
Guilherme Moser de Souza

預先擷取是一種技術,可下載近期可能需要的資源 (甚至是整個網頁),藉此加快網頁載入速度。研究顯示,載入時間越短,轉換率就越高,使用者體驗也會更好。

Terra 是巴西最大的內容入口網站之一,提供娛樂、新聞和體育內容,每月不重複訪客人數超過 6,300 萬。我們與 Terra 的工程團隊合作,在網站的特定部分使用預先載入技術,改善文章的載入時間。

本案例研究說明 Terra 導入旅程後,行動裝置的廣告點閱率 (CTR) 提升 11%、電腦的廣告點閱率提升 30%,以及 最大內容繪製 (LCP) 時間縮短 50%。

預先擷取策略

預先擷取功能已推出一段時間,但請務必謹慎使用,因為這會消耗頻寬,用於非立即必要的資源。請謹慎採用這項做法,以免造成不必要的資料用量。在 Terra 的情況下,如果符合下列條件,系統就會預先擷取文章:

  • 預先擷取文章連結的可視度:Terra 使用 Intersection Observer API 偵測包含預先擷取文章的區塊的可視度。
  • 增加資料用量的有利條件:如前所述,預先載入是一種會消耗額外資料的效能提升方式,且在某些情況下可能不是理想的結果。為降低浪費頻寬的可能性,Terra 會使用 Network Information APIDevice Memory API,判斷是否要擷取下一篇文章。Terra 只會在下列情況下擷取下一篇文章:
    • 連線速度至少為 3G,且裝置至少有 4 GB 的記憶體。
    • 或裝置搭載 iOS。
  • CPU 閒置:最後,Terra 會使用 requestIdleCallback 檢查 CPU 是否處於閒置狀態,並能執行額外工作。這項檢查會在主執行緒處於閒置狀態時,或在特定 (選用) 期限到期時,處理回呼。

遵守這些條件可確保 Terra 只在必要時才擷取資料,進而節省頻寬和電池續航力,並盡可能減少未使用的預先擷取作業所造成的影響。

在符合這些條件時,Terra 會預先擷取「相關內容」和「推薦給你」(下方以藍色標示) 部分中的文章。

Terra 網站上兩個預先擷取連結的部分的螢幕截圖。左側是「相關內容」部分,右側則是「為你推薦」部分。

業務影響

為了評估這項做法的成效,Terra 首先在文章頁面的「相關內容」部分推出這項功能。他們使用 UTM 代碼來區分預先擷取的文章和未預先擷取的文章,以便進行比較。經過兩週的 A/B 版本測試後,Terra 決定在「推薦給您」專區中加入預先載入功能。

預先載入文章後,我們發現廣告指標整體提升,且 LCP 和首次字節回應時間 (TTFB) 縮短:

指標 行動裝置 電腦
廣告點閱率 +11% +30%
廣告可視度 +10.5% +6%
LCP -51% -73%
TTFB -83% -84%

預先載入功能 (若使用得當) 可大幅縮短網頁載入時間、提高廣告指標,並縮短 LCP 時間。

技術詳細資料

您可以使用資源提示 (例如 rel=prefetchrel=preload)、quicklinkGuess.js 等程式庫,或是使用較新的 Speculation Rules API 來實現預先載入功能。Terra 選擇使用 fetch API 搭配低優先順序,並結合 Intersection Observer 例項,實作這項功能。Terra 做出這個選擇,是因為這樣可以支援 Safari,而 Safari 尚未支援其他預先載入方法,例如 rel=prefetch 或推測規則 API,而且 Terra 的需求並不需要完整功能的 JavaScript 程式庫。

下列 JavaScript 與 Terra 使用的程式碼大致相同:

function prefetch(nodeLists) {
  // Exclude slow ECTs < 3g
  if (navigator.connection &&
    (navigator.connection.effectiveType === 'slow-2g'
      || navigator.connection.effectiveType === '2g')
  ) {
    return;
  }

  // Exclude low end device which is device with memory <= 2GB
  if (navigator.deviceMemory && navigator.deviceMemory <= 2) {
    return;
  }

  const fetchLinkList = {};

  const observer = new IntersectionObserver(function (entries) {
    entries.forEach(function (entry) {
      if (entry.isIntersecting) {
        if (!fetchLinkList[entry.target.href]) {
          fetchLinkList[entry.target.href] = true;

          fetch(entry.target, {
            priority: 'low'
          });
        }

        observer.unobserve(entry = entry.target);
      }
    });
  });
}

const idleCallback = window.requestIdleCallback || function (cb) {
  let start = Date.now();

  return setTimeout(function () {
    cb({
      didTimeout: false,
      timeRemaining: function () {
        return Math.max(0, 50 - (Date.now() - start));
      }
    });
  }, 1);
}

idleCallback(function () {
  prefetch(nodeLists)
})
  • prefetch 函式會先檢查最低連線品質和裝置記憶體,再啟動預先擷取。
  • 接著,使用 IntersectionObserver 監控元素何時會在檢視區中顯示,並在之後將網址新增至預先載入清單。
  • 預先載入程序會使用 requestIdleCallback 排程,目的是在主執行緒閒置時執行 prefetch 函式。

結論

只要謹慎使用,預先載入功能就能大幅縮短日後導覽要求的載入時間,進而減少使用者歷程中的阻礙,並提高參與度。預先載入會載入可能不會使用的額外位元組,因此 Terra 採取額外步驟,只在網路狀況良好且裝置支援的情況下,在可取得這類資訊的裝置上預先載入。

特別感謝 Gilberto Cocchi、Harry Theodoulou、Miguel Carlos Martínez Díaz、Barry Pollard、Jeremy Wagner,以及 Terra 工程團隊的 Leonardo Bellini 和 Lucca Paradeda 對這項工作的貢獻。