UNPKG

mk9-prebid

Version:

Header Bidding Management Library

434 lines (415 loc) 12.5 kB
import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'districtmDMX'; const DMXURI = 'https://dmx.districtm.io/b/v1'; const GVLID = 144; const VIDEO_MAPPING = { playback_method: { 'auto_play_sound_on': 1, 'auto_play_sound_off': 2, 'click_to_play': 3, 'mouse_over': 4, 'viewport_sound_on': 5, 'viewport_sound_off': 6 } }; export const spec = { code: BIDDER_CODE, gvlid: GVLID, aliases: ['dmx'], supportedFormat: [BANNER, VIDEO], supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid(bid) { return !!(bid.params.memberid); }, interpretResponse(response, bidRequest) { response = response.body || {}; if (response.seatbid) { if (utils.isArray(response.seatbid)) { const { seatbid } = response; let winners = seatbid.reduce((bid, ads) => { let ad = ads.bid.reduce(function (oBid, nBid) { if (oBid.price < nBid.price) { const bid = matchRequest(nBid.impid, bidRequest); const { width, height } = defaultSize(bid); nBid.cpm = parseFloat(nBid.price).toFixed(2); nBid.bidId = nBid.impid; nBid.requestId = nBid.impid; nBid.width = nBid.w || width; nBid.height = nBid.h || height; nBid.ttl = 300; nBid.mediaType = bid.mediaTypes && bid.mediaTypes.video ? 'video' : 'banner'; if (nBid.mediaType === 'video') { nBid.vastXml = cleanVast(nBid.adm, nBid.nurl); nBid.ttl = 3600; } if (nBid.dealid) { nBid.dealId = nBid.dealid; } nBid.uuid = nBid.bidId; nBid.ad = nBid.adm; nBid.netRevenue = true; nBid.creativeId = nBid.crid; nBid.currency = 'USD'; nBid.meta = nBid.meta || {}; if (nBid.adomain && nBid.adomain.length > 0) { nBid.meta.advertiserDomains = nBid.adomain; } return nBid; } else { oBid.cpm = oBid.price; return oBid; } }, { price: 0 }); if (ad.adm) { bid.push(ad) } return bid; }, []) let winnersClean = winners.filter(w => { if (w.bidId) { return true; } return false; }); return winnersClean; } else { return []; } } else { return []; } }, buildRequests(bidRequest, bidderRequest) { let timeout = config.getConfig('bidderTimeout'); let schain = null; let dmxRequest = { id: utils.generateUUID(), cur: ['USD'], tmax: (timeout - 300), test: this.test() || 0, site: { publisher: { id: String(bidRequest[0].params.memberid) || null } } } try { let params = config.getConfig('dmx'); dmxRequest.user = params.user || {}; let site = params.site || {}; dmxRequest.site = { ...dmxRequest.site, ...site } } catch (e) { } let eids = []; if (bidRequest[0] && bidRequest[0].userId) { bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.idl_env`), 'liveramp.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.id5id.uid`), 'id5-sync.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.pubcid`), 'pubcid.org', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.tdid`), 'adserver.org', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.criteoId`), 'criteo.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.britepoolid`), 'britepool.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.lipb.lipbid`), 'liveintent.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.intentiqid`), 'intentiq.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.lotamePanoramaId`), 'lotame.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.parrableId`), 'parrable.com', 1); bindUserId(eids, utils.deepAccess(bidRequest[0], `userId.netId`), 'netid.de', 1); dmxRequest.user = dmxRequest.user || {}; dmxRequest.user.ext = dmxRequest.user.ext || {}; dmxRequest.user.ext.eids = eids; } if (!dmxRequest.test) { delete dmxRequest.test; } if (bidderRequest.gdprConsent) { dmxRequest.regs = {}; dmxRequest.regs.ext = {}; dmxRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; if (bidderRequest.gdprConsent.gdprApplies === true) { dmxRequest.user = {}; dmxRequest.user.ext = {}; dmxRequest.user.ext.consent = bidderRequest.gdprConsent.consentString; } } dmxRequest.regs = dmxRequest.regs || {}; dmxRequest.regs.coppa = config.getConfig('coppa') === true ? 1 : 0; if (bidderRequest && bidderRequest.uspConsent) { dmxRequest.regs = dmxRequest.regs || {}; dmxRequest.regs.ext = dmxRequest.regs.ext || {}; dmxRequest.regs.ext.us_privacy = bidderRequest.uspConsent; } try { schain = bidRequest[0].schain; dmxRequest.source = {}; dmxRequest.source.ext = {}; dmxRequest.source.ext.schain = schain || {} } catch (e) { } let tosendtags = bidRequest.map(dmx => { var obj = {}; obj.id = dmx.bidId; obj.tagid = String(dmx.params.dmxid || dmx.adUnitCode); obj.secure = 1; obj.bidfloor = getFloor(dmx); if (dmx.mediaTypes && dmx.mediaTypes.video) { obj.video = { topframe: 1, skip: dmx.mediaTypes.video.skip || 0, linearity: dmx.mediaTypes.video.linearity || 1, minduration: dmx.mediaTypes.video.minduration || 5, maxduration: dmx.mediaTypes.video.maxduration || 60, playbackmethod: dmx.mediaTypes.video.playbackmethod || [2], api: getApi(dmx.mediaTypes.video), mimes: dmx.mediaTypes.video.mimes || ['video/mp4'], protocols: getProtocols(dmx.mediaTypes.video), h: dmx.mediaTypes.video.playerSize[0][1], w: dmx.mediaTypes.video.playerSize[0][0] }; } else { obj.banner = { topframe: 1, w: cleanSizes(dmx.sizes, 'w'), h: cleanSizes(dmx.sizes, 'h'), format: cleanSizes(dmx.sizes).map(s => { return { w: s[0], h: s[1] }; }).filter(obj => typeof obj.w === 'number' && typeof obj.h === 'number') }; } return obj; }); if (tosendtags.length <= 5) { dmxRequest.imp = tosendtags; return { method: 'POST', url: DMXURI, data: JSON.stringify(dmxRequest), bidderRequest } } else { return upto5(tosendtags, dmxRequest, bidderRequest, DMXURI); } }, test() { return window.location.href.indexOf('dmTest=true') !== -1 ? 1 : 0; }, getUserSyncs(optionsType, serverResponses, gdprConsent, uspConsent) { let query = []; let url = 'https://cdn.districtm.io/ids/index.html' if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { query.push(['gdpr', gdprConsent.consentString]) } if (uspConsent) { query.push(['ccpa', uspConsent]) } if (query.length > 0) { url += '?' + query.map(q => q.join('=')).join('&') } if (optionsType.iframeEnabled) { return [{ type: 'iframe', url: url }]; } } } export function getFloor(bid) { let floor = null; if (typeof bid.getFloor === 'function') { const floorInfo = bid.getFloor({ currency: 'USD', mediaType: bid.mediaTypes.video ? 'video' : 'banner', size: bid.sizes.map(size => { return { w: size[0], h: size[1] } }) }); if (typeof floorInfo === 'object' && floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) { floor = parseFloat(floorInfo.floor); } } return floor !== null ? floor : bid.params.floor; } export function cleanSizes(sizes, value) { const supportedSize = [ { size: [300, 250], s: 100 }, { size: [728, 90], s: 95 }, { size: [320, 50], s: 90 }, { size: [160, 600], s: 88 }, { size: [300, 600], s: 85 }, { size: [300, 50], s: 80 }, { size: [970, 250], s: 75 }, { size: [970, 90], s: 60 }, ]; let newArray = shuffle(sizes, supportedSize); switch (value) { case 'w': return newArray[0][0] || 0; case 'h': return newArray[0][1] || 0; case 'size': return newArray; default: return newArray; } } export function shuffle(sizes, list) { let removeSizes = sizes.filter(size => { return list.map(l => `${l.size[0]}x${l.size[1]}`).indexOf(`${size[0]}x${size[1]}`) === -1 }) let reOrder = sizes.reduce((results, current) => { if (results.length === 0) { results.push(current); return results; } results.push(current); results = list.filter(l => results.map(r => `${r[0]}x${r[1]}`).indexOf(`${l.size[0]}x${l.size[1]}`) !== -1); results = results.sort(function (a, b) { return b.s - a.s; }) return results.map(r => r.size); }, []) return removeDuplicate([...reOrder, ...removeSizes]); } export function removeDuplicate(arrayValue) { return arrayValue.filter((elem, index) => { return arrayValue.map(e => `${e[0]}x${e[1]}`).indexOf(`${elem[0]}x${elem[1]}`) === index }) } export function upto5(allimps, dmxRequest, bidderRequest, DMXURI) { let start = 0; let step = 5; let req = []; while (allimps.length !== 0) { if (allimps.length >= 5) { req.push(allimps.splice(start, step)) } else { req.push(allimps.splice(start, allimps.length)) } } return req.map(r => { dmxRequest.imp = r; return { method: 'POST', url: DMXURI, data: JSON.stringify(dmxRequest), bidderRequest } }) } /** * Function matchRequest(id: string, BidRequest: object) * @param id * @type string * @param bidRequest * @type Object * @returns Object * */ export function matchRequest(id, bidRequest) { const { bids } = bidRequest.bidderRequest; const [returnValue] = bids.filter(bid => bid.bidId === id); return returnValue; } export function checkDeepArray(Arr) { if (Array.isArray(Arr)) { if (Array.isArray(Arr[0])) { return Arr[0]; } else { return Arr; } } else { return Arr; } } export function defaultSize(thebidObj) { const { sizes } = thebidObj; const returnObject = {}; returnObject.width = checkDeepArray(sizes)[0]; returnObject.height = checkDeepArray(sizes)[1]; return returnObject; } export function bindUserId(eids, value, source, atype) { if (utils.isStr(value) && Array.isArray(eids)) { eids.push({ source, uids: [ { id: value, atype } ] }) } } export function getApi({ api }) { let defaultValue = [2]; if (api && Array.isArray(api) && api.length > 0) { return api } else { return defaultValue; } } export function getPlaybackmethod(playback) { if (Array.isArray(playback) && playback.length > 0) { return playback.map(label => { return VIDEO_MAPPING.playback_method[label] }) } return [2] } export function getProtocols({ protocols }) { let defaultValue = [2, 3, 5, 6, 7, 8]; if (protocols && Array.isArray(protocols) && protocols.length > 0) { return protocols; } else { return defaultValue; } } export function cleanVast(str, nurl) { try { const toberemove = /<img\s[^>]*?src\s*=\s*['\"]([^'\"]*?)['\"][^>]*?>/ const [img, url] = str.match(toberemove) str = str.replace(toberemove, '') if (img) { if (url) { const insrt = `<Impression><![CDATA[${url}]]></Impression>` str = str.replace('</Impression>', `</Impression>${insrt}`) } } return str; } catch (e) { if (!nurl) { return str } const insrt = `<Impression><![CDATA[${nurl}]]></Impression>` str = str.replace('</Impression>', `</Impression>${insrt}`) return str } } registerBidder(spec);