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

permutiveRtd : transform integers to strings #11910

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
94 changes: 72 additions & 22 deletions modules/permutiveRtdProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ export function getModuleConfig(customModuleConfig) {
/**
* Sets ortb2 config for ac bidders
* @param {Object} bidderOrtb2 - The ortb2 object for the all bidders
* @param {Object} customModuleConfig - Publisher config for module
* @param {Object} moduleConfig - Publisher config for module
* @param {Object} segmentData - Segment data grouped by bidder or type
*/
export function setBidderRtb (bidderOrtb2, moduleConfig, segmentData) {
const acBidders = deepAccess(moduleConfig, 'params.acBidders')
Expand Down Expand Up @@ -129,13 +130,13 @@ export function setBidderRtb (bidderOrtb2, moduleConfig, segmentData) {

/**
* Updates `user.data` object in existing bidder config with Permutive segments
* @param string bidder - The bidder
* @param {string} bidder - The bidder identifier
* @param {Object} currConfig - Current bidder config
* @param {Object[]} transformationConfigs - array of objects with `id` and `config` properties, used to determine
* the transformations on user data to include the ORTB2 object
* @param {string[]} segmentIDs - Permutive segment IDs
* @param {string[]} sspSegmentIDs - Permutive SSP segment IDs
* @param {Object} topics - Privacy Sandbox Topics, keyed by IAB taxonomy version (600, 601, etc.)
* @param {Object[]} transformationConfigs - array of objects with `id` and `config` properties, used to determine
* the transformations on user data to include the ORTB2 object
* @param {Object} segmentData - The segments available for targeting
* @return {Object} Merged ortb2 object
*/
Expand Down Expand Up @@ -270,7 +271,7 @@ function setSegments (reqBidsConfigObj, moduleConfig, segmentData) {
*/
function makeSafe (fn) {
try {
fn()
return fn()
} catch (e) {
logError(e)
}
Expand Down Expand Up @@ -310,23 +311,71 @@ export function isPermutiveOnPage () {
* @param {number} maxSegs - Maximum number of segments to be included
* @return {Object}
*/
export function getSegments (maxSegs) {
const legacySegs = readSegments('_psegs', []).map(Number).filter(seg => seg >= 1000000).map(String)
const _ppam = readSegments('_ppam', [])
const _pcrprs = readSegments('_pcrprs', [])

export function getSegments(maxSegs) {
const segments = {
ac: [..._pcrprs, ..._ppam, ...legacySegs],
ix: readSegments('_pindexs', []),
rubicon: readSegments('_prubicons', []),
appnexus: readSegments('_papns', []),
gam: readSegments('_pdfps', []),
ssp: readSegments('_pssps', {
cohorts: [],
ssps: []
ac:
makeSafe(() => {
const legacySegs =
makeSafe(() =>
readSegments('_psegs', [])
.map(Number)
.filter((seg) => seg >= 1000000)
.map(String),
) || [];
const _ppam = makeSafe(() => readSegments('_ppam', []).map(String)) || [];
const _pcrprs = makeSafe(() => readSegments('_pcrprs', []).map(String)) || [];

return [..._pcrprs, ..._ppam, ...legacySegs];
}) || [],

ix:
makeSafe(() => {
const _pindexs = readSegments('_pindexs', []);
return _pindexs.map(String);
}) || [],

rubicon:
makeSafe(() => {
const _prubicons = readSegments('_prubicons', []);
return _prubicons.map(String);
}) || [],

appnexus:
makeSafe(() => {
const _papns = readSegments('_papns', []);
return _papns.map(String);
}) || [],

gam:
makeSafe(() => {
const _pdfps = readSegments('_pdfps', []);
return _pdfps.map(String);
}) || [],

ssp: makeSafe(() => {
const _pssps = readSegments('_pssps', {
cohorts: [],
ssps: [],
});

return {
cohorts: makeSafe(() => _pssps.cohorts.map(String)) || [],
ssps: makeSafe(() => _pssps.ssps.map(String)) || [],
};
}),
topics: readSegments('_ppsts', {}),
}

topics:
makeSafe(() => {
const _ppsts = readSegments('_ppsts', {});

const topics = {};
for (const [k, value] of Object.entries(_ppsts)) {
topics[k] = makeSafe(() => value.map(String)) || [];
}

return topics;
}) || {},
};

for (const bidder in segments) {
if (bidder === 'ssp') {
Expand All @@ -342,7 +391,8 @@ export function getSegments (maxSegs) {
}
}

return segments
logger.logInfo(`Read segments`, segments)
return segments;
}

/**
Expand Down Expand Up @@ -393,7 +443,7 @@ function iabSegmentId(permutiveSegmentId, iabIds) {
* Pull the latest configuration and cohort information and update accordingly.
*
* @param reqBidsConfigObj - Bidder provided config for request
* @param customModuleConfig - Publisher provide config
* @param moduleConfig - Publisher provided config
*/
export function readAndSetCohorts(reqBidsConfigObj, moduleConfig) {
const segmentData = getSegments(deepAccess(moduleConfig, 'params.maxSegs'))
Expand Down
50 changes: 42 additions & 8 deletions test/spec/modules/permutiveRtdProvider_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,9 @@ describe('permutiveRtdProvider', function () {
_psegs: [],
_ppam: [],
_pcrprs: [],
_pssps: { ssps: [], cohorts: [] }
_pindexs: [],
_pssps: { ssps: [], cohorts: [] },
_ppsts: {},
})

setBidderRtb(bidderConfig, moduleConfig, segmentsData)
Expand Down Expand Up @@ -568,6 +570,7 @@ describe('permutiveRtdProvider', function () {
const data = transformedTargeting()
expect(getSegments(250)).to.deep.equal(data)
})

it('should enforce max segments', function () {
const max = 1
const segments = getSegments(max)
Expand All @@ -584,6 +587,26 @@ describe('permutiveRtdProvider', function () {
}
}
})

it('should coerce numbers to strings', function () {
setLocalStorage({ _prubicons: [1, 2, 3], _pssps: { ssps: ['foo', 'bar'], cohorts: [4, 5, 6] } })

const segments = getSegments(200)

expect(segments.rubicon).to.deep.equal(['1', '2', '3'])
expect(segments.ssp.ssps).to.deep.equal(['foo', 'bar'])
expect(segments.ssp.cohorts).to.deep.equal(['4', '5', '6'])
})

it('should return empty values on unexpected format', function () {
setLocalStorage({ _prubicons: 'a string instead?', _pssps: 123 })

const segments = getSegments(200)

expect(segments.rubicon).to.deep.equal([])
expect(segments.ssp.ssps).to.deep.equal([])
expect(segments.ssp.cohorts).to.deep.equal([])
})
})

describe('Existing key-value targeting', function () {
Expand Down Expand Up @@ -703,14 +726,25 @@ function getConfig () {
}

function transformedTargeting (data = getTargetingData()) {
const topics = (() => {
const topics = {}
for (const topic in data._ppsts) {
topics[topic] = data._ppsts[topic].map(String)
}
return topics
})()

return {
ac: [...data._pcrprs, ...data._ppam, ...data._psegs.filter(seg => seg >= 1000000)],
appnexus: data._papns,
ix: data._pindexs,
rubicon: data._prubicons,
gam: data._pdfps,
ssp: data._pssps,
topics: data._ppsts,
ac: [...data._pcrprs, ...data._ppam, ...data._psegs.filter(seg => seg >= 1000000)].map(String),
appnexus: data._papns.map(String),
ix: data._pindexs.map(String),
rubicon: data._prubicons.map(String),
gam: data._pdfps.map(String),
ssp: {
ssps: data._pssps.ssps.map(String),
cohorts: data._pssps.cohorts.map(String)
},
topics,
}
}

Expand Down