mk9-prebid
Version:
Header Bidding Management Library
344 lines (288 loc) • 9.1 kB
JavaScript
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import * as utils from '../src/utils.js';
import { config } from '../src/config.js';
const GVLID = 28;
const BIDDER_CODE = 'triplelift';
const STR_ENDPOINT = 'https://tlx.3lift.com/header/auction?';
let gdprApplies = true;
let consentString = null;
export const tripleliftAdapterSpec = {
gvlid: GVLID,
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid: function (bid) {
return typeof bid.params.inventoryCode !== 'undefined';
},
buildRequests: function(bidRequests, bidderRequest) {
let tlCall = STR_ENDPOINT;
let data = _buildPostBody(bidRequests);
tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid');
tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$');
if (bidderRequest && bidderRequest.refererInfo) {
let referrer = bidderRequest.refererInfo.referer;
tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer);
}
if (bidderRequest && bidderRequest.timeout) {
tlCall = utils.tryAppendQueryString(tlCall, 'tmax', bidderRequest.timeout);
}
if (bidderRequest && bidderRequest.gdprConsent) {
if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') {
gdprApplies = bidderRequest.gdprConsent.gdprApplies;
tlCall = utils.tryAppendQueryString(tlCall, 'gdpr', gdprApplies.toString());
}
if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') {
consentString = bidderRequest.gdprConsent.consentString;
tlCall = utils.tryAppendQueryString(tlCall, 'cmp_cs', consentString);
}
}
if (bidderRequest && bidderRequest.uspConsent) {
tlCall = utils.tryAppendQueryString(tlCall, 'us_privacy', bidderRequest.uspConsent);
}
if (config.getConfig('coppa') === true) {
tlCall = utils.tryAppendQueryString(tlCall, 'coppa', true);
}
if (tlCall.lastIndexOf('&') === tlCall.length - 1) {
tlCall = tlCall.substring(0, tlCall.length - 1);
}
utils.logMessage('tlCall request built: ' + tlCall);
return {
method: 'POST',
url: tlCall,
data,
bidderRequest
};
},
interpretResponse: function(serverResponse, {bidderRequest}) {
let bids = serverResponse.body.bids || [];
return bids.map(function(bid) {
return _buildResponseObject(bidderRequest, bid);
});
},
getUserSyncs: function(syncOptions, responses, gdprConsent, usPrivacy) {
let syncType = _getSyncType(syncOptions);
if (!syncType) return;
let syncEndpoint = 'https://eb2.3lift.com/sync?';
if (syncType === 'image') {
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'px', 1);
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'src', 'prebid');
}
if (consentString !== null) {
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'gdpr', gdprApplies);
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'cmp_cs', consentString);
}
if (usPrivacy) {
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'us_privacy', usPrivacy);
}
return [{
type: syncType,
url: syncEndpoint
}];
}
}
function _getSyncType(syncOptions) {
if (!syncOptions) return;
if (syncOptions.iframeEnabled) return 'iframe';
if (syncOptions.pixelEnabled) return 'image';
}
function _buildPostBody(bidRequests) {
let data = {};
let { schain } = bidRequests[0];
const globalFpd = _getGlobalFpd();
data.imp = bidRequests.map(function(bidRequest, index) {
let imp = {
id: index,
tagid: bidRequest.params.inventoryCode,
floor: _getFloor(bidRequest)
};
// remove the else to support multi-imp
if (_isInstreamBidRequest(bidRequest)) {
imp.video = _getORTBVideo(bidRequest);
} else if (bidRequest.mediaTypes.banner) {
imp.banner = { format: _sizes(bidRequest.sizes) };
};
if (!utils.isEmpty(bidRequest.ortb2Imp)) {
imp.fpd = _getAdUnitFpd(bidRequest.ortb2Imp);
}
return imp;
});
let eids = [
...getUnifiedIdEids([bidRequests[0]]),
...getIdentityLinkEids([bidRequests[0]]),
...getCriteoEids([bidRequests[0]]),
...getPubCommonEids([bidRequests[0]])
];
if (eids.length > 0) {
data.user = {
ext: {eids}
};
}
let ext = _getExt(schain, globalFpd);
if (!utils.isEmpty(ext)) {
data.ext = ext;
}
return data;
}
function _isInstreamBidRequest(bidRequest) {
if (!bidRequest.mediaTypes.video) return false;
if (!bidRequest.mediaTypes.video.context) return false;
if (bidRequest.mediaTypes.video.context.toLowerCase() === 'instream') {
return true;
} else {
return false;
}
}
function _getORTBVideo(bidRequest) {
// give precedent to mediaTypes.video
let video = { ...bidRequest.params.video, ...bidRequest.mediaTypes.video };
if (!video.w) video.w = video.playerSize[0][0];
if (!video.h) video.h = video.playerSize[0][1];
if (video.context === 'instream') video.placement = 1;
// clean up oRTB object
delete video.playerSize;
return video;
}
function _getFloor (bid) {
let floor = null;
if (typeof bid.getFloor === 'function') {
const floorInfo = bid.getFloor({
currency: 'USD',
mediaType: _isInstreamBidRequest(bid) ? 'video' : 'banner',
size: '*'
});
if (typeof floorInfo === 'object' &&
floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) {
floor = parseFloat(floorInfo.floor);
}
}
return floor !== null ? floor : bid.params.floor;
}
function _getGlobalFpd() {
const fpd = {};
const context = {}
const user = {};
const ortbData = config.getLegacyFpd(config.getConfig('ortb2')) || {};
const fpdContext = Object.assign({}, ortbData.context);
const fpdUser = Object.assign({}, ortbData.user);
_addEntries(context, fpdContext);
_addEntries(user, fpdUser);
if (!utils.isEmpty(context)) {
fpd.context = context;
}
if (!utils.isEmpty(user)) {
fpd.user = user;
}
return fpd;
}
function _getAdUnitFpd(adUnitFpd) {
const fpd = {};
const context = {};
_addEntries(context, adUnitFpd.ext);
if (!utils.isEmpty(context)) {
fpd.context = context;
}
return fpd;
}
function _addEntries(target, source) {
if (!utils.isEmpty(source)) {
Object.keys(source).forEach(key => {
if (source[key] != null) {
target[key] = source[key];
}
});
}
}
function _getExt(schain, fpd) {
let ext = {};
if (!utils.isEmpty(schain)) {
ext.schain = { ...schain };
}
if (!utils.isEmpty(fpd)) {
ext.fpd = { ...fpd };
}
return ext;
}
function getUnifiedIdEids(bidRequest) {
return getEids(bidRequest, 'tdid', 'adserver.org', 'TDID');
}
function getIdentityLinkEids(bidRequest) {
return getEids(bidRequest, 'idl_env', 'liveramp.com', 'idl');
}
function getCriteoEids(bidRequest) {
return getEids(bidRequest, 'criteoId', 'criteo.com', 'criteoId');
}
function getPubCommonEids(bidRequest) {
return getEids(bidRequest, 'pubcid', 'pubcid.org', 'pubcid');
}
function getEids(bidRequest, type, source, rtiPartner) {
return bidRequest
.map(getUserId(type)) // bids -> userIds of a certain type
.filter((x) => !!x) // filter out null userIds
.map(formatEid(source, rtiPartner)); // userIds -> eid objects
}
function getUserId(type) {
return (bid) => (bid && bid.userId && bid.userId[type]);
}
function formatEid(source, rtiPartner) {
return (id) => ({
source,
uids: [{
id,
ext: { rtiPartner }
}]
});
}
function _sizes(sizeArray) {
let sizes = sizeArray.filter(_isValidSize);
return sizes.map(function(size) {
return {
w: size[0],
h: size[1]
};
});
}
function _isValidSize(size) {
return (size.length === 2 && typeof size[0] === 'number' && typeof size[1] === 'number');
}
function _buildResponseObject(bidderRequest, bid) {
let bidResponse = {};
let width = bid.width || 1;
let height = bid.height || 1;
let dealId = bid.deal_id || '';
let creativeId = bid.crid || '';
let breq = bidderRequest.bids[bid.imp_id];
if (bid.cpm != 0 && bid.ad) {
bidResponse = {
requestId: breq.bidId,
cpm: bid.cpm,
width: width,
height: height,
netRevenue: true,
ad: bid.ad,
creativeId: creativeId,
dealId: dealId,
currency: 'USD',
ttl: 300,
tl_source: bid.tl_source,
meta: {}
};
if (_isInstreamBidRequest(breq)) {
bidResponse.vastXml = bid.ad;
bidResponse.mediaType = 'video';
};
if (bid.advertiser_name) {
bidResponse.meta.advertiserName = bid.advertiser_name;
}
if (bid.adomain && bid.adomain.length) {
bidResponse.meta.advertiserDomains = bid.adomain;
}
if (bid.tl_source && bid.tl_source == 'hdx') {
bidResponse.meta.mediaType = 'banner';
}
if (bid.tl_source && bid.tl_source == 'tlx') {
bidResponse.meta.mediaType = 'native';
}
};
return bidResponse;
}
registerBidder(tripleliftAdapterSpec);