Skip to content

Commit

Permalink
Add 'targetingControls.addTargetingKeys' configuration option
Browse files Browse the repository at this point in the history
This adds 'addTargetingKeys' as a config option that means 'allow all default targeting keys, plus these'.

#7249
  • Loading branch information
dgirardi committed Nov 10, 2021
1 parent bd6f395 commit adb6767
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/targeting.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ var pbTargetingKeys = [];
const MAX_DFP_KEYLENGTH = 20;
const TTL_BUFFER = 1000;

const CFG_ALLOW_TARGETING_KEYS = `targetingControls.allowTargetingKeys`;
const CFG_ADD_TARGETING_KEYS = `targetingControls.addTargetingKeys`;
const TARGETING_KEY_CONFIGURATION_ERROR_MSG = `Only one of "${CFG_ALLOW_TARGETING_KEYS}" or "${CFG_ADD_TARGETING_KEYS}" can be set`;

export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map(
key => CONSTANTS.TARGETING_KEYS[key]
);
Expand Down Expand Up @@ -261,7 +265,17 @@ export function newTargeting(auctionManager) {
});

const defaultKeys = Object.keys(Object.assign({}, CONSTANTS.DEFAULT_TARGETING_KEYS, CONSTANTS.NATIVE_KEYS));
const allowedKeys = config.getConfig('targetingControls.allowTargetingKeys') || defaultKeys;
let allowedKeys = config.getConfig(CFG_ALLOW_TARGETING_KEYS);
const addedKeys = config.getConfig(CFG_ADD_TARGETING_KEYS);

if (addedKeys != null && allowedKeys != null) {
throw new Error(TARGETING_KEY_CONFIGURATION_ERROR_MSG);
} else if (addedKeys != null) {
allowedKeys = defaultKeys.concat(addedKeys);
} else {
allowedKeys = allowedKeys || defaultKeys;
}

if (Array.isArray(allowedKeys) && allowedKeys.length > 0) {
targeting = getAllowedTargetingKeyValues(targeting, allowedKeys);
}
Expand All @@ -284,6 +298,13 @@ export function newTargeting(auctionManager) {
return targeting;
};

// warn about conflicting configuration
config.getConfig('targetingControls', function (config) {
if (deepAccess(config, CFG_ALLOW_TARGETING_KEYS) != null && deepAccess(config, CFG_ADD_TARGETING_KEYS) != null) {
logError(TARGETING_KEY_CONFIGURATION_ERROR_MSG);
}
});

// create an encoded string variant based on the keypairs of the provided object
// - note this will encode the characters between the keys (ie = and &)
function convertKeysToQueryForm(keyMap) {
Expand Down
72 changes: 72 additions & 0 deletions test/spec/unit/core/targeting_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createBidReceived } from 'test/fixtures/fixtures.js';
import CONSTANTS from 'src/constants.json';
import { auctionManager } from 'src/auctionManager.js';
import * as utils from 'src/utils.js';
import {deepClone} from 'src/utils.js';

const bid1 = {
'bidderCode': 'rubicon',
Expand Down Expand Up @@ -501,6 +502,77 @@ describe('targeting tests', function () {
});
});

describe('targetingControls.addTargetingKeys', function () {
let winningBid = null;

beforeEach(function () {
bidsReceived = [bid1, bid2, nativeBid1, nativeBid2].map(deepClone);
bidsReceived.forEach((bid) => {
bid.adserverTargeting[CONSTANTS.TARGETING_KEYS.SOURCE] = 'test-source';
bid.adUnitCode = 'adunit';
if (winningBid == null || bid.cpm > winningBid.cpm) {
winningBid = bid;
}
});
enableSendAllBids = true;
});

const expandKey = function (key) {
const keys = new Set();
if (winningBid.adserverTargeting[key] != null) {
keys.add(key);
}
bidsReceived
.filter((bid) => bid.adserverTargeting[key] != null)
.map((bid) => bid.bidderCode)
.forEach((code) => keys.add(`${key}_${code}`.substr(0, 20)));
return new Array(...keys);
}

const targetingResult = function () {
return targetingInstance.getAllTargeting(['adunit'])['adunit'];
}

it('should include added keys', function () {
config.setConfig({
targetingControls: {
addTargetingKeys: ['SOURCE']
}
});
expect(targetingResult()).to.include.all.keys(...expandKey(CONSTANTS.TARGETING_KEYS.SOURCE));
});

it('should keep default and native keys', function() {
config.setConfig({
targetingControls: {
addTargetingKeys: ['SOURCE']
}
});
const defaultKeys = new Set(Object.values(CONSTANTS.DEFAULT_TARGETING_KEYS));
Object.values(CONSTANTS.NATIVE_KEYS).forEach((k) => defaultKeys.add(k));

const expectedKeys = new Set();
bidsReceived
.map((bid) => Object.keys(bid.adserverTargeting))
.reduce((left, right) => left.concat(right), [])
.filter((key) => defaultKeys.has(key))
.map(expandKey)
.flat()
.forEach((k) => expectedKeys.add(k));
expect(targetingResult()).to.include.all.keys(...expectedKeys.values());
});

it('should not be allowed together with allowTargetingKeys', function () {
config.setConfig({
targetingControls: {
allowTargetingKeys: [CONSTANTS.TARGETING_KEYS.BIDDER],
addTargetingKeys: [CONSTANTS.TARGETING_KEYS.SOURCE]
}
});
expect(targetingResult).to.throw();
});
});

describe('targetingControls.allowSendAllBidsTargetingKeys', function () {
let bid4;

Expand Down

0 comments on commit adb6767

Please sign in to comment.