Skip to content

Commit

Permalink
Supporting multi-format ads in prebid
Browse files Browse the repository at this point in the history
  • Loading branch information
antosarho committed Sep 24, 2024
1 parent d693107 commit fb5dddd
Show file tree
Hide file tree
Showing 3 changed files with 446 additions and 21 deletions.
132 changes: 132 additions & 0 deletions integrationExamples/gpt/adnuntius_multiformat_example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<html>
<head>
<script async src="https://www.googletagservices.com/tag/js/gpt.js"></script>
<script async src="../../build/dev/prebid.js"></script>
<script>
var FAILSAFE_TIMEOUT = 3000;

var adUnits = [{
code: 'div-gpt-ad-1683695049516-0',
bids: [{
bidder: 'adnuntius',
params: {
auId: "381535",
network: "1287",
bidType: 'netBid',
targeting: {
kv: {
'isolate': 'native-anto'
}
}
}
}],
mediaTypes: {
banner: {
sizes: [[200, 200]]
},
video: {
playerSize: [200, 200],
context: 'instream'
}
}},
{
code: 'div-gpt-ad-1683695049516-0',
bids: [{
bidder: 'adnuntius',
params: {
auId: "381535",
network: "1287",
bidType: 'netBid',
targetId: 'fred',
targeting: {
kv: {
'isolate': 'native-anto'
}
}
}
}],
mediaTypes: {
banner: {
sizes: [[200, 200]]
},
video: {
playerSize: [200, 200],
context: 'instream'
}
}}];
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function() {
googletag.pubads().disableInitialLoad();
});

var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

pbjs.que.push(function() {
pbjs.setConfig({
enableSendAllBids: true,
targetingControls: {
alwaysIncludeDeals: true
},
userSync: {
syncEnabled: false
}
});

pbjs.setBidderConfig({
bidders: ['adnuntius'],
config: {
bidType: 'netBid'
}
});

pbjs.bidderSettings = {
standard: {
storageAllowed: true
}
};

pbjs.addAdUnits(adUnits);
pbjs.requestBids({bidsBackHandler: initAdserver});
});

function initAdserver() {
if (pbjs.initAdserverSet) return;
pbjs.initAdserverSet = true;
googletag.cmd.push(function() {
pbjs.que.push(function() {
pbjs.setTargetingForGPTAsync('div-gpt-ad-1683695049516-0');
googletag.pubads().refresh();
});
});
}

// in case PBJS doesn't load
setTimeout(function() {
initAdserver();
}, FAILSAFE_TIMEOUT);

window.googletag = window.googletag || {cmd: []};
googletag.cmd.push(function() {
googletag.defineSlot('/19660636/320x320', [320, 320], 'div-gpt-ad-1683695049516-0').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
</head>
<body>
<h2>Adnuntius NATIVE</h2>
<h5>Ad Slot 1</h5>

<!-- /19660636/320x320 -->
<div id='div-gpt-ad-1683695049516-0' style='min-width: 320px; min-height: 320px;'>
<script>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-1683695049516-0');
});
</script>
</div>

