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

AdagioAnalyticsAdapter: send PBA for all auctions #11961

Merged
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
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