UNPKG

mk9-prebid

Version:

Header Bidding Management Library

185 lines (151 loc) 4.08 kB
/** * This module adds MASS support to Prebid.js. */ import { config } from '../src/config.js'; import { getHook } from '../src/hook.js'; import find from 'core-js-pure/features/array/find.js'; const defaultCfg = { dealIdPattern: /^MASS/i }; let cfg; export let listenerAdded = false; export let isEnabled = false; const matchedBids = {}; let renderers; init(); config.getConfig('mass', config => init(config.mass)); /** * Module init. */ export function init(userCfg) { cfg = Object.assign({}, defaultCfg, window.massConfig && window.massConfig.mass, userCfg); if (cfg.enabled === false) { if (isEnabled) { getHook('addBidResponse').getHooks({hook: addBidResponseHook}).remove(); isEnabled = false; } } else { if (!isEnabled) { getHook('addBidResponse').before(addBidResponseHook); isEnabled = true; } } if (isEnabled) { updateRenderers(); } } /** * Update the list of renderers based on current config. */ export function updateRenderers() { renderers = []; // official MASS renderer: if (cfg.dealIdPattern && cfg.renderUrl) { renderers.push({ match: isMassBid, render: useDefaultRender(cfg.renderUrl, 'mass') }); } // add any custom renderer defined in the config: (cfg.custom || []).forEach(renderer => { if (!renderer.match && renderer.dealIdPattern) { renderer.match = useDefaultMatch(renderer.dealIdPattern); } if (!renderer.render && renderer.renderUrl && renderer.namespace) { renderer.render = useDefaultRender(renderer.renderUrl, renderer.namespace); } if (renderer.match && renderer.render) { renderers.push(renderer); } }); return renderers; } /** * Before hook for 'addBidResponse'. */ export function addBidResponseHook(next, adUnitCode, bid) { let renderer; for (let i = 0; i < renderers.length; i++) { if (renderers[i].match(bid)) { renderer = renderers[i]; break; } } if (renderer) { const bidRequest = find(this.bidderRequest.bids, bidRequest => bidRequest.bidId === bid.requestId ); matchedBids[bid.requestId] = { renderer, payload: { bidRequest, bid, adm: bid.ad } }; bid.ad = '<script>window.parent.postMessage({massBidId: "' + bid.requestId + '"}, "*");\x3c/script>'; addListenerOnce(); } next(adUnitCode, bid); } /** * Add listener for the "message" event sent by the winning bid */ export function addListenerOnce() { if (!listenerAdded) { window.addEventListener('message', e => { if (!e || !e.data || !e.data.massBidId) { return; } const matchedBid = matchedBids[e.data.massBidId]; if (matchedBid) { const payload = { type: 'prebid', event: e, ...matchedBid.payload }; delete payload.bid.ad; matchedBid.renderer.render(payload); } }); listenerAdded = true; } } /** * Check if a bid is MASS. */ export function isMassBid(bid) { // either bid.meta.mass is set or deal ID matches a publisher specified pattern: if (!((bid.meta && bid.meta.mass) || (cfg.dealIdPattern && cfg.dealIdPattern.test(bid.dealId)))) { return false; } // there must be a 'mass://' or 'pcreative?' in the ad markup: return /mass:\/\/|\/pcreative\?/i.test(bid.ad); } /** * Default match (factory). */ export function useDefaultMatch(dealIdPattern) { return function(bid) { return dealIdPattern.test(bid.dealId); }; } /** * Default render (factory). */ export function useDefaultRender(renderUrl, namespace) { return function render(payload) { const ns = window[namespace] = window[namespace] || {}; ns.queue = ns.queue || []; ns.queue.push(payload); if (!ns.loaded) { const s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = renderUrl; const x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); ns.loaded = true; } }; }