Skip to content

Commit

Permalink
Ozone Bid Adapter: add support for GPP Module & updates (#11648)
Browse files Browse the repository at this point in the history
* Update ozoneBidAdapter.js

* Update ozoneBidAdapter_spec.js

* Update ozoneBidAdapter_spec.js

* Update ozoneBidAdapter.js

fix to address plcmt feedback
  • Loading branch information
AskRupert-DM committed Jun 19, 2024
1 parent 4bf11bd commit eacd24e
Show file tree
Hide file tree
Showing 2 changed files with 309 additions and 80 deletions.
175 changes: 117 additions & 58 deletions modules/ozoneBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
deepClone,
logInfo,
logError,
deepAccess,
Expand All @@ -9,7 +8,7 @@ import {
contains,
mergeDeep,
parseUrl,
generateUUID
generateUUID, isInteger, deepClone
} from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
Expand All @@ -23,7 +22,7 @@ const AUCTIONURI = '/openrtb2/auction';
const OZONECOOKIESYNC = '/static/load-cookie.html';
const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js';
const ORIGIN_DEV = 'https://test.ozpr.net';
const OZONEVERSION = '2.9.1';
const OZONEVERSION = '2.9.2';
export const spec = {
gvlid: 524,
aliases: [{code: 'lmc', gvlid: 524}, {code: 'venatus', gvlid: 524}],
Expand All @@ -39,11 +38,11 @@ export const spec = {
'auctionUrl': ORIGIN + AUCTIONURI,
'cookieSyncUrl': ORIGIN + OZONECOOKIESYNC,
'rendererUrl': OZONE_RENDERER_URL,
'batchRequests': false /* you can change this to true OR override it in the config: config.ozone.batchRequests */
'batchRequests': false /* you can change this to true OR numeric OR override it in the config: config.ozone.batchRequests = true/false/number */
},
loadWhitelabelData(bid) {
if (this.propertyBag.whitelabel) { return; }
this.propertyBag.whitelabel = deepClone(this.whitelabel_defaults);
this.propertyBag.whitelabel = JSON.parse(JSON.stringify(this.whitelabel_defaults));
let bidder = bid.bidder || 'ozone'; // eg. ozone
this.propertyBag.whitelabel.logId = bidder.toUpperCase();
this.propertyBag.whitelabel.bidder = bidder;
Expand Down Expand Up @@ -77,10 +76,22 @@ export const spec = {
}
}
if (bidderConfig.hasOwnProperty('batchRequests')) {
this.propertyBag.whitelabel.batchRequests = bidderConfig.batchRequests;
if (this.batchValueIsValid(bidderConfig.batchRequests)) {
this.propertyBag.whitelabel.batchRequests = bidderConfig.batchRequests;
} else {
logError('bidderConfig.batchRequests must be boolean or a number. Found & ignored data type: ' + typeof bidderConfig.batchRequests);
}
}
if (bidderConfig.hasOwnProperty('videoParams')) {
this.propertyBag.whitelabel.videoParams = bidderConfig.videoParams;
}
if (arr.hasOwnProperty('batchRequests')) {
this.propertyBag.whitelabel.batchRequests = true;
let getBatch = parseInt(arr.batchRequests);
if (this.batchValueIsValid(getBatch)) {
this.propertyBag.whitelabel.batchRequests = getBatch;
} else {
logError('Ignoring query param: batchRequests - this must be a positive number');
}
}
try {
if (arr.hasOwnProperty('auction') && arr.auction === 'dev') {
Expand All @@ -94,6 +105,9 @@ export const spec = {
} catch (e) {}
logInfo('set propertyBag.whitelabel to', this.propertyBag.whitelabel);
},
batchValueIsValid(batch) {
return typeof batch === 'boolean' || (typeof batch === 'number' && batch > 0);
},
getAuctionUrl() {
return this.propertyBag.whitelabel.auctionUrl;
},
Expand All @@ -103,9 +117,17 @@ export const spec = {
getRendererUrl() {
return this.propertyBag.whitelabel.rendererUrl;
},
isBatchRequests() {
logInfo('isBatchRequests going to return ', this.propertyBag.whitelabel.batchRequests);
return this.propertyBag.whitelabel.batchRequests;
getVideoPlacementValue: function(context) {
if (['instream', 'outstream'].indexOf(context) < 0) return null;
return deepAccess(this.propertyBag, `whitelabel.videoParams.${context}`, null);
},
getBatchRequests() {
logInfo('getBatchRequests going to return ', this.propertyBag.whitelabel.batchRequests);
if (this.propertyBag.whitelabel.batchRequests === true) { return 10; }
if (typeof this.propertyBag.whitelabel.batchRequests === 'number' && this.propertyBag.whitelabel.batchRequests > 0) {
return this.propertyBag.whitelabel.batchRequests;
}
return false;
},
isBidRequestValid(bid) {
this.loadWhitelabelData(bid);
Expand Down Expand Up @@ -182,9 +204,10 @@ export const spec = {
if (this.blockTheRequest()) {
return [];
}
let fledgeEnabled = !!bidderRequest.fledgeEnabled; // IF true then this is added as each bid[].ext.ae=1
let htmlParams = {'publisherId': '', 'siteId': ''};
if (validBidRequests.length > 0) {
this.cookieSyncBag.userIdObject = Object.assign(this.cookieSyncBag.userIdObject, this.findAllUserIds(validBidRequests[0]));
this.cookieSyncBag.userIdObject = Object.assign(this.cookieSyncBag.userIdObject, this.findAllUserIdsFromEids(validBidRequests[0]));
this.cookieSyncBag.siteId = deepAccess(validBidRequests[0], 'params.siteId');
this.cookieSyncBag.publisherId = deepAccess(validBidRequests[0], 'params.publisherId');
htmlParams = validBidRequests[0].params;
Expand Down Expand Up @@ -306,6 +329,14 @@ export const spec = {
if (gpid) {
deepSetValue(obj, 'ext.gpid', gpid);
}
if (fledgeEnabled) { // fledge is enabled at some config level - pbjs.setBidderConfig or pbjs.setConfig
const auctionEnvironment = deepAccess(ozoneBidRequest, 'ortb2Imp.ext.ae'); // this will be set for one of 3 reasons; adunit, setBidderConfig, setConfig
if (isInteger(auctionEnvironment)) {
deepSetValue(obj, 'ext.ae', auctionEnvironment);
} else {
logError('ortb2Imp.ext.ae is not an integer - ignoring it for obj.id=' + obj.id);
}
}
return obj;
});
let extObj = {};
Expand All @@ -314,8 +345,8 @@ export const spec = {
extObj[whitelabelBidder][whitelabelPrefix + '_rw'] = placementIdOverrideFromGetParam ? 1 : 0;
if (validBidRequests.length > 0) {
let userIds = this.cookieSyncBag.userIdObject; // 2021-01-06 - slight optimisation - we've already found this info
if (userIds.hasOwnProperty('pubcid')) {
extObj[whitelabelBidder].pubcid = userIds.pubcid;
if (userIds.hasOwnProperty('pubcid.org')) {
extObj[whitelabelBidder].pubcid = userIds['pubcid.org'];
}
}
extObj[whitelabelBidder].pv = this.getPageId(); // attach the page ID that will be common to all auction calls for this page if refresh() is called
Expand Down Expand Up @@ -363,22 +394,37 @@ export const spec = {
} else {
logInfo('WILL NOT ADD USP consent info; no bidderRequest.uspConsent.');
}
if (bidderRequest?.ortb2?.regs?.gpp) {
deepSetValue(ozoneRequest, 'regs.gpp', bidderRequest.ortb2.regs.gpp);
deepSetValue(ozoneRequest, 'regs.gpp_sid', bidderRequest.ortb2.regs.gpp_sid);
}
if (schain) { // we set this while iterating over the bids
logInfo('schain found');
deepSetValue(ozoneRequest, 'source.ext.schain', schain);
}
if (config.getConfig('coppa') === true) {
deepSetValue(ozoneRequest, 'regs.coppa', 1);
}
extObj[whitelabelBidder].cookieDeprecationLabel = deepAccess(bidderRequest, 'ortb2.device.ext.cdep', 'none');
logInfo('cookieDeprecationLabel from bidderRequest object = ' + extObj[whitelabelBidder].cookieDeprecationLabel);
let ozUuid = generateUUID();
if (this.isBatchRequests()) {
let batchRequestsVal = this.getBatchRequests(); // false|numeric
if (typeof batchRequestsVal === 'number') {
logInfo('going to batch the requests');
let arrRet = []; // return an array of objects containing data describing max 10 bids
for (let i = 0; i < tosendtags.length; i += 10) {
ozoneRequest.id = ozUuid; // Unique ID of the bid request, provided by the exchange. (REQUIRED)
ozoneRequest.imp = tosendtags.slice(i, i + 10);
ozoneRequest.ext = extObj;
for (let i = 0; i < tosendtags.length; i += batchRequestsVal) {
if (bidderRequest.auctionId) {
logInfo('Found bidderRequest.auctionId - will pass these values through & not generate our own id');
ozoneRequest.id = bidderRequest.auctionId;
ozoneRequest.auctionId = bidderRequest.auctionId;
deepSetValue(ozoneRequest, 'source.tid', deepAccess(bidderRequest, 'ortb2.source.tid'));
} else {
logInfo('Did not find bidderRequest.auctionId - will generate our own id');
ozoneRequest.id = ozUuid; // Unique ID of the bid request, provided by the exchange. (REQUIRED)
}
deepSetValue(ozoneRequest, 'user.ext.eids', userExtEids);
ozoneRequest.imp = tosendtags.slice(i, i + batchRequestsVal);
ozoneRequest.ext = extObj;
if (ozoneRequest.imp.length > 0) {
arrRet.push({
method: 'POST',
Expand All @@ -394,7 +440,15 @@ export const spec = {
logInfo('requests will not be batched.');
if (singleRequest) {
logInfo('buildRequests starting to generate response for a single request');
ozoneRequest.id = ozUuid; // Unique ID of the bid request, provided by the exchange. (REQUIRED)
if (bidderRequest.auctionId) {
logInfo('Found bidderRequest.auctionId - will pass these values through & not generate our own id');
ozoneRequest.id = bidderRequest.auctionId;
ozoneRequest.auctionId = bidderRequest.auctionId;
deepSetValue(ozoneRequest, 'source.tid', deepAccess(bidderRequest, 'ortb2.source.tid'));
} else {
logInfo('Did not find bidderRequest.auctionId - will generate our own id');
ozoneRequest.id = ozUuid; // Unique ID of the bid request, provided by the exchange. (REQUIRED)
}
ozoneRequest.imp = tosendtags;
ozoneRequest.ext = extObj;
deepSetValue(ozoneRequest, 'user.ext.eids', userExtEids);
Expand Down Expand Up @@ -522,6 +576,7 @@ export const spec = {
adserverTargeting[whitelabelPrefix + '_' + bidderName + '_adv'] = String(allBidsForThisBidid[bidderName].adomain);
adserverTargeting[whitelabelPrefix + '_' + bidderName + '_adId'] = String(allBidsForThisBidid[bidderName].adId);
adserverTargeting[whitelabelPrefix + '_' + bidderName + '_pb_r'] = getRoundedBid(allBidsForThisBidid[bidderName].price, allBidsForThisBidid[bidderName].ext.prebid.type);
adserverTargeting[whitelabelPrefix + '_' + bidderName + '_size'] = String(allBidsForThisBidid[bidderName].width) + 'x' + String(allBidsForThisBidid[bidderName].height);
if (allBidsForThisBidid[bidderName].hasOwnProperty('dealid')) {
adserverTargeting[whitelabelPrefix + '_' + bidderName + '_dealid'] = String(allBidsForThisBidid[bidderName].dealid);
}
Expand Down Expand Up @@ -572,10 +627,28 @@ export const spec = {
arrAllBids.push(thisBid);
}
}
let ret = arrAllBids;
let fledgeAuctionConfigs = deepAccess(serverResponse, 'ext.igi') || []; // 20240606 standardising
if (Array.isArray(fledgeAuctionConfigs) && fledgeAuctionConfigs.length > 0) {
fledgeAuctionConfigs = fledgeAuctionConfigs.filter(config => {
if (!this.isValidAuctionConfig(config)) {
logWarn('Malformed auction config detected:', config);
return false;
}
return true;
});
ret = {
bids: arrAllBids,
fledgeAuctionConfigs,
};
}
let endTime = new Date().getTime();
logInfo(`interpretResponse going to return at time ${endTime} (took ${endTime - startTime}ms) Time from buildRequests Start -> interpretRequests End = ${endTime - this.propertyBag.buildRequestsStart}ms`);
logInfo('interpretResponse arrAllBids (serialised): ', deepClone(arrAllBids)); // this is ok to log because the renderer has not been attached yet
return arrAllBids;
logInfo('interpretResponse arrAllBids (serialised): ', deepClone(ret)); // this is ok to log because the renderer has not been attached yet
return ret;
},
isValidAuctionConfig(config) {
return typeof config === 'object' && config !== null;
},
setBidMediaTypeIfNotExist(thisBid, mediaType) {
if (!thisBid.hasOwnProperty('mediaType')) {
Expand Down Expand Up @@ -614,11 +687,12 @@ export const spec = {
}
return ret;
},
getUserSyncs(optionsType, serverResponse, gdprConsent, usPrivacy) {
getUserSyncs(optionsType, serverResponse, gdprConsent, usPrivacy, gppConsent = {}) {
logInfo('getUserSyncs optionsType', optionsType, 'serverResponse', serverResponse, 'gdprConsent', gdprConsent, 'usPrivacy', usPrivacy, 'cookieSyncBag', this.cookieSyncBag);
if (!serverResponse || serverResponse.length === 0) {
return [];
}
let { gppString = '', applicableSections = [] } = gppConsent;
if (optionsType.iframeEnabled) {
var arrQueryString = [];
if (config.getConfig('debug')) {
Expand All @@ -627,6 +701,10 @@ export const spec = {
arrQueryString.push('gdpr=' + (deepAccess(gdprConsent, 'gdprApplies', false) ? '1' : '0'));
arrQueryString.push('gdpr_consent=' + deepAccess(gdprConsent, 'consentString', ''));
arrQueryString.push('usp_consent=' + (usPrivacy || ''));
arrQueryString.push('gpp=' + gppString);
if (Array.isArray(applicableSections)) {
arrQueryString.push(`gpp_sid=${applicableSections.join()}`);
}
for (let keyname in this.cookieSyncBag.userIdObject) {
arrQueryString.push(keyname + '=' + this.cookieSyncBag.userIdObject[keyname]);
}
Expand Down Expand Up @@ -660,43 +738,26 @@ export const spec = {
}
return null;
},
findAllUserIds(bidRequest) {
var ret = {};
let searchKeysSingle = ['pubcid', 'tdid', 'idl_env', 'criteoId', 'lotamePanoramaId', 'fabrickId'];
if (bidRequest.hasOwnProperty('userId')) {
for (let arrayId in searchKeysSingle) {
let key = searchKeysSingle[arrayId];
if (bidRequest.userId.hasOwnProperty(key)) {
if (typeof (bidRequest.userId[key]) == 'string') {
ret[key] = bidRequest.userId[key];
} else if (typeof (bidRequest.userId[key]) == 'object') {
logError(`WARNING: findAllUserIds had to use first key in user object to get value for bid.userId key: ${key}. Prebid adapter should be updated.`);
ret[key] = bidRequest.userId[key][Object.keys(bidRequest.userId[key])[0]]; // cannot use Object.values
} else {
logError(`failed to get string key value for userId : ${key}`);
}
}
}
let lipbid = deepAccess(bidRequest.userId, 'lipb.lipbid');
if (lipbid) {
ret['lipb'] = {'lipbid': lipbid};
}
let id5id = deepAccess(bidRequest.userId, 'id5id.uid');
if (id5id) {
ret['id5id'] = id5id;
}
let sharedid = deepAccess(bidRequest.userId, 'sharedid.id');
if (sharedid) {
ret['sharedid'] = sharedid;
}
findAllUserIdsFromEids(bidRequest) {
let ret = {};
if (!bidRequest.hasOwnProperty('userIdAsEids')) {
logInfo('findAllUserIdsFromEids - no bidRequest.userIdAsEids object - will quit');
this.tryGetPubCidFromOldLocation(ret, bidRequest); // legacy
return ret;
}
for (let obj of bidRequest.userIdAsEids) {
ret[obj.source] = deepAccess(obj, 'uids.0.id');
}
this.tryGetPubCidFromOldLocation(ret, bidRequest); // legacy
return ret;
},
tryGetPubCidFromOldLocation(ret, bidRequest) {
if (!ret.hasOwnProperty('pubcid')) {
let pubcid = deepAccess(bidRequest, 'crumbs.pubcid');
if (pubcid) {
ret['pubcid'] = pubcid; // if built with old pubCommonId module
ret['pubcid.org'] = pubcid; // if built with old pubCommonId module (use the new eid key)
}
}
return ret;
},
getPlacementId(bidRequest) {
return (bidRequest.params.placementId).toString();
Expand Down Expand Up @@ -792,11 +853,9 @@ export const spec = {
return objRet;
},
_addVideoDefaults(objRet, objConfig, addIfMissing) {
let context = deepAccess(objConfig, 'context');
if (context === 'outstream') {
objRet.placement = 3;
} else if (context === 'instream') {
objRet.placement = 1;
let placementValue = this.getVideoPlacementValue(deepAccess(objConfig, 'context'));
if (placementValue) {
objRet.placement = placementValue;
}
let skippable = deepAccess(objConfig, 'skippable', null);
if (skippable == null) {
Expand Down
Loading

0 comments on commit eacd24e

Please sign in to comment.