This document provides a technical overview of the Integral Ad Science (IAS) Publisher Optimization Prebid.js Adapter.
The Integral Ad Science (IAS) Publisher Optimization Prebid.js Adapter enables you to use the Publisher Optimization while leveraging Prebid.js.
Implementing Publisher Optimization through Prebid.js is more efficient from a size and time response perspective than going through the legacy Publisher Optimization implementation, because the Prebid.js file can be hosted on the same servers as the website. The only downside is since the JavaScript is stored locally, IAS can't update the code remotely. Therefore, publishers must upgrade to get IAS's updates.
This documentation covers Prebid.js version 4.
IAS's optimization allows your ad server to automatically deliver campaigns to goals defined by IAS measurement data. This solution enables you to:
Sell direct campaigns to advertisers with guarantees based upon IAS data – for example, a Run of Network (RON) campaign that has 70% viewability, no brand safety risk, and no invalid traffic.
Set up private marketplaces (PMP) with similar guarantees under conditions (AdExchange on DFP or Data Marketplace by Xandr) – for example, a PMP containing semi-transparent inventory that has 80% viewability, no brand safety risk, and no invalid traffic.
Your ad server's existing facilities for forecasting and automatic optimization can be fully leveraged. As a result, you can minimize waste from over buffering while minimizing risk of under delivery. This solution can minimize the amount of time ad ops needs to monitor campaigns with viewability or brand safety goals and unlock opportunities to sell segments of high quality inventory to advertisers at a premium.
Additionally, Publisher Optimization supports Keyword exclusion list segments which are negative keyword lists.
See the Publisher Optimization Implementation Guide for more information.
Header bidding is running supply-side platform (SSP) and ad exchange code directly on a web page so publishers can receive bids on their inventory that may be unavailable through their primary ad server and exchange. The returned bids are then passed into the ad server so the bids can compete with direct demand and the primary ad server's exchange on a level playing field. Prebid.js is an open source library that helps publishers implement header bidding.
At a more in-depth detail, before calling the ad server, all the ad slots are sent to the enabled SSPs with a mapping of all the ad slots. The SSPs send a request to their demand-side platforms (DSPs) and each DSP returns a winning bid. Then Prebid.js sends to the ad server the highest winning bid as a bundle of 3 key/values.
IAS's adapter for PreBid.js has the following boolean parameters to help determine winning bids:
alwaysUseBid
sendStandardTargeting
suppressEmptyKeys
pbjs.bidderSettings = {
ias: {
alwaysUseBid: true,
sendStandardTargeting: false,
suppressEmptyKeys: true,
...
}
}
alwaysUseBid allows a specific bidder to always pass its key/values.
In Prebid.js, by default, only the winning bid is be sent to the ad server. However, if you're working with a Prebid partner that's not returning a CPM value, it won't be able to compete against the other bids. Setting alwaysUseBid to true, allows the bidder to always send its bids. The decisioning of selecting the winning SSP is then left to the ad server. This way, a SSP passing the Deal ID key/value can trigger a campaign with a higher priority, even though the CPM returned is lower than those of other competing SSPs.
AlwaysUseBid: Bidder 2 returns a CPM (highest CPM) as well as Bidder 3
This boolean flag minimizes key/value pairs sent to the ad server when adapter-specific targeting is specified.
By default, the platform sends both adapter-specific adServerTargeting as well as the standard ad server targeting.
This boolean flag avoids sending empty values to the ad server.
You need to update your Prebid.js file to version 1.16.0 (and above) from prebid.org/download which includes the IAS Publisher Optimization Adapter.
Prior to the implementation, ensure:
The IAS monitoring tag is on all your properties concerned by this implementation for more than 15 days
Prebid.js is implemented on all your properties concerned by this implementation
In your ad manager (for example, DFP) account, go to the Inventory section and define the following key/values pairs precisely:
Prebid.js is JavaScript that must be placed on all publisher's webpages, in the header or through a Tag Management System, after the ad slots from the ad server are declared but before the call to the ad server is done, so that key/values can be sent.
You need to disable the initial loading of your ad server if this is an a sync ad server, before the ad slots are defined.
You must manually map the ad server's ad slots to the bidder's ad slots for each bidder in the competition.
<script async='async' src='./prebid.js'></script>
<script>
googletag.cmd.push(function() {
googletag.pubads().disableInitialLoad();
});
</script>
Then the publisher needs to provide a mapping of all the page's ad slots to their SSPs counterpart, for each bidder. Since IAS is not a bidder that contains ad slots (though IAS needs the ad server's mapping of ad slots), IAS only declares to IAS the different ad servers' ad slots as well as the publisher's anId (named pubId in this instance).
var adUnits = [
{
code: 'div-gpt-ad-1492761750660-0',
sizes: [[970, 250], [728, 90], [1000, 90]],
bids: [
{
bidder: 'ias',
params: {
pubId: '8713',
adUnitPath: '/57514611/user/pub_opt/'
+ 'top_banner'
}
}
]
},
{
code: 'div-gpt-ad-1492761750660-1',
sizes: [
[300, 250],
[300, 600]
],
bids: [
{
bidder: 'ias',
params: {
pubId: '8713'
adUnitPath: '/57514611/user/'
+ 'pub_opt/top_rectangle'
}
}
]
},
{
code: 'div-gpt-ad-1492761750660-2',
sizes: [
[300,250],
[300, 600]
],
bids: [
{
bidder: 'ias',
params: {
pubId: '8713',
adUnitPath: '/57514611/user/pub_opt/'
+ 'mid_rectangle'
}
}
]
}
];
Next you need to declare for each bidder the rules to follow for the answers from Prebid.js via the previously mentioned setups. For IAS bidder, you declare that this bidder always transmits its key/values (alwaysUseBid: true or alwaysUseBid: false).
Then since IAS won't need to transmit the usual bidder's key/values (winning CPM/winning creative), you can turn off the standard key/values targeting, which prevents from sending some key/values twice - under the IAS namespace and without this namespace (sendStandardTargeting: false).
Next, delete the empty keys, since IAS does not always return a value for each keys (like for GroupM viewability metrics for instance). Finally, you need to declare for each key where in the response JSON shall the value be taken (suppressEmptyKeys: true).
pbjs.bidderSettings = {
ias: {
alwaysUseBid: true,
sendStandardTargeting: false,
suppressEmptyKeys: true,
adserverTargeting: [
{
key: 'adt',
val: function(bidResponse) {
return bidResponse.adt;
}
},
{
key: 'alc',
val: function(bidResponse) {
return bidResponse.alc;
}
},
{
key: 'dlm',
val: function(bidResponse) {
return bidResponse.dlm;
}
},
{
key: 'drg',
val: function(bidResponse) {
return bidResponse.drg;
}
},
{
key: 'hat',
val: function(bidResponse) {
return bidResponse.hat;
}
},
{
key: 'off',
val: function(bidResponse) {
return bidResponse.off;
}
},
{
key: 'vio',
val: function(bidResponse) {
return bidResponse.vio;
}
},
{
key: 'fr',
val: function(bidResponse) {
return bidResponse.fr;
}
},
{
key: 'id',
val: function(bidResponse) {
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.id;
}
},
{
key: 'vw',
val: function(bidResponse) {
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.vw;
}
},
{
key: 'grm',
val: function(bidResponse) {
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.grm;
}
},
{
key: 'pub',
val: function(bidResponse) {
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.pub;
}
},
{
key: 'vw05',
val: function(bidResponse)
{
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.vw05;
}
},
{
key: 'vw10',
val: function(bidResponse)
{
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.vw10;
}
},
{
key: 'vw15',
val: function(bidResponse)
{
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.vw15;
}
},
{
key: 'vw30',
val: function(bidResponse)
{
var match = bidResponse.slots[bidResponse.adUnitCode];
return match.vw30;
}
},
{
key: 'ias-kw',
val: function (bidResponse)
{
return bidResponse.custom['ias-kw'];
}
}
]
}
}
Finally, review the callback function that deals with the targeting in the ad server and the launch of the ad server. A best practice is to use a time-out function to send the request to the different bidder's servers through the Prebid.js push function.
function sendAdserverRequest() {
if (pbjs.adserverRequestSent)
return;
pbjs.adserverRequestSent = true;
googletag.cmd.push(function() {
pbjs.que.push(function() {
pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
});
}
setTimeout(function() {
sendAdserverRequest();
}, PREBID_TIMEOUT);
pbjs.que.push(function() {
pbjs.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: sendAdserverRequest
});
});
In your ad server, target the usual IAS key/values, just like for IAS's Publisher Optimization product.
See the Publisher Optimization guide for more information on the key/values to set up on the ad server:
Brand Safety
Context Control
Invalid Traffic
Viewability
You can use the built-in ?pbjs_debug=true parameter in the URL that allows you to see extra logs in your browser's console.
You can also filter the Network tab of your browser by /prebid.js|pub\?anId|gampad/ (for DFP) to see the call to Prebid.js, the call to IAS's servers and the response, and the call to DFP.
From there, the troubleshooting is similar to what has to be done for Publisher Optimization.
If you want to see the actual JSON response of Prebid.js, you can add the following line to any of the bidder's settings' value:
console.log(JSON.stringify(bidResponse));
For example:
key: 'adt',
val: function(bidResponse) {
console.log(JSON.stringify(bidResponse));
return bidResponse.adt;
}
Review complete Google Ad Manager sample code below.
<html>
<head>
<script async='async' src =
'https://www.googletagservices.com/tag/js/gpt.js'></script>
<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
</script>
<script async='async' src='./prebid.js'></script>
<script>
googletag.cmd.push(function() {
googletag.pubads().disableInitialLoad();
});
</script>
<script>
googletag.cmd.push(function() {
googletag.defineSlot('/57514611/user/pub_opt/'
+ 'top_banner',
[
[970, 250],
[728, 90],
[1000, 90]
],
'div-gpt-ad-1492761750660-0').
addService(googletag.pubads());
googletag.defineSlot('/57514611/user/pub_opt/'
+ 'top_rectangle',
[
[300, 250],
[300, 600]
], 'div-gpt-ad-1492761750660-1').
addService(googletag.pubads());
googletag.defineSlot('/57514611/user/pub_opt/'
+ 'mid_rectangle',
[
[300, 250],
[300, 600]
], 'div-gpt-ad-1492761750660-2').
addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
<script>
var PREBID_TIMEOUT = 700;
var adUnits = [{
code: 'div-gpt-ad-1492761750660-0',
sizes: [[970, 250], [728, 90], [1000, 90]],
bids: [{
bidder: 'ias',
params: {
pubId: '8713',
adUnitPath: '/57514611/user/pub_opt/top_banner'
}
}]
function sendAdserverRequest() {
if (pbjs.adserverRequestSent) return;
pbjs.adserverRequestSent = true;
googletag.cmd.push(function() {
pbjs.que.push(function() {
pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
});
}
setTimeout(function() {
sendAdserverRequest();
}, PREBID_TIMEOUT);
pbjs.que.push(function() {
pbjs.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: sendAdserverRequest
});
});
</script>
</head>
<body>
<!-- /57514611/user/pub_opt/top_banner -->
<div id='div-gpt-ad-1492761750660-0'>
<script>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-1492761750660-0');
});
</script>
</div>
<!-- /57514611/user/pub_opt/top_rectangle -->
<div id='div-gpt-ad-1492761750660-1'>
<script>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-1492761750660-1');
});
</script>
</div>
<!-- /57514611/user/pub_opt/mid_rectangle -->
<div id='div-gpt-ad-1492761750660-2'>
<script>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-1492761750660-2');
});
</script>
</div>
</body>
</html>
Create an IAS case with details of your inquiry to receive help from our internal support team.