diff --git a/modules/permutiveRtdProvider.js b/modules/permutiveRtdProvider.js index a2cd7847564..c11d1c12436 100644 --- a/modules/permutiveRtdProvider.js +++ b/modules/permutiveRtdProvider.js @@ -238,7 +238,8 @@ function getDefaultBidderFn (bidder) { deepSetValue(bid, 'params.visitor.p_standard', data.ac) } if (data.rubicon && data.rubicon.length) { - deepSetValue(bid, 'params.visitor.permutive', data.rubicon) + const rubiconCohorts = deepAccess(bid, 'params.video') ? data.rubicon.map(String) : data.rubicon + deepSetValue(bid, 'params.visitor.permutive', rubiconCohorts) } return bid diff --git a/modules/permutiveRtdProvider.md b/modules/permutiveRtdProvider.md index f99389f82cc..7d8f073357c 100644 --- a/modules/permutiveRtdProvider.md +++ b/modules/permutiveRtdProvider.md @@ -45,17 +45,52 @@ as well as enabling settings for specific use cases mentioned above (e.g. acbidd | params.acBidders | String[] | An array of bidders which should receive AC cohorts. | `[]` | | params.maxSegs | Integer | Maximum number of cohorts to be included in either the `permutive` or `p_standard` key-value. | `500` | | params.transformations | Object[] | An array of configurations for ORTB2 user data transformations | | +| params.overwrites | Object | An object specifying functions for custom targeting logic for bidders. | - | ##### The `transformations` parameter This array contains configurations for transformations we'll apply to the Permutive object in the ORTB2 `user.data` array. The results of these transformations will be appended to the `user.data` array that's attached to ORTB2 bid requests. -##### Supported transformations +###### Supported transformations | Name | ID | Config structure | Description | |----------------|-----|---------------------------------------------------|--------------------------------------------------------------------------------------| | IAB taxonomies | iab | { segtax: number, iabIds: Object} | Transform segment IDs from Permutive to IAB (note: alpha version, subject to change) | +##### The `overwrites` parameter + +The keys for this object should match a bidder (e.g. `rubicon`), which then can define a function to overwrite the customer targeting logic. + +```javascript +{ + params: { + overwrites: { + rubicon: function customTargeting(bid, data, acEnabled, utils, defaultFn) { + if (defaultFn) { + bid = defaultFn(bid, data, acEnabled) + } + if (data.gam && data.gam.length) { + utils.deepSetValue(bid, 'params.visitor.permutive', data.gam) + } + } + } + } +} +``` + +###### `customTargeting` function parameters + +| Name | Description | +|--------------|--------------------------------------------------------------------------------| +| `bid` | The bid request object. | +| `data` | Permutive's targeting data read from localStorage. | +| `acEnabled` | Boolean stating whether Audience Connect is enabled via `acBidders`. | +| `utils` | An object of helpful utilities. `(deepSetValue, deepAccess, isFn, mergeDeep)`. | +| `defaultFn` | The default targeting function. | + + + + #### Context Permutive is not listed as a TCF vendor as all data collection is on behalf of the publisher and based on consent the publisher has received from the user. diff --git a/test/spec/modules/permutiveRtdProvider_spec.js b/test/spec/modules/permutiveRtdProvider_spec.js index 9282ec3ac24..3f104ee1e2e 100644 --- a/test/spec/modules/permutiveRtdProvider_spec.js +++ b/test/spec/modules/permutiveRtdProvider_spec.js @@ -13,13 +13,13 @@ import { deepAccess, deepSetValue, mergeDeep } from '../../../src/utils.js' import { config } from 'src/config.js' describe('permutiveRtdProvider', function () { - before(function () { + beforeEach(function () { const data = getTargetingData() setLocalStorage(data) config.resetConfig() }) - after(function () { + afterEach(function () { const data = getTargetingData() removeLocalStorage(data) config.resetConfig() @@ -317,6 +317,7 @@ describe('permutiveRtdProvider', function () { }) } }) + it('sets segment targeting for Magnite', function () { const data = transformedTargeting() const adUnits = getAdUnits() @@ -337,6 +338,38 @@ describe('permutiveRtdProvider', function () { }) } }) + + it('sets segment targeting for Magnite video', function () { + const targetingData = getTargetingData() + targetingData._prubicons.push(321) + + setLocalStorage(targetingData) + + const data = transformedTargeting(targetingData) + const config = getConfig() + + const adUnits = getAdUnits().filter(adUnit => adUnit.mediaTypes.video) + expect(adUnits).to.have.lengthOf(1) + + initSegments({ adUnits }, callback, config) + + function callback() { + adUnits.forEach(adUnit => { + adUnit.bids.forEach(bid => { + const { bidder, params } = bid + + if (bidder === 'rubicon') { + expect( + deepAccess(params, 'visitor.permutive'), + 'Should map all targeting values to a string', + ).to.eql(data.rubicon.map(String)) + expect(deepAccess(params, 'visitor.p_standard')).to.eql(data.ac) + } + }) + }) + } + }) + it('sets segment targeting for Ozone', function () { const data = transformedTargeting() const adUnits = getAdUnits() @@ -516,9 +549,7 @@ function getConfig () { } } -function transformedTargeting () { - const data = getTargetingData() - +function transformedTargeting (data = getTargetingData()) { return { ac: [...data._pcrprs, ...data._ppam, ...data._psegs.filter(seg => seg >= 1000000)], appnexus: data._papns, @@ -640,6 +671,34 @@ function getAdUnits () { } } ] + }, + { + code: 'myVideoAdUnit', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4', 'video/x-ms-wmv'], + protocols: [2, 3, 5, 6], + api: [2], + maxduration: 30, + linearity: 1 + } + }, + bids: [{ + bidder: 'rubicon', + params: { + accountId: '9840', + siteId: '123564', + zoneId: '583584', + video: { + language: 'en' + }, + visitor: { + test_kv: ['true'] + } + } + }] } ] }