埋設 DFP - DoubleClick for Publishers 廣告

文章目錄
  1. 1. 埋設 DFP - DoubleClick for Publishers 廣告
    1. 1.0.1. 初始設定
    2. 1.0.2. 多個廣告版位
    3. 1.0.3. 動態新增廣告
    4. 1.0.4. 自動縮合沒有廣告的版面
    5. 1.0.5. React Component 範例
  2. 1.1. 參考資料

意象說明

廣告媒合

埋設 DFP - DoubleClick for Publishers 廣告

初始設定

比較跳脫一般經驗法則的是,在載入 script 之後,服務仍然不是可用狀態,因此,此時不可呼叫相關服務 API。

譬如,以下是錯誤做法:

1
2
3
4
$.getScript('//www.googletagservices.com/tag/js/gpt.js').then(function () {
window.googletag.pubads().enableSingleRequest();
window.googletag.enableServices();
});

不論是透過直接在 html 中埋入 script tag 的方式載入,或是以上面的方式動態載入 DFP script,都不可以直接呼叫 DFP 的 API。

正確的做法,須將命令以函數的形式,推到 window.googletag.cmd 陣列中。注意,此時 googletaggoogletag.cmd 可以只是普通物件和陣列。待 DFP 服務啟動後,會在 googletag 中添加功能,然後逐一呼叫被推入 googletag.cmd 陣列的函數。也就是說,在該函數中才能保證 DFP 的服務已備妥,並且才能呼叫 API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var adUnitPath = 'pub-id/slot-id';
var adSize = [300, 25];
var adElementId = 'id-to-html-element';

$.getScript('//www.googletagservices.com/tag/js/gpt.js').then(function () {
var googletag = window.googletag || (window.googletag = []);
googletag.cmd = (googletag.cmd || []);
googletag.cmd.push(function () {
initDfp();
googletag.defineSlot(adUnitPath, adSize, adElementId)
.addService(googletag.pubads());
googletag.display(adElementId);
});
});

function initDfp() {
googletag.pubads().enableSingleRequest();
googletag.enableServices();
}

上面的 adElementId,雖然在 DFP 上使用 generate tag 時,會產生一個 div-gpt-ad-1234567890123-0 格式的字串,要我們填在 html 元素作為 id 使用,但其實只要保握 html 的基本原則:id 不要重複,在這裡使用任意 id 皆可,並不影響廣告呈現。不過 DFP 仍然建議,id 最好能反映廣告版位,以方便投廣告的客戶確認。

多個廣告版位

上面的做法,如果直接套用在多個廣告上,雖然不會有什麼問題,但是重複執行 DFP 的設定,還是讓人渾身不舒服。

可以將 $.getScript()initDfp() 的處理包裝起來,讓它們永遠只會執行一次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function once(fn) {
var promise;
return function () {
var args;
if (!promise) {
args = Array.prototype.slice.call(arguments);
promise = Promise.resolve(fn.apply(null, args));
}
return promise;
};
}

var loadDfp = once(function () {
return $.getScript('//www.googletagservices.com/tag/js/gpt.js').then(function () {
window.googletag = window.googletag || {};
window.googletag.cmd = window.googletag.cmd || [];
return window.googletag;
});
});

var initDfp = once(function (googletag) {
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});

然後,每個要新增版位的地方,都這樣呼叫:

1
2
3
4
5
6
7
8
loadDfp().then(function (googletag) {
googletag.cmd.push(function () {
initDfp(googletag);
googletag.defineSlot(adUnitPath, adSize, adElementId)
.addService(googletag.pubads());
googletag.display(adElementId);
});
});

注意到,initDfp() 的呼叫,不能併到 loadDfp() 中執行,只能在 googletag.cmd.push() 的函數中執行,否則就又犯了一開始的錯誤。

上面的寫法,還是有點囉唆,於是,我們還可以進一步包裝成這樣:

1
2
3
4
5
6
7
8
function dfp(fn) {
loadDfp().then(function (googletag) {
initDfp(googletag);
googletag.cmd.push(function () {
fn(googletag);
});
});
}
1
2
3
4
5
dfp(function(googletag) {
googletag.defineSlot(adUnitPath, adSize, adElementId)
.addService(googletag.pubads());
googletag.display(adElementId);
});

動態新增廣告

上面的做法,適用於內容不會變動的頁面。如果是無限捲動列表形式的頁面,可能需要每隔幾個項目就顯示一則廣告。官方建議的做法,是透過呼叫 disableInitialLoad() 函數禁止初始廣告載入,然後於版面備妥時,再呼叫 refresh() 更新廣告內容。

1
2
3
4
5
function initDfp(googletag) {
googletag.pubads().enableSingleRequest();
googletag.pubads().disableInitialLoad();
googletag.enableServices();
}

注意上面 googletag.pubads().disableInitialLoad() 的呼叫。此呼叫將改變 display() 函數的行為,使 display() 函數只註冊廣告版位,而不進行顯示。

在動態插入廣告之後,再呼叫 refresh() 函數,更新廣告:

1
2
3
4
5
6
dfp(function(googletag) {
var slot = googletag.defineSlot(adUnitPath, adSize, adElementId)
.addService(googletag.pubads());
googletag.display(adElementId);
googletag.pubads().refresh([slot]);
});

注意上面如何儲存 slot,然後用以呼叫 refresh() 函數。

自動縮合沒有廣告的版面

也許我們的版位不是非常熱門,經常開天窗(希望不是)。一旦廣告版位沒有人投遞廣告,該廣告版位就會顯示成空白。如果這是所有的版面的常態的話,可以考慮直接在初始化的時候,設定所有的版面在沒有廣告的時候,自動縮合。

1
2
3
4
5
6
function initDfp(googletag) {
googletag.pubads().enableSingleRequest();
googletag.pubads().disableInitialLoad();
googletag.pubads().collapseEmptyDivs();
googletag.enableServices();
}

或者,也可以根據需要,依據版面別進行個別設定:

1
2
3
4
5
6
7
8
9
10
var adCollapse = false;

dfp(function(googletag) {
const slot = googletag.defineSlot(adUnitPath, adSize, adElementId)
.addService(googletag.pubads())
.setCollapseEmptyDiv(adCollapse);
googletag.display(adElementId);
googletag.pubads().refresh([slot]);

});

React Component 範例

最後,測試的過程中寫了一簡單的 React 範例程式,提供給大家參考。

參考資料