UNPKG

mk9-prebid

Version:

Header Bidding Management Library

98 lines (85 loc) 4.36 kB
// This module, when included, will trigger a BID_VIEWABLE event which can be consumed by Bidders and Analytics adapters // GPT API is used to find when a bid is viewable, https://developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent // Does not work with other than GPT integration import { config } from '../src/config.js'; import * as events from '../src/events.js'; import { EVENTS } from '../src/constants.json'; import { logWarn, isFn, triggerPixel } from '../src/utils.js'; import { getGlobal } from '../src/prebidGlobal.js'; import adapterManager, { gdprDataHandler, uspDataHandler } from '../src/adapterManager.js'; import find from 'core-js-pure/features/array/find.js'; const MODULE_NAME = 'bidViewability'; const CONFIG_ENABLED = 'enabled'; const CONFIG_FIRE_PIXELS = 'firePixels'; const CONFIG_CUSTOM_MATCH = 'customMatchFunction'; const BID_VURL_ARRAY = 'vurls'; const GPT_IMPRESSION_VIEWABLE_EVENT = 'impressionViewable'; export let isBidAdUnitCodeMatchingSlot = (bid, slot) => { return (slot.getAdUnitPath() === bid.adUnitCode || slot.getSlotElementId() === bid.adUnitCode); } export let getMatchingWinningBidForGPTSlot = (globalModuleConfig, slot) => { return find(getGlobal().getAllWinningBids(), // supports custom match function from config bid => isFn(globalModuleConfig[CONFIG_CUSTOM_MATCH]) ? globalModuleConfig[CONFIG_CUSTOM_MATCH](bid, slot) : isBidAdUnitCodeMatchingSlot(bid, slot) ) || null; }; export let fireViewabilityPixels = (globalModuleConfig, bid) => { if (globalModuleConfig[CONFIG_FIRE_PIXELS] === true && bid.hasOwnProperty(BID_VURL_ARRAY)) { let queryParams = {}; const gdprConsent = gdprDataHandler.getConsentData(); if (gdprConsent) { if (typeof gdprConsent.gdprApplies === 'boolean') { queryParams.gdpr = Number(gdprConsent.gdprApplies); } if (gdprConsent.consentString) { queryParams.gdpr_consent = gdprConsent.consentString; } if (gdprConsent.addtlConsent) { queryParams.addtl_consent = gdprConsent.addtlConsent; } } const uspConsent = uspDataHandler.getConsentData(); if (uspConsent) { queryParams.us_privacy = uspConsent; } bid[BID_VURL_ARRAY].forEach(url => { // add '?' if not present in URL if (Object.keys(queryParams).length > 0 && url.indexOf('?') === -1) { url += '?'; } // append all query params, `&key=urlEncoded(value)` url += Object.keys(queryParams).reduce((prev, key) => prev += `&${key}=${encodeURIComponent(queryParams[key])}`, ''); triggerPixel(url) }); } }; export let logWinningBidNotFound = (slot) => { logWarn(`bid details could not be found for ${slot.getSlotElementId()}, probable reasons: a non-prebid bid is served OR check the prebid.AdUnit.code to GPT.AdSlot relation.`); }; export let impressionViewableHandler = (globalModuleConfig, slot, event) => { let respectiveBid = getMatchingWinningBidForGPTSlot(globalModuleConfig, slot); if (respectiveBid === null) { logWinningBidNotFound(slot); } else { // if config is enabled AND VURL array is present then execute each pixel fireViewabilityPixels(globalModuleConfig, respectiveBid); // trigger respective bidder's onBidViewable handler adapterManager.callBidViewableBidder(respectiveBid.bidder, respectiveBid); // emit the BID_VIEWABLE event with bid details, this event can be consumed by bidders and analytics pixels events.emit(EVENTS.BID_VIEWABLE, respectiveBid); } }; export let init = () => { events.on(EVENTS.AUCTION_INIT, () => { // read the config for the module const globalModuleConfig = config.getConfig(MODULE_NAME) || {}; // do nothing if module-config.enabled is not set to true // this way we are adding a way for bidders to know (using pbjs.getConfig('bidViewability').enabled === true) whether this module is added in build and is enabled if (globalModuleConfig[CONFIG_ENABLED] !== true) { return; } // add the GPT event listener window.googletag = window.googletag || {}; window.googletag.cmd = window.googletag.cmd || []; window.googletag.cmd.push(() => { window.googletag.pubads().addEventListener(GPT_IMPRESSION_VIEWABLE_EVENT, function(event) { impressionViewableHandler(globalModuleConfig, event.slot, event); }); }); }); } init()