mk9-prebid
Version:
Header Bidding Management Library
217 lines (196 loc) • 6.35 kB
JavaScript
/**
* Adapter to send bids to Undertone
*/
import { deepAccess, parseUrl } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import {BANNER, VIDEO} from '../src/mediaTypes.js';
const BIDDER_CODE = 'undertone';
const URL = 'https://hb.undertone.com/hb';
const FRAME_USER_SYNC = 'https://cdn.undertone.com/js/usersync.html';
const PIXEL_USER_SYNC_1 = 'https://usr.undertone.com/userPixel/syncOne?id=1&of=2';
const PIXEL_USER_SYNC_2 = 'https://usr.undertone.com/userPixel/syncOne?id=2&of=2';
function getCanonicalUrl() {
try {
let doc = window.top.document;
let element = doc.querySelector("link[rel='canonical']");
if (element !== null) {
return element.href;
}
} catch (e) {
}
return null;
}
function extractDomainFromHost(pageHost) {
let domain = null;
try {
let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost);
if (domains != null && domains.length > 0) {
domain = domains[0];
for (let i = 1; i < domains.length; i++) {
if (domains[i].length > domain.length) {
domain = domains[i];
}
}
}
} catch (e) {
domain = null;
}
return domain;
}
function getGdprQueryParams(gdprConsent) {
if (!gdprConsent) {
return null;
}
let gdpr = gdprConsent.gdprApplies ? '1' : '0';
let gdprstr = gdprConsent.consentString ? gdprConsent.consentString : '';
return `gdpr=${gdpr}&gdprstr=${gdprstr}`;
}
function getBannerCoords(id) {
let element = document.getElementById(id);
let left = -1;
let top = -1;
if (element) {
left = element.offsetLeft;
top = element.offsetTop;
let parent = element.offsetParent;
if (parent) {
left += parent.offsetLeft;
top += parent.offsetTop;
}
return [left, top];
} else {
return null;
}
}
export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid: function(bid) {
if (bid && bid.params && bid.params.publisherId) {
bid.params.publisherId = parseInt(bid.params.publisherId);
return true;
}
},
buildRequests: function(validBidRequests, bidderRequest) {
const vw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
const pageSizeArray = vw == 0 || vh == 0 ? null : [vw, vh];
const payload = {
'x-ut-hb-params': [],
'commons': {
'adapterVersion': '$prebid.version$',
'uids': validBidRequests[0].userId,
'pageSize': pageSizeArray
}
};
const referer = bidderRequest.refererInfo.referer;
const hostname = parseUrl(referer).hostname;
let domain = extractDomainFromHost(hostname);
const pageUrl = getCanonicalUrl() || referer;
const pubid = validBidRequests[0].params.publisherId;
let reqUrl = `${URL}?pid=${pubid}&domain=${domain}`;
let gdprParams = getGdprQueryParams(bidderRequest.gdprConsent);
if (gdprParams) {
reqUrl += `&${gdprParams}`;
}
if (bidderRequest.uspConsent) {
reqUrl += `&ccpa=${bidderRequest.uspConsent}`;
}
validBidRequests.map(bidReq => {
const bid = {
bidRequestId: bidReq.bidId,
coordinates: getBannerCoords(bidReq.adUnitCode),
hbadaptor: 'prebid',
url: pageUrl,
domain: domain,
placementId: bidReq.params.placementId != undefined ? bidReq.params.placementId : null,
publisherId: bidReq.params.publisherId,
sizes: bidReq.sizes,
params: bidReq.params
};
const videoMediaType = deepAccess(bidReq, 'mediaTypes.video');
if (videoMediaType) {
bid.video = {
playerSize: deepAccess(bidReq, 'mediaTypes.video.playerSize') || null,
streamType: deepAccess(bidReq, 'mediaTypes.video.context') || null,
playbackMethod: deepAccess(bidReq, 'params.video.playbackMethod') || null,
maxDuration: deepAccess(bidReq, 'params.video.maxDuration') || null,
skippable: deepAccess(bidReq, 'params.video.skippable') || null
};
bid.mediaType = 'video';
}
payload['x-ut-hb-params'].push(bid);
});
return {
method: 'POST',
url: reqUrl,
withCredentials: true,
data: JSON.stringify(payload)
};
},
interpretResponse: function(serverResponse, request) {
const bids = [];
const body = serverResponse.body;
if (body && Array.isArray(body) && body.length > 0) {
body.forEach((bidRes) => {
if (bidRes.ad && bidRes.cpm > 0) {
const bid = {
requestId: bidRes.bidRequestId,
cpm: bidRes.cpm,
width: bidRes.width,
height: bidRes.height,
creativeId: bidRes.adId,
currency: bidRes.currency,
netRevenue: bidRes.netRevenue,
ttl: bidRes.ttl || 360,
meta: { advertiserDomains: bidRes.adomain ? bidRes.adomain : [] }
};
if (bidRes.mediaType && bidRes.mediaType === 'video') {
bid.vastXml = bidRes.ad;
bid.mediaType = bidRes.mediaType;
} else {
bid.ad = bidRes.ad
}
bids.push(bid);
}
});
}
return bids;
},
getUserSyncs: function(syncOptions, serverResponses, gdprConsent, usPrivacy) {
const syncs = [];
let gdprParams = getGdprQueryParams(gdprConsent);
let iframePrivacyParams = '';
let pixelPrivacyParams = '';
if (gdprParams) {
iframePrivacyParams += `?${gdprParams}`;
pixelPrivacyParams += `&${gdprParams}`;
}
if (usPrivacy) {
if (iframePrivacyParams != '') {
iframePrivacyParams += '&'
} else {
iframePrivacyParams += '?'
}
iframePrivacyParams += `ccpa=${usPrivacy}`;
pixelPrivacyParams += `&ccpa=${usPrivacy}`;
}
if (syncOptions.iframeEnabled) {
syncs.push({
type: 'iframe',
url: FRAME_USER_SYNC + iframePrivacyParams
});
} else if (syncOptions.pixelEnabled) {
syncs.push({
type: 'image',
url: PIXEL_USER_SYNC_1 + pixelPrivacyParams
},
{
type: 'image',
url: PIXEL_USER_SYNC_2 + pixelPrivacyParams
});
}
return syncs;
}
};
registerBidder(spec);