Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ozone Bid Adapter: add support for GPP Module & updates #11648

Merged
merged 4 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 118 additions & 59 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 @@ -764,7 +825,7 @@ export const spec = {
return ret;
},
_unpackVideoConfigIntoIABformat(ret, objConfig) {
let arrVideoKeysAllowed = ['mimes', 'minduration', 'maxduration', 'protocols', 'w', 'h', 'startdelay', 'placement', 'plcmt', 'linearity', 'skip', 'skipmin', 'skipafter', 'sequence', 'battr', 'maxextended', 'minbitrate', 'maxbitrate', 'boxingallowed', 'playbackmethod', 'playbackend', 'delivery', 'pos', 'companionad', 'api', 'companiontype'];
let arrVideoKeysAllowed = ['mimes', 'minduration', 'maxduration', 'protocols', 'w', 'h', 'startdelay', 'placement', 'linearity', 'skip', 'skipmin', 'skipafter', 'sequence', 'battr', 'maxextended', 'minbitrate', 'maxbitrate', 'boxingallowed', 'playbackmethod', 'playbackend', 'delivery', 'pos', 'companionad', 'api', 'companiontype'];
AskRupert-DM marked this conversation as resolved.
Show resolved Hide resolved
for (const key in objConfig) {
var found = false;
arrVideoKeysAllowed.forEach(function(arg) {
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