[DFP] 如果再給我一次機會,我打死都不用 DFP(沒有誤

我開始使用 DFP 的時候,是還要有 AdSense 的帳號提出申請的年代。然後呢,那時候知道是 Google 用了 DoubleClick(買來的?然後持續演進到今天的 GPT...

如果讓我再選一次,我今天就不會坐在這裡,寫這篇文章了(欸


GPT 的問題點

最常看到的問題,就是廣告顯示不出來,也是最長被討論,也是被討論的歷史最悠久的問題。

  1. GPT 雖然有新版本的 JavaScript,但是問題依舊。
  2. 雖然有各種 workaround,但是依舊無法解決顯示問題。
  3. 依據新版本的 GPT 來看,能夠使用 refresh 來重新繪製廣告區域。
  4. DFP 後台廣告版位,會有聯播網廣告(也就是 AdSense 廣告亂入,但是你的 AdSense 根本沒開!
  5. 素材在 DFP 後台廣告會有自動消失的問題(然後隔天又自動出現!

如果讓我再選一次,我今天就不會坐在這裡,寫這篇文章了(欸

市面上最常見到的解法

  1. 拿掉 enableSingleRequest 可以解決 80% 以上廣告不出現的問題?
  2. 拿掉 GPT script async

不要再相信沒有根據的說法了,基本上 GPT 說 ad did not fetch 就是廣告沒有出來,你即便做了上述兩點,他依舊不會出來,而且屢試不爽!

解決方式

  1. 必須要檢查 DOM 上面的廣告區塊,與已經讀取的廣告區塊,數量上是否有落差。
  2. 數量落差就必須要重新 refresh 強迫再送一次廣告的資料。
  3. 重送不一定有效(補個幹!所以,保險的方式是確保重送後,廣告有真的秀出來。

所以你可能會要用到這些東西,

  1. slotOnload 必須要監聽哪些廣告區塊進入讀取。
  2. slotRenderEnded 監聽哪些廣告區塊讀取完畢。
  3. 由於 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)
}

強迫畫面做三次(根據實測,基本上只有第一次會生效(之後就不會再跑了,強迫他重新做過一次之後,廣告大概都會出現。

市面上的套件

其中比較有名一點的是這套,

https://github.com/coop182/jquery.dfp.js

但是廣告顯示的問題依舊,所以,我做了一個 Vue 版本的,加上替代方案,基本上可以確保廣告一定會出現,

https://github.com/hinablue/dfp-vue

歡迎送 PR!

小結

如果再給我一次機會,我打死都不用 DFP(沒有誤

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei