-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Permutive RTD Module: add support for new ssp standard cohorts #9236
Changes from all commits
cf827a0
6f4cb68
841c6e0
7232ac0
35edee7
29bfb83
2624db6
3870d14
4bf276c
3127502
6221511
f8b073c
b1a4564
7108de1
f6d9b4e
e36c43d
24e5cf4
891bb68
adb1de9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import {includes} from '../src/polyfill.js'; | |
const MODULE_NAME = 'permutive' | ||
|
||
export const PERMUTIVE_SUBMODULE_CONFIG_KEY = 'permutive-prebid-rtd' | ||
export const PERMUTIVE_STANDARD_AUD_KEYWORD = 'p_standard_aud' | ||
|
||
export const storage = getStorageManager({gvlid: null, moduleName: MODULE_NAME}) | ||
|
||
|
@@ -118,9 +119,21 @@ export function setBidderRtb (bidderOrtb2, customModuleConfig) { | |
const transformationConfigs = deepAccess(moduleConfig, 'params.transformations') || [] | ||
const segmentData = getSegments(maxSegs) | ||
|
||
acBidders.forEach(function (bidder) { | ||
const ssps = segmentData?.ssp?.ssps ?? [] | ||
const sspCohorts = segmentData?.ssp?.cohorts ?? [] | ||
|
||
const bidders = new Set([...acBidders, ...ssps]) | ||
bidders.forEach(function (bidder) { | ||
const currConfig = { ortb2: bidderOrtb2[bidder] || {} } | ||
const nextConfig = updateOrtbConfig(currConfig, segmentData.ac, transformationConfigs) // ORTB2 uses the `ac` segment IDs | ||
|
||
const isAcBidder = acBidders.indexOf(bidder) > -1 | ||
const isSspBidder = ssps.indexOf(bidder) > -1 | ||
|
||
let cohorts = [] | ||
if (isAcBidder) cohorts = segmentData.ac | ||
if (isSspBidder) cohorts = [...new Set([...cohorts, ...sspCohorts])].slice(0, maxSegs) | ||
|
||
const nextConfig = updateOrtbConfig(currConfig, cohorts, sspCohorts, transformationConfigs) | ||
bidderOrtb2[bidder] = nextConfig.ortb2; | ||
}) | ||
} | ||
|
@@ -131,9 +144,10 @@ export function setBidderRtb (bidderOrtb2, customModuleConfig) { | |
* @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 | ||
* @return {Object} Merged ortb2 object | ||
*/ | ||
function updateOrtbConfig (currConfig, segmentIDs, transformationConfigs) { | ||
function updateOrtbConfig (currConfig, segmentIDs, sspSegmentIDs, transformationConfigs) { | ||
const name = 'permutive.com' | ||
|
||
const permutiveUserData = { | ||
|
@@ -154,6 +168,12 @@ function updateOrtbConfig (currConfig, segmentIDs, transformationConfigs) { | |
|
||
deepSetValue(ortbConfig, 'ortb2.user.data', updatedUserData) | ||
|
||
// As of writing this, only used for AppNexus/Xandr in place of appnexusAuctionKeywords in config | ||
const currentUserKeywords = deepAccess(ortbConfig, 'ortb2.user.keywords') || '' | ||
const keywords = sspSegmentIDs.map(segment => `${PERMUTIVE_STANDARD_AUD_KEYWORD}=${segment}`).join(',') | ||
const updatedUserKeywords = (currentUserKeywords === '') ? keywords : `${currentUserKeywords},${keywords}` | ||
deepSetValue(ortbConfig, 'ortb2.user.keywords', updatedUserKeywords) | ||
|
||
return ortbConfig | ||
} | ||
|
||
|
@@ -222,10 +242,19 @@ function getCustomBidderFn (moduleConfig, bidder) { | |
* @return {Object} Bidder function | ||
*/ | ||
function getDefaultBidderFn (bidder) { | ||
const isPStandardTargetingEnabled = (data, acEnabled) => { | ||
return (acEnabled && data.ac && data.ac.length) || (data.ssp && data.ssp.cohorts.length) | ||
} | ||
const pStandardTargeting = (data, acEnabled) => { | ||
const ac = (acEnabled) ? (data.ac ?? []) : [] | ||
const ssp = data?.ssp?.cohorts ?? [] | ||
return [...new Set([...ac, ...ssp])] | ||
} | ||
const bidderMap = { | ||
appnexus: function (bid, data, acEnabled) { | ||
if (acEnabled && data.ac && data.ac.length) { | ||
deepSetValue(bid, 'params.keywords.p_standard', data.ac) | ||
if (isPStandardTargetingEnabled(data, acEnabled)) { | ||
const segments = pStandardTargeting(data, acEnabled) | ||
deepSetValue(bid, 'params.keywords.p_standard', segments) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you guys should consider yourself on notice to remove these special handlings, move them into their respective bid adapters, expect someone else moves them for you or simply deletes them, or expect not to be in the next version of prebid if the deletion or move proves challenging. In other words, if you don't take care of this yourselves soon, it may be especially disruptive to your business in q2. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi Patrick, thanks for the feedback. I'm already working on removing the appnexus special handling, I just wanted to do it as a separate PR in order to simplify reviewing. For the other SSPs for which we have special handling - we're looking into them. I don't have the full context myself, but I understand it's not as simple as migrating to the Regardless, thanks for the heads-up that this method will stop working soon - we'll prioritise updating this to avoid any issues. |
||
} | ||
if (data.appnexus && data.appnexus.length) { | ||
deepSetValue(bid, 'params.keywords.permutive', data.appnexus) | ||
|
@@ -234,19 +263,20 @@ function getDefaultBidderFn (bidder) { | |
return bid | ||
}, | ||
rubicon: function (bid, data, acEnabled) { | ||
if (acEnabled && data.ac && data.ac.length) { | ||
deepSetValue(bid, 'params.visitor.p_standard', data.ac) | ||
if (isPStandardTargetingEnabled(data, acEnabled)) { | ||
const segments = pStandardTargeting(data, acEnabled) | ||
deepSetValue(bid, 'params.visitor.p_standard', segments) | ||
} | ||
if (data.rubicon && data.rubicon.length) { | ||
const rubiconCohorts = deepAccess(bid, 'params.video') ? data.rubicon.map(String) : data.rubicon | ||
deepSetValue(bid, 'params.visitor.permutive', rubiconCohorts) | ||
deepSetValue(bid, 'params.visitor.permutive', data.rubicon.map(String)) | ||
} | ||
|
||
return bid | ||
}, | ||
ozone: function (bid, data, acEnabled) { | ||
if (acEnabled && data.ac && data.ac.length) { | ||
deepSetValue(bid, 'params.customData.0.targeting.p_standard', data.ac) | ||
if (isPStandardTargetingEnabled(data, acEnabled)) { | ||
const segments = pStandardTargeting(data, acEnabled) | ||
deepSetValue(bid, 'params.customData.0.targeting.p_standard', segments) | ||
} | ||
|
||
return bid | ||
|
@@ -290,10 +320,17 @@ export function getSegments (maxSegs) { | |
rubicon: readSegments('_prubicons'), | ||
appnexus: readSegments('_papns'), | ||
gam: readSegments('_pdfps'), | ||
ssp: readSegments('_pssps'), | ||
} | ||
|
||
for (const bidder in segments) { | ||
segments[bidder] = segments[bidder].slice(0, maxSegs) | ||
if (bidder === 'ssp') { | ||
if (segments[bidder].cohorts && Array.isArray(segments[bidder].cohorts)) { | ||
segments[bidder].cohorts = segments[bidder].cohorts.slice(0, maxSegs) | ||
} | ||
} else { | ||
segments[bidder] = segments[bidder].slice(0, maxSegs) | ||
} | ||
} | ||
|
||
return segments | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zshnr Hello!
I am seeing
data.ssp.cohorts
come back asundefined
in some cases for our publishers prebid wrappers.Here is an example:
This causes an exception to be thrown and the permutive
makeSafe
function catches it but probably does not do all of the necessary stuff!So probably just need to add a safe check here for making sure
cohorts
is defined before accessinglength
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like it is okay on the publisher site when the Perutive endpoint comes back with an actual data resonse:
So probably not a huge deal, but just in case might be a good idea to add a safe check!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah that is bizzare 🤔 . I was sure if the
ssp
property exists then it will have acohorts
property even if its empty.Thanks for flagging I'll check internally. @robertrmartinez
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @robertrmartinez , I have merged a fix for this :)
To help us understand the impact of this, can you let me know which publisher websites you saw this on?
Thanks!