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

convert targeting module to factory pattern #1606

Closed
wants to merge 1 commit into from
Closed
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
6 changes: 3 additions & 3 deletions src/adserver.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {formatQS} from './url';
import {getWinningBids} from './targeting';
import { formatQS } from './url';
import { targeting } from './targeting';

// Adserver parent class
const AdServer = function(attr) {
this.name = attr.adserver;
this.code = attr.code;
this.getWinningBidByCode = function() {
return getWinningBids(this.code)[0];
return targeting.getWinningBids(this.code)[0];
};
};

Expand Down
2 changes: 1 addition & 1 deletion src/prebid.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { userSync } from 'src/userSync.js';
import { loadScript } from './adloader';
import { setAjaxTimeout } from './ajax';
import { config } from './config';
import { targeting } from './targeting';

var $$PREBID_GLOBAL$$ = getGlobal();

Expand All @@ -21,7 +22,6 @@ var adaptermanager = require('./adaptermanager');
var bidfactory = require('./bidfactory');
var events = require('./events');
var adserver = require('./adserver.js');
var targeting = require('./targeting.js');
const { syncUsers, triggerUserSyncs } = userSync;

/* private variables */
Expand Down
184 changes: 95 additions & 89 deletions src/targeting.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,66 +5,113 @@ const bidmanager = require('./bidmanager');
const utils = require('./utils');
var CONSTANTS = require('./constants');

var targeting = exports;
var pbTargetingKeys = [];

