避免常見導入錯誤

下列情境代表導入 GPT 時最常發現的一些錯誤。儘管這類導入方式看似能搭配現行版本的 GPT 正常運作,但不保證日後會繼續執行。在最極端的情況下,這些導入方式可能會導致廣告放送作業意外中斷。 系統會將這些項目視為不支援的導入方式。

每個情境都會提供修正顯示問題的建議方法。

請注意,這份清單並未完整列出潛在問題,但這些清單應該可以當做實用指南,有助於您找出需要解決的問題類型。

此外,視導入方式而定,您必須在網站上找出所有需要進行這類變更的位置。

常見錯誤

情境 1:使用非官方的 GPT JavaScript 程式庫副本

一般用途說明 託管 gpt.js、pubads_impl.js 或任何從自有伺服器載入的程式庫,或是從非官方來源載入這些檔案。
含有錯誤的程式碼片段示例
// Incorrect: Accessing these files from an unofficial source
<script async src="https://www.example.com/tag/js/gpt.js"></script>
建議修正方式
// Correct: Access these files from a Google domain
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
// Also correct, if using Limited Ads
<script async src="https://pagead2.googlesyndication.com/tag/js/gpt.js"></script>

情境 2:依賴 gpt.js 指令碼代碼監聽器

一般用途說明 假設當 JavaScript 檔案 gpt.js 載入錯誤時,已可呼叫 GPT API,因為 pubads_impl.js 檔案會提供 API 的某些部分。由於在附加至指令碼標記的事件監聽器內,透過任何方式使用 API (包括架構),因此不正確。
含有錯誤的程式碼片段示例
var tag = document.createElement('script');
tag.type = 'text/javascript';
tag.src = (useSSL ? 'https:' : 'http:') +
        ‘//www.googletagservices.com/tag/js/gpt.js';
// Incorrect: Attaching a callback to the script’s onload event.
tag.onload = callback;
var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(tag, node);
建議修正方式
// Make sure that googletag.cmd exists.
window.googletag = window.googletag || {};
googletag.cmd = googletag.cmd || [];
// Correct: Queueing the callback on the command queue.
googletag.cmd.push(callback);
修正方式說明 / 說明 googletag.cmd 會保留一份指令清單,用來在 GPT 準備就緒時立即執行。要確保系統在 GPT 載入後執行回呼,這是正確的做法。

情境 3:檢查 googletag 物件,確認 GPT 是否已就緒

一般用途說明 由於載入 JavaScript 檔案 gpt.js 或已定義 googletag 物件時,GPT API 可能還未就緒,因此請檢查該物件,確認 GPT API 是否不可靠。
含有錯誤的程式碼片段示例
// Incorrect: Relying on the presence of the googletag object
// as a check for the GPT API.
if (typeof googletag != 'undefined') {
 functionProcessingGPT();
}
建議修正方式
// Correct: Relying on googletag.apiReady as a check for the GPT API.
if (window.googletag && googletag.apiReady) {
 functionProcessingGPT();
}
修正方式說明 / 說明 API 準備好呼叫後,GPT 就會填入布林值標記 googletag.apiReady,以便您做出可靠的斷言。

情境 4:依賴模糊化的程式碼語法

一般用途說明 只要您採用縮小版 GPT 程式庫程式碼的精準語法,就幾乎是不可能遇到的故障情形。為了不斷改進 GPT 內部運作機制,我們會持續變更 GPT 內部運作方式,因此請只使用 API 參考指南中記錄的 API。
舉例來說,其中一項常見的規定是偵測 PubAdsService 何時已完全載入,以便呼叫 refresh()
含有錯誤的程式碼片段示例
// Incorrect: Relying on an obfuscated property.
if (googletag.pubads().a != null) {
 functionProcessingGPT();
}
建議修正方式
// Correct: Relying on public GPT API methods
// (i.e. googletag.pubadsReady in this case).
if(window.googletag && googletag.pubadsReady) {
 functionProcessingGPT();
}
修正方式說明 / 說明 只能使用公用 API。在偵測 PubAdsService 是否已完全載入的情況下,我們會使用布林值 googletag.pubadsReady

情境 5:覆寫 GPT 的任何函式或變數

