Skip to content

Commit

Permalink
Adagio Analytics Adapter: listen to AUCTION_END (#10798)
Browse files Browse the repository at this point in the history
* Adagio Analytics Adapter: add tracker on auction_end

* Adagio Analytics Adapter: refacto metadata transfer

* Adagio Analytics Adapter: update pba props

---------

Co-authored-by: François Rotta <franz.rotta@gmail.com>
  • Loading branch information
osazos and rotta-f authored Dec 11, 2023
1 parent 222b442 commit 3ec81e6
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 32 deletions.
58 changes: 52 additions & 6 deletions modules/adagioAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const cache = {
getAuction: function(auctionId, adUnitCode) {
return this.auctions[auctionId][adUnitCode];
},
getBiddersFromAuction: function(auctionId, adUnitCode) {
return this.getAuction(auctionId, adUnitCode).bdrs.split(',');
},
getAllAdUnitCodes: function(auctionId) {
return Object.keys(this.auctions[auctionId]);
},
updateAuction: function(auctionId, adUnitCode, values) {
this.auctions[auctionId][adUnitCode] = {
...this.auctions[auctionId][adUnitCode],
Expand Down Expand Up @@ -74,7 +80,8 @@ const adagioEnqueue = function adagioEnqueue(action, data) {

const guard = {
adagio: (value) => isAdagio(value),
bidTracked: (auctionId, adUnitCode) => deepAccess(cache, `auctions.${auctionId}.${adUnitCode}`, false)
bidTracked: (auctionId, adUnitCode) => deepAccess(cache, `auctions.${auctionId}.${adUnitCode}`, false),
auctionTracked: (auctionId) => deepAccess(cache, `auctions.${auctionId}`, false)
};

function removeDuplicates(arr, getKey) {
Expand Down Expand Up @@ -105,6 +112,19 @@ function getMediaTypeAlias(mediaType) {
return mediaTypesMap[mediaType] || mediaType;
};

function addKeyPrefix(obj, prefix) {
return Object.keys(obj).reduce((acc, key) => {
// We don't want to prefix already prefixed keys.
if (key.startsWith(prefix)) {
acc[key] = obj[key];
return acc;
}

acc[`${prefix}${key}`] = obj[key];
return acc;
}, {});
}

/**
* sendRequest to Adagio. It filter null values and encode each query param.
* @param {Object} qp
Expand Down Expand Up @@ -146,6 +166,7 @@ function getTargetedAuctionId(bid) {
* HANDLERS
* - handlerAuctionInit
* - handlerBidResponse
* - handlerAuctionEnd
* - handlerBidWon
* - handlerAdRender
*
Expand Down Expand Up @@ -227,11 +248,10 @@ function handlerAuctionInit(event) {
auct_id: adagioAuctionId,
adu_code: adUnitCode,
url_dmn: w.location.hostname,
dvc: params.environment,
pgtyp: params.pagetype,
plcmt: params.placement,
tname: params.testName || null,
tvname: params.testVariationName || null,
t_n: params.testName || null,
t_v: params.testVersion || null,
mts: mediaTypesKeys.join(','),
ban_szs: bannerSizes.join(','),
bdrs: bidders.map(bidder => getAdapterNameForAlias(bidder.bidder)).sort().join(','),
Expand All @@ -257,11 +277,33 @@ function handlerBidResponse(event) {
return;
}

if (!event.pba) {
return;
}

cache.updateAuction(event.auctionId, event.adUnitCode, {
adg_sid: event.seatId || null
...addKeyPrefix(event.pba, 'e_')
});
};

function handlerAuctionEnd(event) {
const { auctionId } = event;

if (!guard.auctionTracked(auctionId)) {
return;
}

const adUnitCodes = cache.getAllAdUnitCodes(auctionId);
adUnitCodes.forEach(adUnitCode => {
const mapper = (bidder) => event.bidsReceived.find(bid => bid.adUnitCode === adUnitCode && bid.bidder === bidder) ? '1' : '0';

cache.updateAuction(auctionId, adUnitCode, {
bdrs_bid: cache.getBiddersFromAuction(auctionId, adUnitCode).map(mapper).join(',')
});
sendNewBeacon(auctionId, adUnitCode);
});
}

function handlerBidWon(event) {
let auctionId = getTargetedAuctionId(event);

Expand Down Expand Up @@ -340,10 +382,14 @@ let adagioAdapter = Object.assign(adapter({ emptyUrl, analyticsType }), {
case CONSTANTS.EVENTS.BID_RESPONSE:
handlerBidResponse(args);
break;
case CONSTANTS.EVENTS.AUCTION_END:
handlerAuctionEnd(args);
break;
case CONSTANTS.EVENTS.BID_WON:
handlerBidWon(args);
break;
case CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED:
// AD_RENDER_SUCCEEDED seems redundant with BID_WON.
// case CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED:
case CONSTANTS.EVENTS.AD_RENDER_FAILED:
handlerAdRender(args, eventType === CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED);
break;
Expand Down
109 changes: 83 additions & 26 deletions test/spec/modules/adagioAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ const BID_ADAGIO = Object.assign({}, BID_ADAGIO, {
meta: {
advertiserDomains: ['example.com']
},
seatId: '42',
pba: {
sid: '42',
e_pba_test: true
}
});

const BID_ANOTHER = Object.assign({}, BID_ANOTHER, {
Expand Down Expand Up @@ -256,7 +259,9 @@ const PARAMS_ADG = {
pageviewId: 'a68e6d70-213b-496c-be0a-c468ff387106',
environment: 'desktop',
pagetype: 'article',
placement: 'pave_top'
placement: 'pave_top',
testName: 'test',
testVersion: 'version',
};

const AUCTION_INIT_ANOTHER = {
Expand Down Expand Up @@ -285,6 +290,11 @@ const AUCTION_INIT_ANOTHER = {
'params': {
'publisherId': '1001'
},
}, {
'bidder': 'nobid',
'params': {
'publisherId': '1002'
},
}, {
'bidder': 'adagio',
'params': {
Expand Down Expand Up @@ -354,6 +364,24 @@ const AUCTION_INIT_ANOTHER = {
'auctionId': AUCTION_ID,
'src': 'client',
'bidRequestsCount': 1
}, {
'bidder': 'nobid',
'params': {
'publisherId': '1001'
},
'mediaTypes': {
'banner': {
'sizes': [[640, 480]]
}
},
'adUnitCode': '/19968336/footer-bid-tag-1',
'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
'sizes': [[640, 480]],
'bidId': '2ecff0db240757',
'bidderRequestId': '1be65d7958826a',
'auctionId': AUCTION_ID,
'src': 'client',
'bidRequestsCount': 1
}
],
'timeout': 3000,
Expand Down Expand Up @@ -533,6 +561,14 @@ const AUCTION_INIT_CACHE = {
'timeout': 3000
};

const AUCTION_END_ANOTHER = Object.assign({}, AUCTION_INIT_ANOTHER, {
bidsReceived: [BID_ANOTHER, BID_ADAGIO]
});

const AUCTION_END_ANOTHER_NOBID = Object.assign({}, AUCTION_INIT_ANOTHER, {
bidsReceived: []
});

const MOCK = {
SET_TARGETING: {
[BID_ADAGIO.adUnitCode]: BID_ADAGIO.adserverTargeting,
Expand All @@ -546,6 +582,10 @@ const MOCK = {
adagio: BID_ADAGIO,
another: BID_ANOTHER
},
AUCTION_END: {
another: AUCTION_END_ANOTHER,
another_nobid: AUCTION_END_ANOTHER_NOBID
},
BID_WON: {
adagio: Object.assign({}, BID_ADAGIO, {
'status': 'rendered'
Expand All @@ -569,6 +609,12 @@ const MOCK = {
bid: BID_CACHED
}
},
AD_RENDER_FAILED: {
bidcached: {
adId: 'fake_ad_id_2',
bid: BID_CACHED
}
}
};

describe('adagio analytics adapter', () => {
Expand Down Expand Up @@ -616,10 +662,11 @@ describe('adagio analytics adapter', () => {
events.emit(constants.EVENTS.AUCTION_INIT, MOCK.AUCTION_INIT.another);
events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.adagio);
events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.another);
events.emit(constants.EVENTS.AUCTION_END, MOCK.AUCTION_END.another);
events.emit(constants.EVENTS.BID_WON, MOCK.BID_WON.another);
events.emit(constants.EVENTS.AD_RENDER_SUCCEEDED, MOCK.AD_RENDER_SUCCEEDED.another);

expect(server.requests.length).to.equal(3);
expect(server.requests.length).to.equal(3, 'requests count');
{
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[0].url);
expect(protocol).to.equal('https');
Expand All @@ -633,12 +680,11 @@ describe('adagio analytics adapter', () => {
expect(search.site).to.equal('test-com');
expect(search.pv_id).to.equal('a68e6d70-213b-496c-be0a-c468ff387106');
expect(search.url_dmn).to.equal(window.location.hostname);
expect(search.dvc).to.equal('desktop');
expect(search.pgtyp).to.equal('article');
expect(search.plcmt).to.equal('pave_top');
expect(search.mts).to.equal('ban');
expect(search.ban_szs).to.equal('640x100,640x480');
expect(search.bdrs).to.equal('adagio,another');
expect(search.bdrs).to.equal('adagio,another,nobid');
expect(search.adg_mts).to.equal('ban');
}

Expand All @@ -648,9 +694,19 @@ describe('adagio analytics adapter', () => {
expect(hostname).to.equal('c.4dex.io');
expect(pathname).to.equal('/pba.gif');
expect(search.v).to.equal('2');
expect(search.e_sid).to.equal('42');
expect(search.e_pba_test).to.equal('true');
expect(search.bdrs_bid).to.equal('1,1,0');
}

{
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[2].url);
expect(protocol).to.equal('https');
expect(hostname).to.equal('c.4dex.io');
expect(pathname).to.equal('/pba.gif');
expect(search.v).to.equal('3');
expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
expect(search.adg_sid).to.equal('42');
expect(search.win_bdr).to.equal('another');
expect(search.win_mt).to.equal('ban');
expect(search.win_ban_sz).to.equal('728x90');
Expand All @@ -661,17 +717,6 @@ describe('adagio analytics adapter', () => {
expect(search.og_cur).to.equal('GBP');
expect(search.og_cur_rate).to.equal('1.6');
}

{
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[2].url);
expect(protocol).to.equal('https');
expect(hostname).to.equal('c.4dex.io');
expect(pathname).to.equal('/pba.gif');
expect(search.v).to.equal('3');
expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
expect(search.rndr).to.equal('1');
}
});

it('builds and sends auction data with a cached bid win', () => {
Expand All @@ -691,10 +736,11 @@ describe('adagio analytics adapter', () => {
events.emit(constants.EVENTS.AUCTION_INIT, MOCK.AUCTION_INIT.another);
events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.adagio);
events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE.another);
events.emit(constants.EVENTS.AUCTION_END, MOCK.AUCTION_END.another_nobid);
events.emit(constants.EVENTS.BID_WON, MOCK.BID_WON.bidcached);
events.emit(constants.EVENTS.AD_RENDER_SUCCEEDED, MOCK.AD_RENDER_SUCCEEDED.bidcached);
events.emit(constants.EVENTS.AD_RENDER_FAILED, MOCK.AD_RENDER_FAILED.bidcached);

expect(server.requests.length).to.equal(4);
expect(server.requests.length).to.equal(5, 'requests count');
{
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[0].url);
expect(protocol).to.equal('https');
Expand All @@ -708,13 +754,14 @@ describe('adagio analytics adapter', () => {
expect(search.site).to.equal('test-com');
expect(search.pv_id).to.equal('a68e6d70-213b-496c-be0a-c468ff387106');
expect(search.url_dmn).to.equal(window.location.hostname);
expect(search.dvc).to.equal('desktop');
expect(search.pgtyp).to.equal('article');
expect(search.plcmt).to.equal('pave_top');
expect(search.mts).to.equal('ban');
expect(search.ban_szs).to.equal('640x100,640x480');
expect(search.bdrs).to.equal('adagio,another');
expect(search.adg_mts).to.equal('ban');
expect(search.t_n).to.equal('test');
expect(search.t_v).to.equal('version');
}

{
Expand All @@ -730,12 +777,11 @@ describe('adagio analytics adapter', () => {
expect(search.site).to.equal('test-com');
expect(search.pv_id).to.equal('a68e6d70-213b-496c-be0a-c468ff387106');
expect(search.url_dmn).to.equal(window.location.hostname);
expect(search.dvc).to.equal('desktop');
expect(search.pgtyp).to.equal('article');
expect(search.plcmt).to.equal('pave_top');
expect(search.mts).to.equal('ban');
expect(search.ban_szs).to.equal('640x100,640x480');
expect(search.bdrs).to.equal('adagio,another');
expect(search.bdrs).to.equal('adagio,another,nobid');
expect(search.adg_mts).to.equal('ban');
}

Expand All @@ -745,10 +791,20 @@ describe('adagio analytics adapter', () => {
expect(hostname).to.equal('c.4dex.io');
expect(pathname).to.equal('/pba.gif');
expect(search.v).to.equal('2');
expect(search.e_sid).to.equal('42');
expect(search.e_pba_test).to.equal('true');
expect(search.bdrs_bid).to.equal('0,0,0');
}

{
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[3].url);
expect(protocol).to.equal('https');
expect(hostname).to.equal('c.4dex.io');
expect(pathname).to.equal('/pba.gif');
expect(search.v).to.equal('3');
expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
expect(search.auct_id_c).to.equal(AUCTION_ID_CACHE_ADAGIO);
expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
expect(search.adg_sid).to.equal('42');
expect(search.win_bdr).to.equal('adagio');
expect(search.win_mt).to.equal('ban');
expect(search.win_ban_sz).to.equal('728x90');
Expand All @@ -758,18 +814,19 @@ describe('adagio analytics adapter', () => {
expect(search.og_cpm).to.equal('1.42');
expect(search.og_cur).to.equal('USD');
expect(search.og_cur_rate).to.equal('1');
expect(search.rndr).to.not.exist;
}

{
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[3].url);
const { protocol, hostname, pathname, search } = utils.parseUrl(server.requests[4].url);
expect(protocol).to.equal('https');
expect(hostname).to.equal('c.4dex.io');
expect(pathname).to.equal('/pba.gif');
expect(search.v).to.equal('3');
expect(search.v).to.equal('4');
expect(search.auct_id).to.equal(AUCTION_ID_ADAGIO);
expect(search.auct_id_c).to.equal(AUCTION_ID_CACHE_ADAGIO);
expect(search.adu_code).to.equal('/19968336/header-bid-tag-1');
expect(search.rndr).to.equal('1');
expect(search.rndr).to.equal('0');
}
});
});
Expand Down

0 comments on commit 3ec81e6

Please sign in to comment.