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

Sirdata RTD Module : bidder specific handling removal #9970

Merged
merged 4 commits into from
Jun 6, 2023
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
107 changes: 38 additions & 69 deletions modules/sirdataRtdProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export function applyBidderOrtb2Sda(ortb2Fragments, bidder, type, segments, segt

export function setBidderOrtb2(bidderOrtb2Fragments, bidder, path, segments) {
try {
if (isEmpty(segments)) { return; }
if (isEmpty(segments)) { return false; }
let ortb2Conf = {};
deepSetValue(ortb2Conf, path, segments || {});
mergeDeep(bidderOrtb2Fragments, {[bidder]: ortb2Conf});
Expand Down Expand Up @@ -254,7 +254,7 @@ export function getSegAndCatsArray(data, minScore, pid) {
return sirdataData;
}

export function applySdaGetSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit) {
export function applySdaGetSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit) {
// only share SDA data if whitelisted
if (!biddersParamsExist || indexFound) {
// SDA Publisher
Expand All @@ -269,7 +269,8 @@ export function applySdaGetSpecificData(data, sirdataList, biddersParamsExist, m
if (data.shared_taxonomy && data.shared_taxonomy[curationId]) {
// Get Bidder Specific Data
let curationData = getSegAndCatsArray(data.shared_taxonomy[curationId], minScore, null);
sirdataList = sirdataList.concat(curationData.segments).concat(curationData.categories);
sirdataData.segments = sirdataData.segments.concat(curationData.segments);
sirdataData.categories = sirdataData.categories.concat(curationData.categories);

// SDA Partners
let curationDataForSDA = getSegAndCatsArray(data.shared_taxonomy[curationId], minScore, curationId);
Expand All @@ -278,19 +279,22 @@ export function applySdaGetSpecificData(data, sirdataList, biddersParamsExist, m
}

// Apply custom function or return Bidder Specific Data if publisher is ok
if (sirdataList && sirdataList.length > 0 && (!biddersParamsExist || indexFound)) {
if (!biddersParamsExist || indexFound) {
if (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('customFunction')) {
return loadCustomFunction(moduleConfig.params.bidders[bidderIndex].customFunction, adUnit, sirdataList, data, bid);
return loadCustomFunction(moduleConfig.params.bidders[bidderIndex].customFunction, adUnit, sirdataData, data, bid);
} else {
return sirdataList;
return sirdataData;
}
}
}

export function applySdaAndDefaultSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit) {
let specificData = applySdaGetSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
if (specificData && specificData.length > 0) {
setBidderOrtb2(reqBids.ortb2Fragments?.bidder, bid.bidder, 'user.ext.data', {sd_rtd: specificData});
export function applySdaAndDefaultSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit) {
sirdataData = applySdaGetSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
if (sirdataData.segments && sirdataData.segments.length > 0) {
setBidderOrtb2(reqBids.ortb2Fragments?.bidder, bid.bidder, 'user.ext.data', {sd_rtd: sirdataData.segments});
}
if (sirdataData.categories && sirdataData.categories.length > 0) {
setBidderOrtb2(reqBids.ortb2Fragments?.bidder, bid.bidder, 'site.ext.data', {sd_rtd: sirdataData.categories});
}
}

Expand All @@ -301,8 +305,6 @@ export function addSegmentData(reqBids, data, moduleConfig, onDone) {
const globalMinScore = moduleConfig.params.hasOwnProperty('contextualMinRelevancyScore') ? moduleConfig.params.contextualMinRelevancyScore : 30;
var sirdataData = getSegAndCatsArray(data, globalMinScore, null);

const sirdataList = sirdataData.segments.concat(sirdataData.categories);

const biddersParamsExist = (!!(moduleConfig.params && moduleConfig.params.bidders));

// Global ortb2 SDA
Expand All @@ -320,15 +322,17 @@ export function addSegmentData(reqBids, data, moduleConfig, onDone) {
if (typeof window.googletag !== 'undefined' && (moduleConfig.params.setGptKeyValues || !moduleConfig.params.hasOwnProperty('setGptKeyValues'))) {
try {
let gptCurationId = (moduleConfig.params.gptCurationId ? moduleConfig.params.gptCurationId : (partnerIds['sdRtdForGpt'] ? partnerIds['sdRtdForGpt'] : null));
let sirdataMergedList = sirdataList;
let sirdataMergedList = sirdataData.segments.concat(sirdataData.categories);
if (gptCurationId && data.shared_taxonomy && data.shared_taxonomy[gptCurationId]) {
let gamCurationData = getSegAndCatsArray(data.shared_taxonomy[gptCurationId], globalMinScore, null);
sirdataMergedList = sirdataMergedList.concat(gamCurationData.segments).concat(gamCurationData.categories);
}
window.googletag.pubads().getSlots().forEach(function (n) {
if (typeof n.setTargeting !== 'undefined' && sirdataMergedList && sirdataMergedList.length > 0) {
n.setTargeting('sd_rtd', sirdataMergedList);
}
window.googletag.cmd.push(function() {
window.googletag.pubads().getSlots().forEach(function (n) {
if (typeof n.setTargeting !== 'undefined' && sirdataMergedList && sirdataMergedList.length > 0) {
n.setTargeting('sd_rtd', sirdataMergedList);
}
});
});
} catch (e) {
logError(e);
Expand All @@ -340,18 +344,13 @@ export function addSegmentData(reqBids, data, moduleConfig, onDone) {
var indexFound = false;

adUnits.forEach(adUnit => {
if (!biddersParamsExist && !deepAccess(adUnit, 'ortb2Imp.ext.data.sd_rtd')) {
deepSetValue(adUnit, 'ortb2Imp.ext.data.sd_rtd', sirdataList);
}

adUnit.hasOwnProperty('bids') && adUnit.bids.forEach(bid => {
bidderIndex = (moduleConfig.params.hasOwnProperty('bidders') ? findIndex(moduleConfig.params.bidders, function (i) {
return i.bidder === bid.bidder;
}) : false);
indexFound = (!!(typeof bidderIndex == 'number' && bidderIndex >= 0));
try {
let minScore = (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('contextualMinRelevancyScore') ? moduleConfig.params.bidders[bidderIndex].contextualMinRelevancyScore : globalMinScore);
let specificData = null;

switch (bid.bidder) {
case 'appnexus':
Expand All @@ -370,57 +369,24 @@ export function addSegmentData(reqBids, data, moduleConfig, onDone) {
case 'msq_classic':
case 'msq_max':
case '366_apx':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm missing some context, if the intent of this is to remove bidder-specific handling why is there a giant switch statement for a bunch of bidders?

specificData = applySdaGetSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
if (specificData && specificData.length > 0) {
deepSetValue(bid, 'params.keywords.sd_rtd', specificData);
sirdataData = applySdaGetSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
if (sirdataData.segments && sirdataData.segments.length > 0) {
setBidderOrtb2(reqBids.ortb2Fragments?.bidder, bid.bidder, 'user.keywords', 'sd_rtd=' + sirdataData.segments.join(',sd_rtd='));
}
break;

case 'smartadserver':
case 'smart':
specificData = applySdaGetSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
if (specificData && specificData.length > 0) {
var target = [];
if (bid.hasOwnProperty('params') && bid.params.hasOwnProperty('target')) {
target.push(bid.params.target);
}
specificData.forEach(function (entry) {
if (target.indexOf('sd_rtd=' + entry) === -1) {
target.push('sd_rtd=' + entry);
}
});
deepSetValue(bid, 'params.target', target.join(';'));
}
break;

case 'ix':
specificData = applySdaGetSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
let ixConfig = config.getConfig('ix.firstPartyData.sd_rtd');
if (!ixConfig && specificData && specificData.length > 0) {
let cappIxCategories = [];
let ixLength = 0;
let ixLimit = (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('sizeLimit') ? moduleConfig.params.bidders[bidderIndex].sizeLimit : 1000);
// Push ids For publisher use and for curation if exists but limit size because the bidder uses GET parameters
specificData.forEach(function (entry) {
if (ixLength < ixLimit) {
cappIxCategories.push(entry);
ixLength += entry.toString().length;
}
});
config.setConfig({ix: {firstPartyData: {sd_rtd: cappIxCategories}}});
if (sirdataData.categories && sirdataData.categories.length > 0) {
setBidderOrtb2(reqBids.ortb2Fragments?.bidder, bid.bidder, 'site.content.keywords', 'sd_rtd=' + sirdataData.categories.join(',sd_rtd='));
}
break;

case 'proxistore':
specificData = applySdaGetSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
if (specificData && specificData.length > 0) {
let psCurationId = (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('curationId') ? moduleConfig.params.bidders[bidderIndex].curationId : (partnerIds[bid.bidder] ? partnerIds[bid.bidder] : null));
if (!data.shared_taxonomy || !data.shared_taxonomy[psCurationId]) {
data.shared_taxonomy[psCurationId] = {segments: [], contextual_categories: {}, segtaxid: null, cattaxid: null};
}
let psCurationData = getSegAndCatsArray(data.shared_taxonomy[psCurationId], minScore, null);
sirdataData = applySdaGetSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
let psCurationId = (indexFound && moduleConfig.params.bidders[bidderIndex].hasOwnProperty('curationId') ? moduleConfig.params.bidders[bidderIndex].curationId : (partnerIds[bid.bidder] ? partnerIds[bid.bidder] : null));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you move this logic into the proxistore adapter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done :)

if (!data.shared_taxonomy || !data.shared_taxonomy[psCurationId]) {
data.shared_taxonomy[psCurationId] = {segments: [], contextual_categories: {}, segtaxid: null, cattaxid: null};
}
if ((sirdataData.segments && sirdataData.segments.length > 0) || (sirdataData.categories && sirdataData.categories.length > 0)) {
setBidderOrtb2(reqBids.ortb2Fragments?.bidder, bid.bidder, 'user.ext.data', {
segments: sirdataData.segments.concat(psCurationData.segments),
segments: sirdataData.segments,
contextual_categories: {...data.contextual_categories, ...data.shared_taxonomy[psCurationId].contextual_categories}
});
}
Expand All @@ -445,12 +411,15 @@ export function addSegmentData(reqBids, data, moduleConfig, onDone) {
case 'sublime':
case 'rtbhouse':
case 'mediasquare':
applySdaAndDefaultSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
case 'smartadserver':
case 'smart':
case 'ix':
applySdaAndDefaultSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
break;

default:
if (!biddersParamsExist || (indexFound && (!moduleConfig.params.bidders[bidderIndex].hasOwnProperty('adUnitCodes') || moduleConfig.params.bidders[bidderIndex].adUnitCodes.indexOf(adUnit.code) !== -1))) {
applySdaAndDefaultSpecificData(data, sirdataList, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
applySdaAndDefaultSpecificData(data, sirdataData, biddersParamsExist, minScore, reqBids, bid, moduleConfig, indexFound, bidderIndex, adUnit);
}
}
} catch (e) {
Expand Down
127 changes: 110 additions & 17 deletions test/spec/modules/sirdataRtdProvider_spec.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import {addSegmentData, getSegmentsAndCategories, sirdataSubmodule} from 'modules/sirdataRtdProvider.js';
import {addSegmentData, getSegmentsAndCategories, sirdataSubmodule, setBidderOrtb2} from 'modules/sirdataRtdProvider.js';
import {server} from 'test/mocks/xhr.js';

const responseHeader = {'Content-Type': 'application/json'};

describe('sirdataRtdProvider', function () {
describe('sirdataSubmodule', function () {
it('exists', function () {
expect(sirdataSubmodule.init).to.be.a('function');
});
it('successfully instantiates', function () {
expect(sirdataSubmodule.init()).to.equal(true);
});
it('has the correct module name', function () {
expect(sirdataSubmodule.name).to.equal('SirdataRTDModule');
});
});

describe('Add Segment Data', function () {
it('adds segment data', function () {
const config = {
const firstConfig = {
params: {
setGptKeyValues: false,
partnerId: 1,
key: 1,
setGptKeyValues: true,
gptCurationId: 27449,
contextualMinRelevancyScore: 50,
bidders: [{
bidder: 'appnexus'
}, {
bidder: 'other'
}]
bidders: []
}
};

Expand All @@ -37,21 +42,47 @@ describe('sirdataRtdProvider', function () {
}
];

let data = {
let firstReqBidsConfigObj = {
adUnits: adUnits,
ortb2Fragments: {
global: {}
}
};

let firstData = {
segments: [111111, 222222],
contextual_categories: {'333333': 100}
contextual_categories: {'333333': 100},
'segtaxid': null,
'cattaxid': null,
'shared_taxonomy': {
'27449': {
'segments': [444444, 555555],
'segtaxid': null,
'cattaxid': null,
'contextual_categories': {'666666': 100}
}
},
'global_taxonomy': {
'9998': {
'segments': [123, 234],
'segtaxid': 4,
'cattaxid': 7,
'contextual_categories': {'345': 100, '456': 100}
}
}
};

addSegmentData({adUnits}, data, config, () => {
addSegmentData(firstReqBidsConfigObj, firstData, firstConfig, () => {
});
expect(adUnits[0].bids[0].params.keywords).to.have.deep.property('sd_rtd', ['111111', '222222', '333333']);

expect(firstReqBidsConfigObj.ortb2Fragments.global.user.data[0].ext.segtax).to.equal(4);
});
});

describe('Get Segments And Categories', function () {
it('gets data from async request and adds segment data', function () {
const overrideAppnexus = function (adUnit, list, data, bid) {
deepSetValue(bid, 'params.keywords.custom', list);
deepSetValue(bid, 'params.keywords.custom', list.segments.concat(list.categories));
}

const config = {
Expand All @@ -60,16 +91,21 @@ describe('sirdataRtdProvider', function () {
contextualMinRelevancyScore: 50,
bidders: [{
bidder: 'appnexus',
customFunction: overrideAppnexus
customFunction: overrideAppnexus,
curationId: 27446
}, {
bidder: 'smartadserver'
bidder: 'smartadserver',
curationId: 27440
}, {
bidder: 'ix',
sizeLimit: 1200,
curationId: 27248
}, {
bidder: 'rubicon',
curationId: 27452
}, {
bidder: 'proxistore',
curationId: 27484
}]
}
};
Expand Down Expand Up @@ -146,6 +182,12 @@ describe('sirdataRtdProvider', function () {
'segtaxid': 552,
'cattaxid': 553,
'contextual_categories': {'666666': 100}
},
'27446': {
'segments': [777777, 888888],
'segtaxid': 552,
'cattaxid': 553,
'contextual_categories': {'999999': 100}
}
},
'global_taxonomy': {
Expand All @@ -164,8 +206,6 @@ describe('sirdataRtdProvider', function () {
let request = server.requests[0];
request.respond(200, responseHeader, JSON.stringify(data));

expect(reqBidsConfigObj.adUnits[0].bids[1].params).to.have.deep.property('target', 'sd_rtd=111111;sd_rtd=222222;sd_rtd=333333;sd_rtd=444444;sd_rtd=555555;sd_rtd=666666');

expect(reqBidsConfigObj.ortb2Fragments.global.site.content.data[0].name).to.equal(
'sirdata.com'
);
Expand All @@ -185,4 +225,57 @@ describe('sirdataRtdProvider', function () {
expect(reqBidsConfigObj.ortb2Fragments.global.user.data[0].ext.segtax).to.equal(4);
});
});

describe('Set ortb2 for bidder', function () {
it('set ortb2 for a givent bidder', function () {
const config = {
params: {
setGptKeyValues: false,
contextualMinRelevancyScore: 50,
bidders: [{
bidder: 'appnexus',
}]
}
};

let reqBidsConfigObj = {
adUnits: [{
bids: [{
bidder: 'appnexus',
params: {
placementId: 13144370
}
}]
}],
ortb2Fragments: {
global: {}
}
};

let data = {
'segments': [111111, 222222],
'segtaxid': null,
'cattaxid': null,
'contextual_categories': {'333333': 100},
'shared_taxonomy': {
'27440': {
'segments': [444444, 555555],
'segtaxid': null,
'cattaxid': null,
'contextual_categories': {'666666': 100}
}
},
'global_taxonomy': {}
};

window.googletag = window.googletag || {};
window.googletag.cmd = window.googletag.cmd || [];

let test = setBidderOrtb2(reqBidsConfigObj.ortb2Fragments, 'appnexus', 'user', []);
expect(test).to.be.false;

test = setBidderOrtb2(reqBidsConfigObj.ortb2Fragments, 'appnexus', 'user', ['1']);
expect(test).to.be.true;
});
});
});