一般用途說明 如果是以覆寫 GPT 所用函式或變數為基礎的用途,則隨時可能會損毀,因為系統不支援這種情況。GPT 內部的時間變更可能會導致系統因為服務中斷而出現這類錯誤行為。
含有錯誤的程式碼片段示例
// Incorrect: Haphazardly overwriting a googletag.* property.
googletag.cmd = [];
建議修正方式
// Correct: Never overwrite googletag.* properties if they already exist.
// Always check before assigning to them.
googletag.cmd = googletag.cmd || [];

情境 6:對 GPT 發出順序錯誤的呼叫

一般用途說明 隨著 GPT 內部的發展,競爭狀況可能會造成中斷。如果陳述式組合因執行中的特定時間而無法正常運作,日後可能會無法繼續使用。
含有錯誤的程式碼片段示例
// Incorrect: Setting page-level key-value targeting after calling
// googletag.enableServices().
googletag.enableServices();
googletag.defineSlot(...);
googletag.pubads().setTargeting(e, a);
建議修正方式
// Correct: Setting page-level key-value targeting before calling
// googletag.enableServices().
googletag.pubads().setTargeting(e, a);
googletag.defineSlot(...);
googletag.enableServices();
修正方式說明 / 說明 請務必遵循 GPT 的正常時間,避免競爭狀況。有效的部分排序示例包括:
  • 定義-啟用-多媒體
    1. 定義網頁層級設定
    2. 定義運算單元
    3. enableServices()
    4. 顯示版位
  • 啟用-定義-多媒體
    1. 定義網頁層級設定
    2. enableServices()
    3. 定義運算單元
    4. 顯示版位

情境 7:誤用關閉和 JavaScript 變數範圍

一般用途說明 有關 JavaScript 變數範圍的假設,以及傳遞至 googletag.cmd.push 的函式中擷取的變數值不正確。
含有錯誤的程式碼片段示例
// Incorrect: Variable x is declared outside the anonymous function
// but referenced within it.
for (var x = 0; x < slotCount; x++) {
 window.googletag.cmd.push(
  function(){
    // If GPT is not yet loaded, this code will be executed subsequently when
    // the command queue is processed. Every queued function will use the last value
    // assigned to x (most likely slotCount).
    // This is because the function closure captures the reference to x,
    // not the current value of x.
    window.googletag.display(slot[x]);
  })
 }
}
建議修正方式
window.googletag.cmd.push(
 function(){
  // Correct: We both declare and reference x inside the context of the function.
  for (var x = 0; x < slotCount; x++){
   window.googletag.display(slot[x]);
  }
 }
)
修正方式說明 / 說明

在 JavaScript 中,閉包透過參照而非值來擷取變數。這表示如果重新指派某個變數,稍後會在執行擷取該變數的函式關閉時,使用該變數的新值。因此,視回呼是立即執行或延遲,關閉後程式碼的行為可能會不同。

如果是非同步載入 GPT,具體取決於 GPT 在指令佇列上載入回呼的速度,可能立即執行或否。在上述範例中,這會變更已排入佇列的指令的行為。

為避免發生問題,撰寫程式碼時,應避免假設放置在指令佇列中的函式會立即執行,並留意 JavaScript 的範圍規則。

情境 8:在呼叫螢幕後移動 DOM 中的版位容器

一般用途說明 在呼叫顯示畫面後,在 DOM 中移動或插入版位容器,可能會導致 GPT 中的異常重排和無法預測的行為。
含有錯誤的程式碼片段示例
// Incorrect: Moving slot containers after calling display
googletag.defineSlot("/1234/travel/asia", [728, 90], "div-gpt-ad-123456789-0");
googletag.enableServices();
googletag.display("div-gpt-ad-123456789-0");
...
// Inserting another element before the slot container, pushing the slot container down the page.
document.body.insertBefore(someOtherElement, document.getElementById("div-gpt-ad-123456789-0"));
建議修正方式
// Correct: Make any DOM order changes before calling display

document.body.insertBefore(someOtherElement, document.getElementById("div-gpt-ad-123456789-0"));
...
googletag.defineSlot("/1234/travel/asia", [728, 90], "div-gpt-ad-123456789-0");
googletag.enableServices();
googletag.display("div-gpt-ad-123456789-0");