Skip to content

Commit

Permalink
AdagioAnalyticsAdapter: send PBA for all auctions (prebid#11961)
Browse files Browse the repository at this point in the history
* AdagioAnalyticsAdapter: send PBA for all auctions

* AdagioAnalyticsAdapter: typo

* AdagioAnalyticsAdapter: update md file

---------

Co-authored-by: Olivier <[email protected]>
  • Loading branch information
Abyfall and osazos authored Jul 15, 2024
1 parent eccf064 commit 6a85621
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 96 deletions.
128 changes: 83 additions & 45 deletions modules/adagioAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

import { _ADAGIO, getBestWindowForAdagio } from '../libraries/adagioUtils/adagioUtils.js';
import { deepAccess, logError, logInfo } from '../src/utils.js';
import { deepAccess, logError, logInfo, logWarn } from '../src/utils.js';
import { BANNER } from '../src/mediaTypes.js';
import { EVENTS } from '../src/constants.js';
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
Expand Down Expand Up @@ -130,6 +130,10 @@ function getCurrencyData(bid) {
* @param {Object} qp
*/
function sendRequest(qp) {
if (!qp.org_id || !qp.site) {
logInfo('request is missing org_id or site, skipping beacon.');
return;
}
// Removing null values
qp = Object.keys(qp).reduce((acc, key) => {
if (qp[key] !== null) {
Expand Down Expand Up @@ -180,33 +184,22 @@ function handlerAuctionInit(event) {
const adUnitCodes = removeDuplicates(event.adUnitCodes, adUnitCode => adUnitCode);

// Check if Adagio is on the bid requests.
// If not, we don't need to track the auction.
const adagioBidRequest = event.bidderRequests.find(bidRequest => isAdagio(bidRequest.bidderCode));
if (!adagioBidRequest) {
logInfo(`Adagio is not on the bid requests for auction '${prebidAuctionId}'`)
return;
}

const rtdUid = deepAccess(adagioBidRequest, 'ortb2.site.ext.data.adg_rtd.uid');
cache.addPrebidAuctionIdRef(prebidAuctionId, rtdUid);

cache.auctions[prebidAuctionId] = {};

adUnitCodes.forEach(adUnitCode => {
// event.adUnits are splitted by mediatypes
const adUnits = event.adUnits.filter(adUnit => adUnit.code === adUnitCode);

// Get all bidders configures for the ad unit.
const bidders = removeDuplicates(
adUnits.map(adUnit => adUnit.bids.map(bid => ({bidder: bid.bidder, params: bid.params}))).flat(),
bidder => bidder.bidder
);

// Check if Adagio is configured for the ad unit.
// If not, we don't need to track the ad unit.
const adagioBidder = bidders.find(bidder => isAdagio(bidder.bidder));
if (!adagioBidder) {
logInfo(`Adagio is not configured for ad unit '${adUnitCode}'`);
return;
}
// Get all bidders configured for the ad unit.
// AdUnits with the same code can have a different bidder list, aggregate all of them.
const biddersAggregate = adUnits.reduce((bidders, adUnit) => bidders.concat(adUnit.bids.map(bid => bid.bidder)), [])
// remove duplicates
const bidders = [...new Set(biddersAggregate)];

// Get all media types and banner sizes configured for the ad unit.
const mediaTypes = adUnits.map(adUnit => adUnit.mediaTypes);
Expand All @@ -221,45 +214,56 @@ function handlerAuctionInit(event) {
bannerSize => bannerSize
).sort();

// Get all Adagio bids for the ad unit from the bidRequest.
// If no bids, we don't need to track the ad unit.
const adagioAdUnitBids = adagioBidRequest.bids.filter(bid => bid.adUnitCode === adUnitCode);
if (deepAccess(adagioAdUnitBids, 'length', 0) <= 0) {
logInfo(`Adagio is not on the bid requests for ad unit '${adUnitCode}' and auction '${prebidAuctionId}'`)
return;
}
// Get Adagio params from the first bid.
// We assume that all Adagio bids for a same adunit have the same params.
const params = adagioAdUnitBids[0].params;
const sortedBidderCodes = bidders.sort()

// Get all media types requested for Adagio.
const adagioMediaTypes = removeDuplicates(
adagioAdUnitBids.map(bid => Object.keys(bid.mediaTypes)).flat(),
mediaTypeKey => mediaTypeKey
).flat().map(mediaType => getMediaTypeAlias(mediaType)).sort();
const bidSrcMapper = (bidder) => {
const request = event.bidderRequests.find(br => br.bidderCode === bidder)
return request ? request.bids[0].src : null
}
const biddersSrc = sortedBidderCodes.map(bidSrcMapper).join(',');

// if adagio was involved in the auction we identified it with rtdUid, if not use the prebid auctionId
let auctionId = rtdUid || prebidAuctionId;
const auctionId = rtdUid || prebidAuctionId;

const adgRtdSession = deepAccess(event.bidderRequests[0], 'ortb2.site.ext.data.adg_rtd.session', {});

const qp = {
org_id: adagioAdapter.options.organizationId,
site: adagioAdapter.options.site,
v: 0,
pbjsv: PREBID_VERSION,
org_id: params.organizationId,
site: params.site,
pv_id: params.pageviewId,
pv_id: _internal.getAdagioNs().pageviewId,
auct_id: auctionId,
adu_code: adUnitCode,
url_dmn: w.location.hostname,
pgtyp: params.pagetype,
plcmt: params.placement,
t_n: params.testName || null,
t_v: params.testVersion || null,
mts: mediaTypesKeys.join(','),
ban_szs: bannerSizes.join(','),
bdrs: bidders.map(bidder => bidder.bidder).sort().join(','),
adg_mts: adagioMediaTypes.join(',')
bdrs: sortedBidderCodes.join(','),
pgtyp: deepAccess(event.bidderRequests[0], 'ortb2.site.ext.data.pagetype', null),
plcmt: deepAccess(adUnits[0], 'ortb2Imp.ext.data.placement', null),
t_n: adgRtdSession.testName || null,
t_v: adgRtdSession.testVersion || null,
s_id: adgRtdSession.id || null,
s_new: adgRtdSession.new || null,
bdrs_src: biddersSrc,
};

if (adagioBidRequest && adagioBidRequest.bids) {
const adagioAdUnitBids = adagioBidRequest.bids.filter(bid => bid.adUnitCode === adUnitCode);
if (adagioAdUnitBids.length > 0) {
// Get all media types requested for Adagio.
const adagioMediaTypes = removeDuplicates(
adagioAdUnitBids.map(bid => Object.keys(bid.mediaTypes)).flat(),
mediaTypeKey => mediaTypeKey
).flat().map(mediaType => getMediaTypeAlias(mediaType)).sort();

qp.adg_mts = adagioMediaTypes.join(',');
// for backward compatibility: if we didn't find organizationId & site but we have a bid from adagio we might still find it in params
qp.org_id = qp.org_id || adagioAdUnitBids[0].params.organizationId;
qp.site = qp.site || adagioAdUnitBids[0].params.site;
}
}

cache.auctions[prebidAuctionId][adUnitCode] = qp;
sendNewBeacon(prebidAuctionId, adUnitCode);
});
Expand Down Expand Up @@ -306,13 +310,21 @@ function handlerAuctionEnd(event) {
return bid ? getCurrencyData(bid).netCpm : null
}

const perfNavigation = performance.getEntriesByType('navigation')[0];

cache.updateAuction(auctionId, adUnitCode, {
bdrs_bid: cache.getBiddersFromAuction(auctionId, adUnitCode).map(bidResponseMapper).join(','),
bdrs_cpm: cache.getBiddersFromAuction(auctionId, adUnitCode).map(bidCpmMapper).join(',')
bdrs_cpm: cache.getBiddersFromAuction(auctionId, adUnitCode).map(bidCpmMapper).join(','),
// check timings at the end of the auction to leave time to the browser to update it
dom_i: Math.round(perfNavigation['domInteractive']) || null,
dom_c: Math.round(perfNavigation['domComplete']) || null,
loa_e: Math.round(perfNavigation['loadEventEnd']) || null,
});

sendNewBeacon(auctionId, adUnitCode);
});
}

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

Expand All @@ -326,6 +338,9 @@ function handlerBidWon(event) {
(event.latestTargetedAuctionId && event.latestTargetedAuctionId !== event.auctionId)
? cache.getAdagioAuctionId(event.auctionId)
: null);

const perfNavigation = performance.getEntriesByType('navigation')[0];

cache.updateAuction(auctionId, event.adUnitCode, {
win_bdr: event.bidder,
win_mt: getMediaTypeAlias(event.mediaType),
Expand All @@ -334,6 +349,11 @@ function handlerBidWon(event) {
win_net_cpm: currencyData.netCpm,
win_og_cpm: currencyData.orginalCpm,

// check timings at the end of the auction to leave time to the browser to update it
dom_i: Math.round(perfNavigation['domInteractive']) || null,
dom_c: Math.round(perfNavigation['domComplete']) || null,
loa_e: Math.round(perfNavigation['loadEventEnd']) || null,

// cache bid id
auct_id_c: adagioAuctionCacheId,
});
Expand Down Expand Up @@ -405,6 +425,24 @@ adagioAdapter.originEnableAnalytics = adagioAdapter.enableAnalytics;
adagioAdapter.enableAnalytics = config => {
_internal.getAdagioNs().versions.adagioAnalyticsAdapter = VERSION;

let modules = getGlobal().installedModules;
if (modules && (!modules.length || modules.indexOf('adagioRtdProvider') === -1 || modules.indexOf('rtdModule') === -1)) {
logError('Adagio Analytics Adapter requires rtdModule & adagioRtdProvider modules which are not installed. No beacon will be sent');
return;
}

adagioAdapter.options = config.options || {};
if (!adagioAdapter.options.organizationId) {
logWarn('Adagio Analytics Adapter: organizationId is required and is missing will try to fallback on params.');
} else {
adagioAdapter.options.organizationId = adagioAdapter.options.organizationId.toString(); // allows publisher to pass it as a number
}
if (!adagioAdapter.options.site) {
logWarn('Adagio Analytics Adapter: site is required and is missing will try to fallback on params.');
} else if (typeof adagioAdapter.options.site !== 'string') {
logWarn('Adagio Analytics Adapter: site should be a string will try to fallback on params.');
adagioAdapter.options.site = undefined;
}
adagioAdapter.originEnableAnalytics(config);
}

Expand Down
4 changes: 4 additions & 0 deletions modules/adagioAnalyticsAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@ Analytics adapter for Adagio
```js
pbjs.enableAnalytics({
provider: 'adagio',
options: {
organizationId: '1000', // Required. Provided by Adagio
site: 'my-website', // Required. Provided by Adagio
}
});
```
Loading

0 comments on commit 6a85621

Please sign in to comment.