targeting.resetPresetTargeting = function(adUnitCode) {
if (isGptPubadsDefined()) {
export function newTargeting() {
Copy link
Contributor

@dbemiller dbemiller Sep 22, 2017

Choose a reason for hiding this comment

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

As written, all these instances are hardcoded to depend on two pieces of mutable/global state: $$PREBID_GLOBAL$$ (through getBidLandscapeTargeting and getAlwaysUseBidTargeting) and the bidmanager (through getStandardKeys).

These two things should be arguments here, with the globals passed in in the export const targeting line.

That will make it possible (for someone else--unless you want to tackle it here) to clear the unit tests of the issues that @mkendall07 ran into in #1427, and bring the project one step closer to #1508.

let targeting = {};
targeting.resetPresetTargeting = function(adUnitCode) {
if (isGptPubadsDefined()) {
const adUnitCodes = getAdUnitCodes(adUnitCode);
const adUnits = $$PREBID_GLOBAL$$.adUnits.filter(adUnit => adUnitCodes.includes(adUnit.code));
window.googletag.pubads().getSlots().forEach(slot => {
pbTargetingKeys.forEach(function(key) {
// reset only registered adunits
adUnits.forEach(function(unit) {
if (unit.code === slot.getAdUnitPath() ||
unit.code === slot.getSlotElementId()) {
slot.setTargeting(key, null);
}
});
});
});
}
};

targeting.getAllTargeting = function(adUnitCode) {
const adUnitCodes = getAdUnitCodes(adUnitCode);
const adUnits = $$PREBID_GLOBAL$$.adUnits.filter(adUnit => adUnitCodes.includes(adUnit.code));
window.googletag.pubads().getSlots().forEach(slot => {
pbTargetingKeys.forEach(function(key) {
// reset only registered adunits
adUnits.forEach(function(unit) {
if (unit.code === slot.getAdUnitPath() ||
unit.code === slot.getSlotElementId()) {
slot.setTargeting(key, null);

// Get targeting for the winning bid. Add targeting for any bids that have
// `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids.
var targeting = getWinningBidTargeting(adUnitCodes)
.concat(getAlwaysUseBidTargeting(adUnitCodes))
.concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []);

// store a reference of the targeting keys
targeting.map(adUnitCode => {
Object.keys(adUnitCode).map(key => {
adUnitCode[key].map(targetKey => {
if (pbTargetingKeys.indexOf(Object.keys(targetKey)[0]) === -1) {
pbTargetingKeys = Object.keys(targetKey).concat(pbTargetingKeys);
}
});
});
});
}
};
return targeting;
};

targeting.getAllTargeting = function(adUnitCode) {
const adUnitCodes = getAdUnitCodes(adUnitCode);

// Get targeting for the winning bid. Add targeting for any bids that have
// `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids.
var targeting = getWinningBidTargeting(adUnitCodes)
.concat(getAlwaysUseBidTargeting(adUnitCodes))
.concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []);

// store a reference of the targeting keys
targeting.map(adUnitCode => {
Object.keys(adUnitCode).map(key => {
adUnitCode[key].map(targetKey => {
if (pbTargetingKeys.indexOf(Object.keys(targetKey)[0]) === -1) {
pbTargetingKeys = Object.keys(targetKey).concat(pbTargetingKeys);
}
});
targeting.setTargeting = function(targetingConfig) {
window.googletag.pubads().getSlots().forEach(slot => {
targetingConfig.filter(targeting => Object.keys(targeting)[0] === slot.getAdUnitPath() ||
Object.keys(targeting)[0] === slot.getSlotElementId())
.forEach(targeting => targeting[Object.keys(targeting)[0]]
.forEach(key => {
key[Object.keys(key)[0]]
.map((value) => {
utils.logMessage(`Attempting to set key value for slot: ${slot.getSlotElementId()} key: ${Object.keys(key)[0]} value: ${value}`);
return value;
})
.forEach(value => {
slot.setTargeting(Object.keys(key)[0], value);
});
}));
});
});
};

/**
* Returns top bids for a given adUnit or set of adUnits.
* @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes
* @return {[type]} [description]
*/
targeting.getWinningBids = function(adUnitCode) {
const adUnitCodes = getAdUnitCodes(adUnitCode);

return $$PREBID_GLOBAL$$._bidsReceived
.filter(bid => adUnitCodes.includes(bid.adUnitCode))
.filter(bid => bid.cpm > 0)
.map(bid => bid.adUnitCode)
.filter(uniques)
.map(adUnitCode => $$PREBID_GLOBAL$$._bidsReceived
.filter(bid => bid.adUnitCode === adUnitCode ? bid : null)
.reduce(getHighestCpm, getEmptyBid(adUnitCode)));
};

targeting.setTargetingForAst = function() {
let targeting = $$PREBID_GLOBAL$$.getAdserverTargeting();
Object.keys(targeting).forEach(targetId =>
Object.keys(targeting[targetId]).forEach(key => {
utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${targeting[targetId][key]}`);
// setKeywords supports string and array as value
if (utils.isStr(targeting[targetId][key]) || utils.isArray(targeting[targetId][key])) {
let keywordsObj = {};
let input = 'hb_adid';
let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key;
keywordsObj[nKey] = targeting[targetId][key];
window.apntag.setKeywords(targetId, keywordsObj);
}
})
);
};

targeting.isApntagDefined = function() {
if (window.apntag && utils.isFn(window.apntag.setKeywords)) {
return true;
}
};

return targeting;
};

targeting.setTargeting = function(targetingConfig) {
window.googletag.pubads().getSlots().forEach(slot => {
targetingConfig.filter(targeting => Object.keys(targeting)[0] === slot.getAdUnitPath() ||
Object.keys(targeting)[0] === slot.getSlotElementId())
.forEach(targeting => targeting[Object.keys(targeting)[0]]
.forEach(key => {
key[Object.keys(key)[0]]
.map((value) => {
utils.logMessage(`Attempting to set key value for slot: ${slot.getSlotElementId()} key: ${Object.keys(key)[0]} value: ${value}`);
return value;
})
.forEach(value => {
slot.setTargeting(Object.keys(key)[0], value);
});
}));
});
};
export const targeting = newTargeting();

/**
* normlizes input to a `adUnit.code` array
Expand All @@ -80,41 +127,6 @@ function getAdUnitCodes(adUnitCode) {
return $$PREBID_GLOBAL$$._adUnitCodes || [];
}

/**
* Returns top bids for a given adUnit or set of adUnits.
* @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes
* @return {[type]} [description]
*/
targeting.getWinningBids = function(adUnitCode) {
const adUnitCodes = getAdUnitCodes(adUnitCode);

return $$PREBID_GLOBAL$$._bidsReceived
.filter(bid => adUnitCodes.includes(bid.adUnitCode))
.filter(bid => bid.cpm > 0)
.map(bid => bid.adUnitCode)
.filter(uniques)
.map(adUnitCode => $$PREBID_GLOBAL$$._bidsReceived
.filter(bid => bid.adUnitCode === adUnitCode ? bid : null)
.reduce(getHighestCpm, getEmptyBid(adUnitCode)));
};

targeting.setTargetingForAst = function() {
let targeting = $$PREBID_GLOBAL$$.getAdserverTargeting();
Object.keys(targeting).forEach(targetId =>
Object.keys(targeting[targetId]).forEach(key => {
utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${targeting[targetId][key]}`);
// setKeywords supports string and array as value
if (utils.isStr(targeting[targetId][key]) || utils.isArray(targeting[targetId][key])) {
let keywordsObj = {};
let input = 'hb_adid';
let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key;
keywordsObj[nKey] = targeting[targetId][key];
window.apntag.setKeywords(targetId, keywordsObj);
}
})
);
};

function getWinningBidTargeting(adUnitCodes) {
let winners = targeting.getWinningBids(adUnitCodes);
let standardKeys = getStandardKeys();
Expand Down Expand Up @@ -194,12 +206,6 @@ function getTargetingMap(bid, keys) {
});
}

targeting.isApntagDefined = function() {
if (window.apntag && utils.isFn(window.apntag.setKeywords)) {
return true;
}
};

function getEmptyBid(adUnitCode) {
return {
adUnitCode: adUnitCode,
Expand Down
4 changes: 2 additions & 2 deletions test/spec/unit/core/targeting_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import Targeting from 'src/targeting';
import { targeting as targetingInstance } from 'src/targeting';
import { config } from 'src/config';
import { getAdUnits } from 'test/fixtures/fixtures';
import CONSTANTS from 'src/constants.json';
Expand Down Expand Up @@ -85,7 +85,7 @@ describe('targeting tests', () => {
config.setConfig({ enableSendAllBids: true });
$$PREBID_GLOBAL$$._bidsReceived.push(bid1, bid2);
$$PREBID_GLOBAL$$._adUnitCodes = ['/123456/header-bid-tag-0'];
let targeting = Targeting.getAllTargeting(['/123456/header-bid-tag-0']);
let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']);
let flattened = [];
targeting.filter(obj => obj['/123456/header-bid-tag-0'] !== undefined).forEach(item => flattened = flattened.concat(item['/123456/header-bid-tag-0']));
let sendAllBidCpm = flattened.filter(obj => obj.hb_pb_rubicon !== undefined);
Expand Down