Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Komorski authored and Marcin Komorski committed Jul 8, 2024
1 parent afc58a3 commit 9e14c13
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 63 deletions.
30 changes: 14 additions & 16 deletions modules/dfpAdServerVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
* This module adds [DFP support]{@link https://www.doubleclickbygoogle.com/} for Video to Prebid.
*/

import {registerVideoSupport} from '../src/adServerManager.js';
import {targeting} from '../src/targeting.js';
import { DEFAULT_DFP_PARAMS, DFP_ENDPOINT } from '../libraries/dfpUtils/dfpUtils.js';
import { registerVideoSupport } from '../src/adServerManager.js';
import { gdprDataHandler } from '../src/adapterManager.js';
import { getPPID } from '../src/adserver.js';
import { auctionManager } from '../src/auctionManager.js';
import { config } from '../src/config.js';
import { EVENTS } from '../src/constants.js';
import * as events from '../src/events.js';
import { getHook } from '../src/hook.js';
import { getSignals } from '../src/pps.js';
import { getRefererInfo } from '../src/refererDetection.js';
import { targeting } from '../src/targeting.js';
import {
buildUrl,
deepAccess,
Expand All @@ -12,20 +22,8 @@ import {
isNumber,
logError,
parseSizesInput,
parseUrl,
uniques
parseUrl
} from '../src/utils.js';
import {config} from '../src/config.js';
import {getHook} from '../src/hook.js';
import {auctionManager} from '../src/auctionManager.js';
import {gdprDataHandler} from '../src/adapterManager.js';
import * as events from '../src/events.js';
import {EVENTS} from '../src/constants.js';
import {getPPID} from '../src/adserver.js';
import {getRefererInfo} from '../src/refererDetection.js';
import {CLIENT_SECTIONS} from '../src/fpd/oneClient.js';
import {DEFAULT_DFP_PARAMS, DFP_ENDPOINT} from '../libraries/dfpUtils/dfpUtils.js';
import { getSegments, getSignals } from '../src/pps.js';
/**
* @typedef {Object} DfpVideoParams
*
Expand Down Expand Up @@ -171,7 +169,7 @@ export function buildDfpVideoUrl(options) {
});
const fpd = auctionManager.index.getBidRequest(options.bid || {})?.ortb2 ??
auctionManager.index.getAuction(options.bid || {})?.getFPD()?.global;

const signals = getSignals(fpd);

if (signals.length) {
Expand Down
17 changes: 14 additions & 3 deletions src/pps.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { auctionManager } from './auctionManager.js';
import { TARGETING_KEYS } from './constants.js';
import { CLIENT_SECTIONS } from './fpd/oneClient.js';
import { deepAccess, uniques } from './utils.js';

Expand All @@ -21,15 +22,16 @@ export function getSignals(fpd) {
return signals;
}

export function getSignalsArray(auctionIds) {
export function getSignalsArrayByAuctionsIds(auctionIds) {
const signals = auctionIds
.map(auctionId => auctionManager.index.getAuction({ auctionId })?.getFPD()?.global)
.map(getSignals)
.filter(fpd => fpd);
return signals

return signals;
}

export function getSegmentsIntersection(signals) {
export function getSignalsIntersection(signals) {
const taxonomies = ['IAB_AUDIENCE_1_1', 'IAB_CONTENT_2_2'];
const result = {};
taxonomies.forEach((taxonomy) => {
Expand All @@ -42,6 +44,15 @@ export function getSegmentsIntersection(signals) {
return commonElements.filter(element => subArray.includes(element));
})
) : []
result[taxonomy] = { values: result[taxonomy] };
})
return result;
}

export function getAuctionsIdsFromTargeting(targeting) {
return Object.values(targeting)
.flatMap(x => Object.entries(x))
.filter((entry) => (entry[0] || '').includes(TARGETING_KEYS.AD_ID))
.flatMap(entry => entry[1])
.filter(uniques);
}
60 changes: 26 additions & 34 deletions src/targeting.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
import { auctionManager } from './auctionManager.js';
import { getTTL } from './bidTTL.js';
import { bidderSettings } from './bidderSettings.js';
import { config } from './config.js';
import {
BID_STATUS,
DEFAULT_TARGETING_KEYS,
EVENTS,
JSON_MAPPING,
NATIVE_KEYS,
STATUS,
TARGETING_KEYS
} from './constants.js';
import * as events from './events.js';
import { hook } from './hook.js';
import { ADPOD } from './mediaTypes.js';
import { NATIVE_TARGETING_KEYS } from './native.js';
import { find, includes } from './polyfill.js';
import { getAuctionsIdsFromTargeting, getSignalsArrayByAuctionsIds, getSignalsIntersection } from './pps.js';
import {
deepAccess,
deepClone,
Expand All @@ -14,26 +33,7 @@ import {
timestamp,
uniques,
} from './utils.js';
import {config} from './config.js';
import {NATIVE_TARGETING_KEYS} from './native.js';
import {auctionManager} from './auctionManager.js';
import {ADPOD} from './mediaTypes.js';
import {hook} from './hook.js';
import {bidderSettings} from './bidderSettings.js';
import {find, includes} from './polyfill.js';
import {
BID_STATUS,
DEFAULT_TARGETING_KEYS,
EVENTS,
JSON_MAPPING,
NATIVE_KEYS,
STATUS,
TARGETING_KEYS
} from './constants.js';
import {getHighestCpm, getOldestHighestCpmBid} from './utils/reducers.js';
import {getTTL} from './bidTTL.js';
import * as events from './events.js';
import { getSignalsArray } from './pps.js';
import { getHighestCpm, getOldestHighestCpmBid } from './utils/reducers.js';

var pbTargetingKeys = [];

Expand Down Expand Up @@ -436,16 +436,6 @@ export function newTargeting(auctionManager) {
// get our ad unit codes
let targetingSet = targeting.getAllTargeting(adUnit);

const auctionIds = targetingSet
.flatMap(entry => Object.values(entry))
.flatMap(x => x)
.filter(x => Object.keys(x).some(key => key.includes(TARGETING_KEYS.AD_ID)))
.map(entry => Object.values(entry))
.flatMap(x => x[0])

const signals = getSignalsArray(auctionIds)
googletag.setConfig({pps: signals})

let resetMap = Object.fromEntries(pbTargetingKeys.map(key => [key, null]));

Object.entries(getGPTSlotsForAdUnits(Object.keys(targetingSet), customSlotMatching)).forEach(([targetId, slots]) => {
Expand All @@ -472,6 +462,11 @@ export function newTargeting(auctionManager) {
});
});

// set gpt config
const auctionsIds = getAuctionsIdsFromTargeting(targetingSet);
const signals = getSignalsIntersection(getSignalsArrayByAuctionsIds(auctionsIds));
window.googletag.setConfig && window.googletag.setConfig({pps: { taxonomies: signals }});

// emit event
events.emit(EVENTS.SET_TARGETING, targetingSet);
}, 'setTargetingForGPT');
Expand Down Expand Up @@ -676,10 +671,7 @@ export function newTargeting(auctionManager) {
function getCustomBidTargeting(adUnitCodes, bidsReceived) {
return bidsReceived
.filter(bid => includes(adUnitCodes, bid.adUnitCode))
.map(bid => {
const newBid = Object.assign({}, bid);
return newBid;
})
.map(bid => Object.assign({}, bid))
.reduce(mergeAdServerTargeting, [])
.map(truncateCustomKeys)
.filter(bid => bid); // removes empty elements in array;
Expand Down
54 changes: 44 additions & 10 deletions test/spec/unit/core/pps_spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { auctionManager } from '../../../../src/auctionManager';
import { getFpdIntersection, getSegmentsIntersection, getSignalsArray } from '../../../../src/pps'
import { getAuctionsIdsFromTargeting, getSegments, getSignals, getSignalsArrayByAuctionsIds, getSignalsIntersection } from '../../../../src/pps';

describe('pps', () => {
let getAuctionStub;
const mockTargeting = {'/123456/header-bid-tag-0': {'hb_deal_rubicon': '1234', 'hb_deal': '1234', 'hb_pb': '0.53', 'hb_adid': '148018fe5e', 'hb_bidder': 'rubicon', 'foobar': '300x250', 'hb_pb_rubicon': '0.53', 'hb_adid_rubicon': '148018fe5e', 'hb_bidder_rubicon': 'rubicon', 'hb_deal_appnexus': '4321', 'hb_pb_appnexus': '0.1', 'hb_adid_appnexus': '567891011', 'hb_bidder_appnexus': 'appnexus'}}

const mocksAuctions = [
{
Expand Down Expand Up @@ -64,19 +65,52 @@ describe('pps', () => {
},
]

beforeEach(function () {
it('should parse segments from fpd', () => {
const twoSegments = getSegments(mocksAuctions[0].getFPD().global, ['user.data'], 4);
expect(JSON.stringify(twoSegments)).to.equal(JSON.stringify(['1', '2']))
const zeroSegments = getSegments(mocksAuctions[0].getFPD().global, ['user.data'], 6);
expect(zeroSegments).to.length(0);
})

it('should return signals from fpd', () => {
const signals = getSignals(mocksAuctions[0].getFPD().global);
const expectedSignals = [{ taxonomy: 'IAB_AUDIENCE_1_1', values: ['1', '2'] }];
expect(JSON.stringify(signals)).to.equal(JSON.stringify(expectedSignals))
})

it('should properly get auctions ids from targeting', () => {
const auctionsIds = getAuctionsIdsFromTargeting(mockTargeting);
expect(JSON.stringify(auctionsIds)).to.equal(JSON.stringify(['148018fe5e', '567891011']))
})

it('should properly return empty array of auction ids for invalid targeting', () => {
let auctionsIds = getAuctionsIdsFromTargeting({});
expect(Array.isArray(auctionsIds)).to.equal(true);
expect(auctionsIds).to.length(0);
auctionsIds = getAuctionsIdsFromTargeting({'/123456/header-bid-tag-0/bg': {'invalidContent': '123'}});
expect(Array.isArray(auctionsIds)).to.equal(true);
expect(auctionsIds).to.length(0);
})

it('should properly get signals from auctions', () => {
getAuctionStub = sinon.stub(auctionManager.index, 'getAuction').callsFake(({ auctionId }) => {
return mocksAuctions.find(auction => auction.auctionId === auctionId)
});
});

afterEach(function () {
const signals = getSignalsArrayByAuctionsIds(['1111', '234234', '234324234']);
const intersection = getSignalsIntersection(signals)
const expectedResult = { IAB_AUDIENCE_1_1: { values: ['2'] }, IAB_CONTENT_2_2: { values: [] } };
expect(JSON.stringify(intersection)).to.be.equal(JSON.stringify(expectedResult));
getAuctionStub.restore();
});
})

it('should return empty signals array for empty auctions ids array', () => {
const signals = getSignalsArrayByAuctionsIds([]);
expect(Array.isArray(signals)).to.equal(true);
expect(signals).to.length(0);
})

it('should properly find intersection', () => {
const signals = getSignalsArray(['1111', '234234', '234324234']);
const expectedResult = { IAB_AUDIENCE_1_1:["2"], IAB_CONTENT_2_2:[]};
expect(signals).to.be.equal(JSON.stringify(expectedResult));
it('should return properly formatted object for getSignalsIntersection invoked with empty array', () => {
const signals = getSignalsIntersection([]);
expect(Object.keys(signals)).to.contain.members(['IAB_AUDIENCE_1_1', 'IAB_CONTENT_2_2']);
})
})

0 comments on commit 9e14c13

Please sign in to comment.