我開始使用 DFP 的時候,是還要有 AdSense 的帳號提出申請的年代。然後呢,那時候知道是 Google 用了 DoubleClick(買來的?然後持續演進到今天的 GPT...
如果讓我再選一次,我今天就不會坐在這裡,寫這篇文章了(欸
GPT 的問題點
最常看到的問題,就是廣告顯示不出來,也是最長被討論,也是被討論的歷史最悠久的問題。
- GPT 雖然有新版本的 JavaScript,但是問題依舊。
 - 雖然有各種 workaround,但是依舊無法解決顯示問題。
 - 依據新版本的 GPT 來看,能夠使用 
refresh來重新繪製廣告區域。 - DFP 後台廣告版位,會有聯播網廣告(也就是 AdSense 廣告亂入,但是你的 AdSense 根本沒開!
 - 素材在 DFP 後台廣告會有自動消失的問題(然後隔天又自動出現!
 
如果讓我再選一次,我今天就不會坐在這裡,寫這篇文章了(欸
市面上最常見到的解法
- 拿掉 
enableSingleRequest可以解決 80% 以上廣告不出現的問題? - 拿掉 GPT script 
async 
不要再相信沒有根據的說法了,基本上 GPT 說 ad did not fetch 就是廣告沒有出來,你即便做了上述兩點,他依舊不會出來,而且屢試不爽!
解決方式
- 必須要檢查 DOM 上面的廣告區塊,與已經讀取的廣告區塊,數量上是否有落差。
 - 數量落差就必須要重新 
refresh強迫再送一次廣告的資料。 - 重送不一定有效(補個幹!所以,保險的方式是確保重送後,廣告有真的秀出來。
 
所以你可能會要用到這些東西,
slotOnload必須要監聽哪些廣告區塊進入讀取。slotRenderEnded監聽哪些廣告區塊讀取完畢。- 由於 
refresh不一定會有效,所以需要做一個替代方案來監聽 DOM 中的廣告區塊是不是 真的 有廣告。 
本來是以為計算 slotOnload 或是 slotRenderEnded 這兩個事件所算出的數量,就可以檢查畫面上的廣告數量是否正確,
但是!就算這樣,數量還是會不對!
就算打開 GPT debug console 數量還是不對!
最後發現是 GPT 就是不去抓你的廣告內容回來!
而且他只跟你說
ad did not fetch這
console()不是廢話!什麼才是廢話!
所以,只好做出這樣的替代方案,
// 強迫檢查 3 次
let noShowTimer = 3
// 我的廣告區塊有一個 ClassName 叫做 .dfp-adunit
const slots = document.querySelectorAll('.dfp-adunit')
let adUnits = [/* 這裡是放 DFP 產出的資料結構,以 ID 對應每個版位 */]
// 底下是亂寫的,參考用就好。
const checkInitializeNoShow = () => {
  if (typeof checkInitializeNoShowTimer !== 'undefined') {
    clearInterval(checkInitializeNoShowTimer)
  }
  checkInitializeNoShowTimer = setInterval(() => {
    if (noShowTimer > 0) {
      // 把 DOM 上面每一個廣告區塊都檢查一次
      Array.prototype.forEach.call(slots, (adunit) => {
        // 如果 DFP 真的有把廣告版位產出,會帶一個 Query ID
        // 如果這個屬性不存在,就表示廣告根本沒被 DFP 產出
        if (adunit.firstElementChild.hasAttribute('data-google-query-id') === false) {
          let adUnit = adUnits.find((unit) => {
            return adunit.firstElementChild.id === Object.keys(unit)[0]
          })
          if (typeof adUnit !== 'undefined') {
            googletag.cmd.push(function () {
              // 如果找不到 DFP 產出的廣告版位,就把 DFP 的資料餵給 refresh 請他重新產出
              googletag.pubads().refresh([adUnit[adunit.firstElementChild.id]])
            })
          }
        }
      })
      noShowTimer--
    }
  }, 1000)
}
強迫畫面做三次(根據實測,基本上只有第一次會生效(之後就不會再跑了,強迫他重新做過一次之後,廣告大概都會出現。
市面上的套件
其中比較有名一點的是這套,
但是廣告顯示的問題依舊,所以,我做了一個 Vue 版本的,加上替代方案,基本上可以確保廣告一定會出現,
歡迎送 PR!
小結
如果再給我一次機會,我打死都不用 DFP(沒有誤