modules/medianetAnalyticsAdapter.js
import {
_map,
deepAccess,
getWindowTop,
groupBy,
isEmpty,
isPlainObject,
logError,
logInfo,
triggerPixel,
uniques
} from '../src/utils.js';
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
import adapterManager from '../src/adapterManager.js';
import { BID_STATUS, EVENTS, TARGETING_KEYS } from '../src/constants.js';
import {ajax} from '../src/ajax.js';
import {getRefererInfo} from '../src/refererDetection.js';
import {AUCTION_COMPLETED, AUCTION_IN_PROGRESS, getPriceGranularity} from '../src/auction.js';
import {includes} from '../src/polyfill.js';
import {getGlobal} from '../src/prebidGlobal.js';
const analyticsType = 'endpoint';
const ENDPOINT = 'https://pb-logs.media.net/log?logid=kfk&evtid=prebid_analytics_events_client';
const CONFIG_URL = 'https://prebid.media.net/rtb/prebid/analytics/config';
const EVENT_PIXEL_URL = 'https://qsearch-a.akamaihd.net/log';
const DEFAULT_LOGGING_PERCENT = 50;
const ANALYTICS_VERSION = '1.0.0';
const PRICE_GRANULARITY = {
'auto': 'pbAg',
'custom': 'pbCg',
'dense': 'pbDg',
'low': 'pbLg',
'medium': 'pbMg',
'high': 'pbHg',
};
const MEDIANET_BIDDER_CODE = 'medianet';
// eslint-disable-next-line no-undef
const PREBID_VERSION = getGlobal().version;
const ERROR_CONFIG_JSON_PARSE = 'analytics_config_parse_fail';
const ERROR_CONFIG_FETCH = 'analytics_config_ajax_fail';
const ERROR_WINNING_BID_ABSENT = 'winning_bid_absent';
const ERROR_WINNING_AUCTION_MISSING = 'winning_auction_missing';
const BID_SUCCESS = 1;
const BID_NOBID = 2;
const BID_TIMEOUT = 3;
const BID_FLOOR_REJECTED = 12;
const DUMMY_BIDDER = '-2';
const CONFIG_PENDING = 0;
const CONFIG_PASS = 1;
const CONFIG_ERROR = 3;
const VALID_URL_KEY = ['canonical_url', 'og_url', 'twitter_url'];
const DEFAULT_URL_KEY = 'topmostLocation';
const LOG_TYPE = {
APPR: 'APPR',
RA: 'RA'
};
let auctions = {};
let config;
let pageDetails;
let logsQueue = [];
let errorQueue = [];
class ErrorLogger {
constructor(event, additionalData) {
this.event = event;
this.logid = 'kfk';
this.evtid = 'projectevents';
this.project = 'prebidanalytics';
this.dn = pageDetails.domain || '';
this.requrl = pageDetails.topmostLocation || '';
this.pbversion = PREBID_VERSION;
this.cid = config.cid || '';
this.rd = additionalData;
}
send() {
let url = EVENT_PIXEL_URL + '?' + formatQS(this);
errorQueue.push(url);
triggerPixel(url);
}
}
class Configure {
constructor(cid) {
this.cid = cid;
this.pubLper = -1;
this.ajaxState = CONFIG_PENDING;
this.loggingPercent = DEFAULT_LOGGING_PERCENT;
this.urlToConsume = DEFAULT_URL_KEY;
this.debug = false;
this.gdprConsent = undefined;
this.gdprApplies = undefined;
this.uspConsent = undefined;
this.shouldBeLogged = {};
this.mnetDebugConfig = '';
}
getLoggingData() {
return {
cid: this.cid,
lper: Math.round(100 / this.loggingPercent),
plper: this.pubLper,
gdpr: this.gdprApplies ? '1' : '0',
gdprConsent: this.gdprConsent,
ccpa: this.uspConsent,
ajx: this.ajaxState,
pbv: PREBID_VERSION,
pbav: ANALYTICS_VERSION,
flt: 1,
}
}
_configURL() {
return CONFIG_URL + '?cid=' + encodeURIComponent(this.cid) + '&dn=' + encodeURIComponent(pageDetails.domain);
}
_parseResponse(response) {
try {
response = JSON.parse(response);
this.setDataFromResponse(response);
this.overrideDomainLevelData(response);
this.overrideToDebug(this.mnetDebugConfig);
this.urlToConsume = includes(VALID_URL_KEY, response.urlKey) ? response.urlKey : this.urlToConsume;
this.ajaxState = CONFIG_PASS;
} catch (e) {
this.ajaxState = CONFIG_ERROR;
/* eslint no-new: "error" */
new ErrorLogger(ERROR_CONFIG_JSON_PARSE, e).send();
}
}
setDataFromResponse(response) {
if (!isNaN(parseInt(response.percentage, 10))) {
this.loggingPercent = response.percentage;
}
}
overrideDomainLevelData(response) {
const domain = deepAccess(response, 'domain.' + pageDetails.domain);
if (domain) {
this.setDataFromResponse(domain);
}
}
overrideToDebug(response) {
if (response === '') return;
try {
this.setDataFromResponse(JSON.parse(decodeURIComponent(response)));
} catch (e) {
}
}
_errorFetch() {
this.ajaxState = CONFIG_ERROR;
/* eslint no-new: "error" */
new ErrorLogger(ERROR_CONFIG_FETCH).send();
}
init() {
// Forces Logging % to 100%
let urlObj = URL.parseUrl(pageDetails.topmostLocation);
if (deepAccess(urlObj, 'search.medianet_test') || urlObj.hostname === 'localhost') {
this.loggingPercent = 100;
this.ajaxState = CONFIG_PASS;
this.debug = true;
return;
}
if (deepAccess(urlObj, 'search.mnet_setconfig')) {
this.mnetDebugConfig = deepAccess(urlObj, 'search.mnet_setconfig');
}
ajax(
this._configURL(),
{
success: this._parseResponse.bind(this),
error: this._errorFetch.bind(this)
}
);
}
}
class PageDetail {
constructor () {
const ogUrl = this._getUrlFromSelector('meta[property="og:url"]', 'content');
const twitterUrl = this._getUrlFromSelector('meta[name="twitter:url"]', 'content');
const refererInfo = getRefererInfo();
// TODO: are these the right refererInfo values?
this.domain = refererInfo.domain;
this.page = refererInfo.page;
this.is_top = refererInfo.reachedTop;
this.referrer = refererInfo.ref || window.document.referrer;
this.canonical_url = refererInfo.canonicalUrl;
this.og_url = ogUrl;
this.twitter_url = twitterUrl;
this.topmostLocation = refererInfo.topmostLocation;
this.screen = this._getWindowSize();
}
_getWindowSize() {
let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || -1;
let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || -1;
return `${w}x${h}`;
}
_getAttributeFromSelector(selector, attribute) {
try {
let doc = getWindowTop().document;
let element = doc.querySelector(selector);
if (element !== null && element[attribute]) {
return element[attribute];
}
} catch (e) {}
}
_getAbsoluteUrl(url) {
let aTag = getWindowTop().document.createElement('a');
aTag.href = url;
return aTag.href;
}
_getUrlFromSelector(selector, attribute) {
let attr = this._getAttributeFromSelector(selector, attribute);
return attr && this._getAbsoluteUrl(attr);
}
getLoggingData() {
return {
requrl: this[config.urlToConsume] || this.topmostLocation,
dn: this.domain,
ref: this.referrer,
screen: this.screen
}
}
}
class AdSlot {
constructor(tmax, supplyAdCode, context, adext) {
this.tmax = tmax;
this.supplyAdCode = supplyAdCode;
this.context = context;
this.adext = adext;
this.logged = {};
this.targeting = undefined;
this.medianetPresent = 0;
}
getShouldBeLogged(logType) {
if (!config.shouldBeLogged.hasOwnProperty(logType)) {
config.shouldBeLogged[logType] = isSampled();
}
return config.shouldBeLogged[logType];
}
getLoggingData() {
return Object.assign({
supcrid: this.supplyAdCode,
tmax: this.tmax,
targ: JSON.stringify(this.targeting),
ismn: this.medianetPresent,
vplcmtt: this.context,
},
this.adext && {'adext': JSON.stringify(this.adext)},
);
}
}
class BidWrapper {
constructor() {
this.bidReqs = [];
this.bidObjs = [];
}
findReqBid(bidId) {
return this.bidReqs.find(bid => {
return bid['bidId'] === bidId
});
}
findBidObj(key, value) {
return this.bidObjs.find(bid => {
return bid[key] === value
});
}
addBidReq(bidRequest) {
this.bidReqs.push(bidRequest)
}
addBidObj(bidObj) {
if (!(bidObj instanceof Bid)) {
bidObj = Bid.getInstance(bidObj);
}
const bidReq = this.findReqBid(bidObj.bidId);
if (bidReq instanceof Bid) {
bidReq.used = true;
}
this.bidObjs.push(bidObj);
}
getAdSlotBids(adSlot) {
const bidResponses = this.getAdSlotBidObjs(adSlot);
return bidResponses.map((bid) => bid.getLoggingData());
}
getAdSlotBidObjs(adSlot) {
const bidResponses = this.bidObjs
.filter((bid) => bid.adUnitCode === adSlot);
const remResponses = this.bidReqs.filter(bid => !bid.used && bid.adUnitCode === adSlot);
return [...bidResponses, ...remResponses];
}
}
class Bid {
constructor(bidId, bidder, src, start, adUnitCode, mediaType, allMediaTypeSizes) {
this.bidId = bidId;
this.bidder = bidder;
this.src = src;
this.start = start;
this.adUnitCode = adUnitCode;
this.allMediaTypeSizes = allMediaTypeSizes;
this.iwb = 0;
this.winner = 0;
this.status = bidder === DUMMY_BIDDER ? BID_SUCCESS : BID_TIMEOUT;
this.ext = {};
this.originalCpm = undefined;
this.cpm = undefined;
this.dfpbd = undefined;
this.width = undefined;
this.height = undefined;
this.mediaType = mediaType;
this.timeToRespond = undefined;
this.dealId = undefined;
this.creativeId = undefined;
this.adId = undefined;
this.currency = undefined;
this.crid = undefined;
this.pubcrid = undefined;
this.mpvid = undefined;
this.floorPrice = undefined;
this.floorRule = undefined;
this.serverLatencyMillis = undefined;
this.used = false;
this.originalRequestId = bidId;
this.requestId = undefined;
}
get size() {
if (!this.width || !this.height) {
return '';
}
return this.width + 'x' + this.height;
}
static getInstance(bidProps) {
const bidObj = new Bid();
return bidProps && Object.assign(bidObj, bidProps);
}
getLoggingData() {
return {
reqId: this.requestId || this.bidId,
ogReqId: this.originalRequestId,
adid: this.adId,
pvnm: this.bidder,
src: this.src,
ogbdp: this.originalCpm,
bdp: this.cpm,
cbdp: this.dfpbd,
dfpbd: this.dfpbd,
szs: this.allMediaTypeSizes.join('|'),
size: this.size,
mtype: this.mediaType,
dId: this.dealId,
winner: this.winner,
curr: this.currency,
rests: this.timeToRespond,
status: this.status,
iwb: this.iwb,
crid: this.crid,
pubcrid: this.pubcrid,
mpvid: this.mpvid,
bidflr: this.floorPrice,
flrrule: this.floorRule,
ext: JSON.stringify(this.ext),
rtime: this.serverLatencyMillis,
}
}
}
class Auction {
constructor(acid) {
this.acid = acid;
this.status = AUCTION_IN_PROGRESS;
this.bidWrapper = new BidWrapper();
this.adSlots = {};
this.auctionInitTime = undefined;
this.auctionStartTime = undefined;
this.setTargetingTime = undefined;
this.auctionEndTime = undefined;
this.bidWonTime = undefined;
this.floorData = {};
}
hasEnded() {
return this.status === AUCTION_COMPLETED;
}
getLoggingData() {
return {
sts: this.auctionStartTime - this.auctionInitTime,
ets: this.auctionEndTime - this.auctionInitTime,
tts: this.setTargetingTime - this.auctionInitTime,
wts: this.bidWonTime - this.auctionInitTime,
aucstatus: this.status,
acid: this.acid,
flrdata: this._mergeFieldsToLog({
ln: this.floorData.location,
skp: this.floorData.skipped,
enfj: deepAccess(this.floorData, 'enforcements.enforceJS'),
enfd: deepAccess(this.floorData, 'enforcements.floorDeals'),
sr: this.floorData.skipRate,
fs: this.floorData.fetchStatus
}),
flrver: this.floorData.modelVersion
}
}
addSlot({ adUnitCode, supplyAdCode, mediaTypes, allMediaTypeSizes, tmax, adext, context }) {
if (adUnitCode && this.adSlots[adUnitCode] === undefined) {
this.adSlots[adUnitCode] = new AdSlot(tmax, supplyAdCode, context, adext);
this.addBidObj(new Bid('-1', DUMMY_BIDDER, 'client', Date.now(), adUnitCode, mediaTypes, allMediaTypeSizes));
}
}
addBid(bid) {
this.bidWrapper.addBidReq(bid);
}
addBidObj(bidObj) {
this.bidWrapper.addBidObj(bidObj)
}
findReqBid(bidId) {
return this.bidWrapper.findReqBid(bidId)
}
findBidObj(key, value) {
return this.bidWrapper.findBidObj(key, value)
}
getAdSlotBids(adSlot) {
return this.bidWrapper.getAdSlotBids(adSlot);
}
getAdSlotBidObjs(adSlot) {
return this.bidWrapper.getAdSlotBidObjs(adSlot);
}
_mergeFieldsToLog(objParams) {
let logParams = [];
let value;
for (const param of Object.keys(objParams)) {
value = objParams[param];
logParams.push(param + '=' + (value === undefined ? '' : value));
}
return logParams.join('||');
}
}
function auctionInitHandler({auctionId, adUnits, timeout, timestamp, bidderRequests}) {
if (auctionId && auctions[auctionId] === undefined) {
auctions[auctionId] = new Auction(auctionId);
auctions[auctionId].auctionInitTime = timestamp;
}
addAddSlots(auctionId, adUnits, timeout);
const floorData = deepAccess(bidderRequests, '0.bids.0.floorData');
if (floorData) {
auctions[auctionId].floorData = {...floorData};
}
}
function addAddSlots(auctionId, adUnits, tmax) {
adUnits = adUnits || [];
const groupedAdUnits = groupBy(adUnits, 'code');
Object.keys(groupedAdUnits).forEach((adUnitCode) => {
const adUnits = groupedAdUnits[adUnitCode];
const supplyAdCode = deepAccess(adUnits, '0.adUnitCode') || adUnitCode;
let context = '';
let adext = {};
const mediaTypeMap = {};
const oSizes = {banner: [], video: []};
adUnits.forEach(({mediaTypes, sizes, ext}) => {
mediaTypes = mediaTypes || {};
adext = Object.assign(adext, ext || deepAccess(mediaTypes, 'banner.ext'));
context = deepAccess(mediaTypes, 'video.context') || context;
Object.keys(mediaTypes).forEach((mediaType) => mediaTypeMap[mediaType] = 1);
const sizeObject = _getSizes(mediaTypes, sizes);
sizeObject.banner.forEach(size => oSizes.banner.push(size));
sizeObject.video.forEach(size => oSizes.video.push(size));
});
adext = isEmpty(adext) ? undefined : adext;
oSizes.banner = oSizes.banner.filter(uniques);
oSizes.video = oSizes.video.filter(uniques);
oSizes.native = mediaTypeMap.native === 1 ? [[1, 1].join('x')] : [];
const allMediaTypeSizes = [].concat(oSizes.banner, oSizes.native, oSizes.video);
const mediaTypes = Object.keys(mediaTypeMap).join('|');
auctions[auctionId].addSlot({adUnitCode, supplyAdCode, mediaTypes, allMediaTypeSizes, context, tmax, adext});
});
}
function bidRequestedHandler({ auctionId, auctionStart, bids, start, uspConsent, gdpr }) {
if (!(auctions[auctionId] instanceof Auction)) {
return;
}
config.gdprApplies = !!(gdpr && gdpr.gdprApplies);
if (config.gdprApplies) {
config.gdprConsent = gdpr.consentString || '';
}
config.uspConsent = config.uspConsent || uspConsent;
auctions[auctionId].auctionStartTime = auctionStart;
bids.forEach(bid => {
const { adUnitCode, bidder, bidId, src, mediaTypes, sizes } = bid;
const sizeObject = _getSizes(mediaTypes, sizes);
const requestSizes = [].concat(sizeObject.banner, sizeObject.native, sizeObject.video);
const bidObj = new Bid(bidId, bidder, src, start, adUnitCode, mediaTypes && Object.keys(mediaTypes).join('|'), requestSizes);
auctions[auctionId].addBid(bidObj);
if (bidder === MEDIANET_BIDDER_CODE) {
bidObj.crid = deepAccess(bid, 'params.crid');
bidObj.pubcrid = deepAccess(bid, 'params.crid');
auctions[auctionId].adSlots[adUnitCode].medianetPresent = 1;
}
});
}
function _getSizes(mediaTypes, sizes) {
const banner = deepAccess(mediaTypes, 'banner.sizes') || sizes || [];
const native = deepAccess(mediaTypes, 'native') ? [[1, 1]] : [];
const playerSize = deepAccess(mediaTypes, 'video.playerSize') || [];
let video = [];
if (playerSize.length === 2) {
video = [playerSize]
}
return {
banner: banner.map(size => size.join('x')),
native: native.map(size => size.join('x')),
video: video.map(size => size.join('x'))
}
}
function bidResponseHandler(bid) {
const { width, height, mediaType, cpm, requestId, timeToRespond, auctionId, dealId, originalRequestId, bidder } = bid;
const {originalCpm, creativeId, adId, currency} = bid;
if (!(auctions[auctionId] instanceof Auction)) {
return;
}
const reqId = originalRequestId || requestId;
const bidReq = auctions[auctionId].findReqBid(reqId);
if (!(bidReq instanceof Bid)) return;
let bidObj = auctions[auctionId].findBidObj('bidId', requestId);
let isBidOverridden = true;
if (!bidObj || bidObj.status === BID_SUCCESS) {
bidObj = {};
isBidOverridden = false;
}
Object.assign(bidObj, bidReq,
{ cpm, width, height, mediaType, timeToRespond, dealId, creativeId, originalRequestId, requestId },
{ adId, currency }
);
bidObj.floorPrice = deepAccess(bid, 'floorData.floorValue');
bidObj.floorRule = deepAccess(bid, 'floorData.floorRule');
bidObj.originalCpm = originalCpm || cpm;
let dfpbd = deepAccess(bid, 'adserverTargeting.hb_pb');
if (!dfpbd) {
let priceGranularity = getPriceGranularity(bid);
let priceGranularityKey = PRICE_GRANULARITY[priceGranularity];
dfpbd = bid[priceGranularityKey] || cpm;
}
bidObj.dfpbd = dfpbd;
if (bid.status === BID_STATUS.BID_REJECTED) {
bidObj.status = BID_FLOOR_REJECTED;
} else {
bidObj.status = BID_SUCCESS;
}
if (bidder === MEDIANET_BIDDER_CODE && bid.ext instanceof Object) {
Object.assign(
bidObj,
{ 'ext': bid.ext },
{ 'mpvid': bid.ext.pvid },
bid.ext.crid && { 'crid': bid.ext.crid }
);
}
if (typeof bid.serverResponseTimeMs !== 'undefined') {
bidObj.serverLatencyMillis = bid.serverResponseTimeMs;
}
!isBidOverridden && auctions[auctionId].addBidObj(bidObj);
}
function noBidResponseHandler({ auctionId, bidId }) {
if (!(auctions[auctionId] instanceof Auction)) {
return;
}
if (auctions[auctionId].hasEnded()) {
return;
}
const bidReq = auctions[auctionId].findReqBid(bidId);
if (!(bidReq instanceof Bid) || bidReq.used) {
return;
}
const bidObj = {...bidReq};
bidObj.status = BID_NOBID;
auctions[auctionId].addBidObj(bidObj);
}
function bidTimeoutHandler(timedOutBids) {
timedOutBids.map(({bidId, auctionId}) => {
if (!(auctions[auctionId] instanceof Auction)) {
return;
}
const bidReq = auctions[auctionId].findReqBid('bidId', bidId);
if (!(bidReq instanceof Bid) || bidReq.used) {
return;
}
const bidObj = {...bidReq};
bidObj.status = BID_TIMEOUT;
auctions[auctionId].addBidObj(bidObj);
})
}
function auctionEndHandler({auctionId, auctionEnd}) {
if (!(auctions[auctionId] instanceof Auction)) {
return;
}
auctions[auctionId].status = AUCTION_COMPLETED;
auctions[auctionId].auctionEndTime = auctionEnd;
}
function setTargetingHandler(params) {
for (const adunit of Object.keys(params)) {
for (const auctionId of Object.keys(auctions)) {
let auctionObj = auctions[auctionId];
let adunitObj = auctionObj.adSlots[adunit];
if (!(adunitObj instanceof AdSlot)) {
continue;
}
adunitObj.targeting = params[adunit];
auctionObj.setTargetingTime = Date.now();
let targetingObj = Object.keys(params[adunit]).reduce((result, key) => {
if (key.indexOf(TARGETING_KEYS.AD_ID) !== -1) {
result[key] = params[adunit][key]
}
return result;
}, {});
const winnerAdId = params[adunit][TARGETING_KEYS.AD_ID];
let winningBid;
let bidAdIds = Object.keys(targetingObj).map(k => targetingObj[k]);
auctionObj.bidWrapper.bidObjs.filter((bid) => bidAdIds.indexOf(bid.adId) !== -1).map(function(bid) {
bid.iwb = 1;
if (bid.adId === winnerAdId) {
winningBid = bid;
}
});
auctionObj.bidWrapper.bidObjs.forEach(bid => {
if (bid.bidder === DUMMY_BIDDER && bid.adUnitCode === adunit) {
bid.iwb = bidAdIds.length === 0 ? 0 : 1;
bid.width = deepAccess(winningBid, 'width');
bid.height = deepAccess(winningBid, 'height');
}
});
sendEvent(auctionId, adunit, LOG_TYPE.APPR);
}
}
}
function bidWonHandler(bid) {
const { auctionId, adUnitCode, adId, bidder, requestId, originalRequestId } = bid;
if (!(auctions[auctionId] instanceof Auction)) {
new ErrorLogger(ERROR_WINNING_AUCTION_MISSING, {
adId,
auctionId,
adUnitCode,
bidder,
requestId,
originalRequestId
}).send();
return;
}
let bidObj = auctions[auctionId].findBidObj('adId', adId);
if (!(bidObj instanceof Bid)) {
new ErrorLogger(ERROR_WINNING_BID_ABSENT, {
adId,
auctionId,
adUnitCode,
bidder,
requestId,
originalRequestId
}).send();
return;
}
auctions[auctionId].bidWonTime = Date.now();
bidObj.winner = 1;
sendEvent(auctionId, adUnitCode, LOG_TYPE.RA, bidObj.adId);
}
function isSampled() {
return Math.random() * 100 < parseFloat(config.loggingPercent);
}
function isValidAuctionAdSlot(acid, adtag) {
return (auctions[acid] instanceof Auction) && (auctions[acid].adSlots[adtag] instanceof AdSlot);
}
function sendEvent(id, adunit, logType, adId) {
if (!isValidAuctionAdSlot(id, adunit)) {
return;
}
if (logType === LOG_TYPE.RA) {
fireAuctionLog(id, adunit, logType, adId);
} else {
fireApPrLog(id, adunit, logType)
}
}
function fireApPrLog(auctionId, adUnitName, logType) {
const adSlot = auctions[auctionId].adSlots[adUnitName];
if (adSlot.getShouldBeLogged(logType) && !adSlot.logged[logType]) {
fireAuctionLog(auctionId, adUnitName, logType);
adSlot.logged[logType] = true;
}
}
function getCommonLoggingData(acid, adtag) {
let commonParams = Object.assign(pageDetails.getLoggingData(), config.getLoggingData());
let adunitParams = auctions[acid].adSlots[adtag].getLoggingData();
let auctionParams = auctions[acid].getLoggingData();
return Object.assign(commonParams, adunitParams, auctionParams);
}
function fireAuctionLog(acid, adtag, logType, adId) {
let commonParams = getCommonLoggingData(acid, adtag);
commonParams.lgtp = logType;
let targeting = deepAccess(commonParams, 'targ');
Object.keys(commonParams).forEach((key) => (commonParams[key] == null) && delete commonParams[key]);
delete commonParams.targ;
let bidParams;
if (logType === LOG_TYPE.RA) {
const winningBidObj = auctions[acid].findBidObj('adId', adId);
if (!winningBidObj) return;
const winLogData = winningBidObj.getLoggingData();
bidParams = [winLogData];
commonParams.lper = 1;
} else {
bidParams = auctions[acid].getAdSlotBids(adtag).map(({winner, ...restParams}) => restParams);
delete commonParams.wts;
}
let mnetPresent = bidParams.filter(b => b.pvnm === MEDIANET_BIDDER_CODE).length > 0;
if (!mnetPresent) {
bidParams = bidParams.map(({mpvid, crid, ext, pubcrid, ...restParams}) => restParams);
}
let url = formatQS(commonParams) + '&';
bidParams.forEach(function(bidParams) {
url = url + formatQS(bidParams) + '&';
});
url = url + formatQS({targ: targeting});
firePixel(url);
}
function formatQS(data) {
return _map(data, (value, key) => {
if (value === undefined) {
return key + '=';
}
if (isPlainObject(value)) {
value = JSON.stringify(value);
}
return key + '=' + encodeURIComponent(value);
}).join('&');
}
function firePixel(qs) {
logsQueue.push(ENDPOINT + '&' + qs);
triggerPixel(ENDPOINT + '&' + qs);
}
class URL {
static parseUrl(url) {
let parsed = document.createElement('a');
parsed.href = decodeURIComponent(url);
return {
hostname: parsed.hostname,
search: URL.parseQS(parsed.search || ''),
host: parsed.host || window.location.host
};
}
static parseQS(query) {
return !query ? {} : query
.replace(/^\?/, '')
.split('&')
.reduce((acc, criteria) => {
let [k, v] = criteria.split('=');
if (/\[\]$/.test(k)) {
k = k.replace('[]', '');
acc[k] = acc[k] || [];
acc[k].push(v);
} else {
acc[k] = v || '';
}
return acc;
}, {});
}
}
let medianetAnalytics = Object.assign(adapter({URL, analyticsType}), {
getlogsQueue() {
return logsQueue;
},
getErrorQueue() {
return errorQueue;
},
clearlogsQueue() {
logsQueue = [];
errorQueue = [];
auctions = {};
},
track({ eventType, args }) {
if (config.debug) {
logInfo(eventType, args);
}
switch (eventType) {
case EVENTS.AUCTION_INIT: {
auctionInitHandler(args);
break;
}
case EVENTS.BID_REQUESTED: {
bidRequestedHandler(args);
break;
}
case EVENTS.BID_RESPONSE: {
bidResponseHandler(args);
break;
}
case EVENTS.BID_TIMEOUT: {
bidTimeoutHandler(args);
break;
}
case EVENTS.NO_BID: {
noBidResponseHandler(args);
break;
}
case EVENTS.AUCTION_END: {
auctionEndHandler(args);
break;
}
case EVENTS.SET_TARGETING: {
setTargetingHandler(args);
break;
}
case EVENTS.BID_WON: {
bidWonHandler(args);
break;
}
}
}});
medianetAnalytics.originEnableAnalytics = medianetAnalytics.enableAnalytics;
medianetAnalytics.enableAnalytics = function (configuration) {
if (!configuration || !configuration.options || !configuration.options.cid) {
logError('Media.net Analytics adapter: cid is required.');
return;
}
getGlobal().medianetGlobals = getGlobal().medianetGlobals || {};
getGlobal().medianetGlobals.analyticsEnabled = true;
pageDetails = new PageDetail();
config = new Configure(configuration.options.cid);
config.pubLper = configuration.options.sampling || '';
config.init();
configuration.options.sampling = 1;
medianetAnalytics.originEnableAnalytics(configuration);
};
adapterManager.registerAnalyticsAdapter({
adapter: medianetAnalytics,
code: 'medianetAnalytics',
gvlid: 142,
});
export default medianetAnalytics;