下列情境代表導入 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 的正常時間,避免競爭狀況。有效的部分排序示例包括:
|
情境 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"); |