From 7035afddaa7112fc4f2ac9af4c9107ae7699b650 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Tue, 26 May 2020 23:31:51 -0700 Subject: [PATCH 1/2] Updated schema to be grouped by adunit code and added client-side incremental lift calculation. --- modules/openxAnalyticsAdapter.js | 63 +++++++++++++++---- .../modules/openxAnalyticsAdapter_spec.js | 54 +++++++++------- 2 files changed, 84 insertions(+), 33 deletions(-) diff --git a/modules/openxAnalyticsAdapter.js b/modules/openxAnalyticsAdapter.js index c7b367a8687..35d9ce163e2 100644 --- a/modules/openxAnalyticsAdapter.js +++ b/modules/openxAnalyticsAdapter.js @@ -1,4 +1,4 @@ -import includes from 'core-js/library/fn/array/includes.js'; +import includes from 'core-js-pure/features/array/includes.js'; import adapter from '../src/AnalyticsAdapter.js'; import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; @@ -1080,24 +1080,19 @@ function buildAuctionPayload(auction) { deviceOSType: detectOS(), browser: detectBrowser(), testCode: analyticsConfig.testCode, - bidRequests: buildBidRequestsPayload(adUnitCodeToBidderRequestMap), + adUnits: buildBidRequestsPayload(adUnitCodeToBidderRequestMap), }; function buildBidRequestsPayload(adUnitCodeToBidderRequestMap) { return utils._map(adUnitCodeToBidderRequestMap, (bidderRequestMap, adUnitCode) => { - return utils._map(bidderRequestMap, (bidderRequest) => { + let bidRequests = utils._map(bidderRequestMap, (bidderRequest) => { let {bidder, source, bids, mediaTypes, timedOut, userId} = bidderRequest; return { adUnitCode, bidder, source, // return an array of objects containing the module name and id - userIds: utils._map(userId, (id, module) => { - return { - module: module, - id: getUserId(module, id)}; - }) - .filter(({id}) => id), + userIds: buildUserIdPayload(userId), hasBidderResponded: Object.keys(bids).length > 0, availableAdSizes: getMediaTypeSizes(mediaTypes), availableMediaTypes: getMediaTypes(mediaTypes), @@ -1122,7 +1117,7 @@ function buildAuctionPayload(auction) { latency, winner, rendered, - renderTime, + renderTime } = bidderBidResponse; return { @@ -1141,14 +1136,58 @@ function buildAuctionPayload(auction) { ts, rendered, renderTime, - meta, + meta } }) } - }) + }); + + return { + code: adUnitCode, + incrementalLiftMicroCpmUSD: calculateIncrementalLift(bidRequests), + bidRequests + }; + + function buildUserIdPayload(userId) { + return utils._map(userId, (id, module) => { + return { + module: module, + id: getUserId(module, id) + }; + }) + .filter(({id}) => id) + } }).flat(); } + function calculateIncrementalLift(bidRequests) { + let bidResponses = bidRequests.flatMap(bidRequest => bidRequest.bidResponses); + let [winningBidResponses, losingBidResponses] = partitionByWinningResponses(bidResponses); + let loserWithHigestCpm; + + + if(winningBidResponses.length === 0) { + return 0; + } + + loserWithHigestCpm = losingBidResponses.reduce((bidResponseWithHighestCpm, bidResponse) => { + if(!bidResponseWithHighestCpm){ + return bidResponse + } else { + return bidResponse.microCpm > bidResponseWithHighestCpm.microCpm ? bidResponse : bidResponseWithHighestCpm; + } + }, {microCpm: 0}); + + return (winningBidResponses[0].microCpm - loserWithHigestCpm.microCpm); + + function partitionByWinningResponses(bidResponses){ + return bidResponses.reduce(([winners, losers], bidResponse) => { + bidResponse.winner ? winners.push(bidResponse) : losers.push(bidResponse); + return [winners, losers]; + }, [[],[]]); + } + } + function getUserId(module, idOrIdObject) { let normalizedId; diff --git a/test/spec/modules/openxAnalyticsAdapter_spec.js b/test/spec/modules/openxAnalyticsAdapter_spec.js index d57b3bb7d1e..1462bb3b971 100644 --- a/test/spec/modules/openxAnalyticsAdapter_spec.js +++ b/test/spec/modules/openxAnalyticsAdapter_spec.js @@ -675,10 +675,10 @@ describe('openx analytics adapter', function() { const bidTimeoutOpenX = { 0: { - adUnitCode: AD_UNIT_CODE, - auctionId: 'test-auction-id', - bidId: 'test-openx-request-id' - }}; + adUnitCode: AD_UNIT_CODE, + auctionId: 'test-auction-id', + bidId: 'test-openx-request-id' + }}; const bidTimeoutCloseX = { 0: { @@ -922,32 +922,32 @@ describe('openx analytics adapter', function() { }); it('should track the bidder', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); - let closexBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let closexBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); expect(openxBidder.bidder).to.equal('openx'); expect(closexBidder.bidder).to.equal('closex'); }); it('should track the adunit code', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); - let closexBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let closexBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); expect(openxBidder.adUnitCode).to.equal(AD_UNIT_CODE); expect(closexBidder.adUnitCode).to.equal(AD_UNIT_CODE); }); it('should track the user ids', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); - let closexBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let closexBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); expect(openxBidder.userIds).to.deep.include({module: 'tdid', id: bidRequestedOpenX.bids[0].userId.tdid}); expect(closexBidder.userIds).to.deep.include({module: 'tdid', id: bidRequestedCloseX.bids[0].userId.tdid}); }); it('should not have responded', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); - let closexBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let closexBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); expect(openxBidder.hasBidderResponded).to.equal(false); expect(closexBidder.hasBidderResponded).to.equal(false); @@ -973,8 +973,8 @@ describe('openx analytics adapter', function() { clock.tick(SLOT_LOAD_WAIT_TIME * 2); auction = JSON.parse(server.requests[0].requestBody)[0]; - openxBidRequest = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); - closexBidRequest = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); + openxBidRequest = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + closexBidRequest = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); }); afterEach(function () { @@ -1008,8 +1008,8 @@ describe('openx analytics adapter', function() { clock.tick(SLOT_LOAD_WAIT_TIME * 2); auction = JSON.parse(server.requests[0].requestBody)[0]; - openxBidResponse = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx').bidResponses[0]; - closexBidResponse = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex').bidResponses[0]; + openxBidResponse = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx').bidResponses[0]; + closexBidResponse = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex').bidResponses[0]; }); afterEach(function () { @@ -1104,14 +1104,26 @@ describe('openx analytics adapter', function() { }); it('should track that bidder as the winner', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); expect(openxBidder.bidResponses[0]).to.contain({winner: true}); }); it('should track that bidder as the losers', function () { - let closexBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); + let closexBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); expect(closexBidder.bidResponses[0]).to.contain({winner: false}); }); + + it('should calculate the incremental lift for winning bids', function () { + let openxBidderResponse = auction.adUnits[0].bidRequests + .find(bidderRequest => bidderRequest.bidder === 'openx') + .bidResponses[0]; + + let closexBidderResponse = auction.adUnits[0].bidRequests + .find(bidderRequest => bidderRequest.bidder === 'closex') + .bidResponses[0]; + + expect(auction.adUnits[0].incrementalLiftMicroCpmUSD).to.equal(openxBidderResponse.microCpm - closexBidderResponse.microCpm); + }); }); describe('when a winning bid renders', function () { @@ -1145,12 +1157,12 @@ describe('openx analytics adapter', function() { }); it('should track that winning bid rendered', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); expect(openxBidder.bidResponses[0]).to.contain({rendered: true}); }); it('should track that winning bid render time', function () { - let openxBidder = auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let openxBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); expect(openxBidder.bidResponses[0]).to.contain({renderTime: CURRENT_TIME}); }); @@ -1386,7 +1398,7 @@ describe('openx analytics adapter', function() { expect(bidWonEventInfoList.length).to.equal(1); - let openxBidder = v2Auction.bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); + let openxBidder = v2Auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'openx'); expect(openxBidder.bidResponses[0]).to.contain({winner: true}); }); }); From da00d4d1424e86582d17f07e471a4ac152fb2f88 Mon Sep 17 00:00:00 2001 From: Jimmy Tu Date: Wed, 27 May 2020 21:26:21 -0700 Subject: [PATCH 2/2] Removed incremental calculation. --- modules/openxAnalyticsAdapter.js | 29 ------------------- .../modules/openxAnalyticsAdapter_spec.js | 12 -------- 2 files changed, 41 deletions(-) diff --git a/modules/openxAnalyticsAdapter.js b/modules/openxAnalyticsAdapter.js index 35d9ce163e2..68b2d2478ec 100644 --- a/modules/openxAnalyticsAdapter.js +++ b/modules/openxAnalyticsAdapter.js @@ -1144,7 +1144,6 @@ function buildAuctionPayload(auction) { return { code: adUnitCode, - incrementalLiftMicroCpmUSD: calculateIncrementalLift(bidRequests), bidRequests }; @@ -1160,34 +1159,6 @@ function buildAuctionPayload(auction) { }).flat(); } - function calculateIncrementalLift(bidRequests) { - let bidResponses = bidRequests.flatMap(bidRequest => bidRequest.bidResponses); - let [winningBidResponses, losingBidResponses] = partitionByWinningResponses(bidResponses); - let loserWithHigestCpm; - - - if(winningBidResponses.length === 0) { - return 0; - } - - loserWithHigestCpm = losingBidResponses.reduce((bidResponseWithHighestCpm, bidResponse) => { - if(!bidResponseWithHighestCpm){ - return bidResponse - } else { - return bidResponse.microCpm > bidResponseWithHighestCpm.microCpm ? bidResponse : bidResponseWithHighestCpm; - } - }, {microCpm: 0}); - - return (winningBidResponses[0].microCpm - loserWithHigestCpm.microCpm); - - function partitionByWinningResponses(bidResponses){ - return bidResponses.reduce(([winners, losers], bidResponse) => { - bidResponse.winner ? winners.push(bidResponse) : losers.push(bidResponse); - return [winners, losers]; - }, [[],[]]); - } - } - function getUserId(module, idOrIdObject) { let normalizedId; diff --git a/test/spec/modules/openxAnalyticsAdapter_spec.js b/test/spec/modules/openxAnalyticsAdapter_spec.js index 1462bb3b971..468e42b649e 100644 --- a/test/spec/modules/openxAnalyticsAdapter_spec.js +++ b/test/spec/modules/openxAnalyticsAdapter_spec.js @@ -1112,18 +1112,6 @@ describe('openx analytics adapter', function() { let closexBidder = auction.adUnits[0].bidRequests.find(bidderRequest => bidderRequest.bidder === 'closex'); expect(closexBidder.bidResponses[0]).to.contain({winner: false}); }); - - it('should calculate the incremental lift for winning bids', function () { - let openxBidderResponse = auction.adUnits[0].bidRequests - .find(bidderRequest => bidderRequest.bidder === 'openx') - .bidResponses[0]; - - let closexBidderResponse = auction.adUnits[0].bidRequests - .find(bidderRequest => bidderRequest.bidder === 'closex') - .bidResponses[0]; - - expect(auction.adUnits[0].incrementalLiftMicroCpmUSD).to.equal(openxBidderResponse.microCpm - closexBidderResponse.microCpm); - }); }); describe('when a winning bid renders', function () {