</body>
</html>
86 changes: 69 additions & 17 deletions modules/adnuntiusBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import {BANNER, VIDEO} from '../src/mediaTypes.js';
import {isStr, isEmpty, deepAccess, getUnixTimestampFromNow, convertObjectToArray} from '../src/utils.js';
import { config } from '../src/config.js';
import { getStorageManager } from '../src/storageManager.js';
Expand All @@ -12,13 +12,20 @@ const BIDDER_CODE_DEAL_ALIASES = [1, 2, 3, 4, 5].map(num => {
const ENDPOINT_URL = 'https://ads.adnuntius.delivery/i';
const ENDPOINT_URL_EUROPE = 'https://europe.delivery.adnuntius.com/i';
const GVLID = 855;
const DEFAULT_VAST_VERSION = 'vast4'
const SUPPORTED_MEDIA_TYPES = [BANNER, VIDEO];
const MAXIMUM_DEALS_LIMIT = 5;
const VALID_BID_TYPES = ['netBid', 'grossBid'];
const METADATA_KEY = 'adn.metaData';
const METADATA_KEY_SEPARATOR = '@@@';

export const misc = {
findHighestPrice: function(arr, bidType) {
return arr.reduce((highest, cur) => {
const currentBid = cur[bidType];
const highestBid = highest[bidType]
return currentBid.currency === highestBid.currency && currentBid.amount > highestBid.amount ? cur : highest;
}, arr[0]);
}
};

const storageTool = (function () {
Expand Down Expand Up @@ -219,7 +226,7 @@ export const spec = {
code: BIDDER_CODE,
aliases: BIDDER_CODE_DEAL_ALIASES,
gvlid: GVLID,
supportedMediaTypes: [BANNER, VIDEO],
supportedMediaTypes: SUPPORTED_MEDIA_TYPES,
isBidRequestValid: function (bid) {
// The auId MUST be a hexadecimal string
const validAuId = AU_ID_REGEX.test(bid.params.auId);
Expand Down Expand Up @@ -266,10 +273,6 @@ export const spec = {
}

let network = bid.params.network || 'network';
if (bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.context !== 'outstream') {
network += '_video'
}

bidRequests[network] = bidRequests[network] || [];
bidRequests[network].push(bid);

Expand All @@ -291,20 +294,40 @@ export const spec = {

const bidTargeting = {...bid.params.targeting || {}};
targetingTool.mergeKvsFromOrtb(bidTargeting, bidderRequest);
const adUnit = { ...bidTargeting, auId: bid.params.auId, targetId: bid.params.targetId || bid.bidId };
const maxDeals = Math.max(0, Math.min(bid.params.maxDeals || 0, MAXIMUM_DEALS_LIMIT));
if (maxDeals > 0) {
adUnit.maxDeals = maxDeals;
const mediaTypes = bid.mediaTypes || {};
const validMediaTypes = SUPPORTED_MEDIA_TYPES.filter(mt => {
return mediaTypes[mt];
}) || [];
if (validMediaTypes.length === 0) {
// banner ads by default if nothing specified, dimensions to be derived from the ad unit within adnuntius system
validMediaTypes.push(BANNER);
}
if (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) adUnit.dimensions = bid.mediaTypes.banner.sizes
networks[network].adUnits.push(adUnit);
const isSingleFormat = validMediaTypes.length === 1;
validMediaTypes.forEach(mediaType => {
const mediaTypeData = mediaTypes[mediaType];
if (mediaType === VIDEO && mediaTypeData && mediaTypeData.context === 'outstream') {
return;
}
const targetId = (bid.params.targetId || bid.bidId) + (isSingleFormat || mediaType === BANNER ? '' : ('-' + mediaType));
const adUnit = {...bidTargeting, auId: bid.params.auId, targetId: targetId};
if (mediaType === VIDEO) {
adUnit.adType = 'VAST';
}
const maxDeals = Math.max(0, Math.min(bid.params.maxDeals || 0, MAXIMUM_DEALS_LIMIT));
if (maxDeals > 0) {
adUnit.maxDeals = maxDeals;
}
if (mediaType === BANNER && mediaTypeData && mediaTypeData.sizes) {
adUnit.dimensions = mediaTypeData.sizes;
}
networks[network].adUnits.push(adUnit);
});
}

const requests = [];
const networkKeys = Object.keys(networks);
for (let j = 0; j < networkKeys.length; j++) {
const network = networkKeys[j];
if (network.indexOf('_video') > -1) { queryParamsAndValues.push('tt=' + DEFAULT_VAST_VERSION) }
const requestURL = gdprApplies ? ENDPOINT_URL_EUROPE : ENDPOINT_URL
requests.push({
method: 'POST',
Expand All @@ -321,7 +344,7 @@ export const spec = {
if (serverResponse.body.metaData) {
storageTool.saveToStorage(serverResponse.body.metaData, serverResponse.body.network);
}
const adUnits = serverResponse.body.adUnits;
const responseAdUnits = serverResponse.body.adUnits;

let validatedBidType = validateBidType(config.getConfig().bidType);
if (bidRequest.bid) {
Expand Down Expand Up @@ -367,14 +390,43 @@ export const spec = {
return adResponse;
}

const highestYieldingAdUnits = [];
if (responseAdUnits.length === 1) {
highestYieldingAdUnits.push(responseAdUnits[0]);
} else if (responseAdUnits.length > 1) {
bidRequest.bid.forEach((resp) => {
const multiFormatAdUnits = [];
SUPPORTED_MEDIA_TYPES.forEach((mediaType) => {
const suffix = mediaType === BANNER ? '' : '-' + mediaType;
const targetId = (resp?.params?.targetId || resp.bidId) + suffix;

const au = responseAdUnits.find((rAu) => {
return rAu.targetId === targetId && rAu.matchedAdCount > 0;
});
if (au) {
multiFormatAdUnits.push(au);
}
});
if (multiFormatAdUnits.length > 0) {
const highestYield = multiFormatAdUnits.length === 1 ? multiFormatAdUnits[0] : multiFormatAdUnits.reduce((highest, cur) => {
const highestBid = misc.findHighestPrice(highest.ads, validatedBidType)[validatedBidType];
const curBid = misc.findHighestPrice(cur.ads, validatedBidType)[validatedBidType];
return curBid.currency === highestBid.currency && curBid.amount > highestBid.amount ? cur : highest;
}, multiFormatAdUnits[0]);
highestYield.targetId = resp.bidId;
highestYieldingAdUnits.push(highestYield);
}
});
}

const bidsById = bidRequest.bid.reduce((response, bid) => {
return {
...response,
[bid.bidId]: bid
};
}, {});

const hasBidAdUnits = adUnits.filter((au) => {
const hasBidAdUnits = highestYieldingAdUnits.filter((au) => {
const bid = bidsById[au.targetId];
if (bid && bid.bidder && BIDDER_CODE_DEAL_ALIASES.indexOf(bid.bidder) < 0) {
return au.matchedAdCount > 0;
Expand All @@ -384,7 +436,7 @@ export const spec = {
return false;
}
});
const hasDealsAdUnits = adUnits.filter((au) => {
const hasDealsAdUnits = highestYieldingAdUnits.filter((au) => {
return au.deals && au.deals.length > 0;
});

Expand Down
Loading

0 comments on commit fb5dddd

Please sign in to comment.