diff --git a/modules/gptPreAuction.js b/modules/gptPreAuction.js index a6495e3570e..ca660dd1069 100644 --- a/modules/gptPreAuction.js +++ b/modules/gptPreAuction.js @@ -1,24 +1,48 @@ -import { getSignals as getSignalsFn, getSegments as getSegmentsFn, taxonomies } from '../libraries/gptUtils/gptUtils.js'; -import { auctionManager } from '../src/auctionManager.js'; -import { config } from '../src/config.js'; -import { TARGETING_KEYS } from '../src/constants.js'; -import { getHook } from '../src/hook.js'; -import { find } from '../src/polyfill.js'; +import { + getSignals as getSignalsFn, + getSegments as getSegmentsFn, + taxonomies, +} from "../libraries/gptUtils/gptUtils.js"; +import { auctionManager } from "../src/auctionManager.js"; +import { config } from "../src/config.js"; +import { TARGETING_KEYS } from "../src/constants.js"; +import { getHook } from "../src/hook.js"; import { deepAccess, deepSetValue, - isAdUnitCodeMatchingSlot, - isGptPubadsDefined, logInfo, logWarn, pick, - uniques -} from '../src/utils.js'; + uniques, +} from "../src/utils.js"; -const MODULE_NAME = 'GPT Pre-Auction'; +const MODULE_NAME = "GPT Pre-Auction"; export let _currentConfig = {}; let hooksAdded = false; - +window.adpushup = window.adpushup || {}; +const adp = window.adpushup; +const adpConfig = adp.config || {}; + +window.adpTags = window.adpTags || {}; +const adpTags = window.adpTags; +const adpSlots = adpTags.adpSlots || {}; + +const getAdUnitPath = function (code) { + const adpSlot = adpSlots[code]; + if (!adpSlot) return null; + const { childPublisherId, isMcmEnabled = false } = adpConfig.mcm; + + let dfpNetwork = adpSlot.activeDFPNetwork; + if (isMcmEnabled) { + dfpNetwork += `,${childPublisherId}`; + } + const dfpAdUnitCode = + adpSlot.currentGptSlotData && adpSlot.currentGptSlotData.dfpAdunitCode; + if (!dfpAdUnitCode) { + return null; + } + return `/${dfpNetwork}/${dfpAdUnitCode}`; +}; export function getSegments(fpd, sections, segtax) { return getSegmentsFn(fpd, sections, segtax); } @@ -27,11 +51,14 @@ export function getSignals(fpd) { return getSignalsFn(fpd); } -export function getSignalsArrayByAuctionsIds(auctionIds, index = auctionManager.index) { +export function getSignalsArrayByAuctionsIds( + auctionIds, + index = auctionManager.index +) { const signals = auctionIds - .map(auctionId => index.getAuction({ auctionId })?.getFPD()?.global) + .map((auctionId) => index.getAuction({ auctionId })?.getFPD()?.global) .map(getSignals) - .filter(fpd => fpd); + .filter((fpd) => fpd); return signals; } @@ -40,33 +67,35 @@ export function getSignalsIntersection(signals) { const result = {}; taxonomies.forEach((taxonomy) => { const allValues = signals - .flatMap(x => x) - .filter(x => x.taxonomy === taxonomy) - .map(x => x.values); - result[taxonomy] = allValues.length ? ( - allValues.reduce((commonElements, subArray) => { - return commonElements.filter(element => subArray.includes(element)); - }) - ) : [] + .flatMap((x) => x) + .filter((x) => x.taxonomy === taxonomy) + .map((x) => x.values); + result[taxonomy] = allValues.length + ? allValues.reduce((commonElements, subArray) => { + return commonElements.filter((element) => subArray.includes(element)); + }) + : []; result[taxonomy] = { values: result[taxonomy] }; - }) + }); return result; } export function getAuctionsIdsFromTargeting(targeting, am = auctionManager) { return Object.values(targeting) - .flatMap(x => Object.entries(x)) - .filter((entry) => entry[0] === TARGETING_KEYS.AD_ID || entry[0].startsWith(TARGETING_KEYS.AD_ID + '_')) - .flatMap(entry => entry[1]) - .map(adId => am.findBidByAdId(adId)?.auctionId) - .filter(id => id != null) + .flatMap((x) => Object.entries(x)) + .filter( + (entry) => + entry[0] === TARGETING_KEYS.AD_ID || + entry[0].startsWith(TARGETING_KEYS.AD_ID + "_") + ) + .flatMap((entry) => entry[1]) + .map((adId) => am.findBidByAdId(adId)?.auctionId) + .filter((id) => id != null) .filter(uniques); } -export const appendGptSlots = adUnits => { - const { customGptSlotMatching } = _currentConfig; - - if (!isGptPubadsDefined()) { +export const appendGptSlots = (adUnits) => { + if (!adpSlots) { return; } @@ -76,38 +105,37 @@ export const appendGptSlots = adUnits => { return acc; }, {}); - const adUnitPaths = {}; - - window.googletag.pubads().getSlots().forEach(slot => { - const matchingAdUnitCode = find(Object.keys(adUnitMap), customGptSlotMatching - ? customGptSlotMatching(slot) - : isAdUnitCodeMatchingSlot(slot)); - + for (adUnit in adpSlots) { + const matchingAdUnitCode = Object.keys(adUnitMap).find( + (key) => key === adUnit + ); if (matchingAdUnitCode) { - const path = adUnitPaths[matchingAdUnitCode] = slot.getAdUnitPath(); const adserver = { - name: 'gam', - adslot: sanitizeSlotPath(path) + name: "gam", + adslot: sanitizeSlotPath(getAdUnitPath(adUnit)), }; adUnitMap[matchingAdUnitCode].forEach((adUnit) => { - deepSetValue(adUnit, 'ortb2Imp.ext.data.adserver', Object.assign({}, adUnit.ortb2Imp?.ext?.data?.adserver, adserver)); + deepSetValue( + adUnit, + "ortb2Imp.ext.data.adserver", + Object.assign({}, adUnit.ortb2Imp?.ext?.data?.adserver, adserver) + ); }); } - }); - return adUnitPaths; + } }; const sanitizeSlotPath = (path) => { - const gptConfig = config.getConfig('gptPreAuction') || {}; + const gptConfig = config.getConfig("gptPreAuction") || {}; if (gptConfig.mcmEnabled) { - return path.replace(/(^\/\d*),\d*\//, '$1/'); + return path.replace(/(^\/\d*),\d*\//, "$1/"); } return path; -} +}; -const defaultPreAuction = (adUnit, adServerAdSlot, adUnitPath) => { +const defaultPreAuction = (adUnit, adServerAdSlot) => { const context = adUnit.ortb2Imp.ext.data; // use pbadslot if supplied @@ -115,13 +143,13 @@ const defaultPreAuction = (adUnit, adServerAdSlot, adUnitPath) => { return context.pbadslot; } - // confirm that GPT is set up - if (!isGptPubadsDefined()) { + if (!adpSlots) { return; } - // find all GPT slots with this name - var gptSlots = window.googletag.pubads().getSlots().filter(slot => slot.getAdUnitPath() === adUnitPath); + var gptSlots = Object.keys(adpSlots).filter( + (slot) => getAdUnitPath(slot) === adServerAdSlot + ); if (gptSlots.length === 0) { return; // should never happen @@ -133,9 +161,9 @@ const defaultPreAuction = (adUnit, adServerAdSlot, adUnitPath) => { // else the adunit code must be div id. append it. return `${adServerAdSlot}#${adUnit.code}`; -} +}; -export const appendPbAdSlot = adUnit => { +export const appendPbAdSlot = (adUnit) => { const context = adUnit.ortb2Imp.ext.data; const { customPbAdSlot } = _currentConfig; @@ -145,7 +173,10 @@ export const appendPbAdSlot = adUnit => { } if (customPbAdSlot) { - context.pbadslot = customPbAdSlot(adUnit.code, deepAccess(context, 'adserver.adslot')); + context.pbadslot = customPbAdSlot( + adUnit.code, + deepAccess(context, "adserver.adslot") + ); return; } @@ -158,7 +189,7 @@ export const appendPbAdSlot = adUnit => { } } catch (e) {} // banner adUnit, use GPT adunit if defined - if (deepAccess(context, 'adserver.adslot')) { + if (deepAccess(context, "adserver.adslot")) { context.pbadslot = context.adserver.adslot; return; } @@ -167,13 +198,16 @@ export const appendPbAdSlot = adUnit => { }; function warnDeprecation(adUnit) { - logWarn(`pbadslot is deprecated and will soon be removed, use gpid instead`, adUnit) + logWarn( + `pbadslot is deprecated and will soon be removed, use gpid instead`, + adUnit + ); } export const makeBidRequestsHook = (fn, adUnits, ...args) => { - const adUnitPaths = appendGptSlots(adUnits); + appendGptSlots(adUnits); const { useDefaultPreAuction, customPreAuction } = _currentConfig; - adUnits.forEach(adUnit => { + adUnits.forEach((adUnit) => { // init the ortb2Imp if not done yet adUnit.ortb2Imp = adUnit.ortb2Imp || {}; adUnit.ortb2Imp.ext = adUnit.ortb2Imp.ext || {}; @@ -191,12 +225,16 @@ export const makeBidRequestsHook = (fn, adUnits, ...args) => { if (context.data?.pbadslot) { warnDeprecation(adUnit); } - let adserverSlot = deepAccess(context, 'data.adserver.adslot'); + let adserverSlot = deepAccess(context, "data.adserver.adslot"); let result; if (customPreAuction) { - result = customPreAuction(adUnit, adserverSlot, adUnitPaths?.[adUnit.code]); + result = customPreAuction( + adUnit, + adserverSlot, + adUnitPaths?.[adUnit.code] + ); } else if (useDefaultPreAuction) { - result = defaultPreAuction(adUnit, adserverSlot, adUnitPaths?.[adUnit.code]); + result = defaultPreAuction(adUnit, adserverSlot); } if (result) { context.gpid = context.data.pbadslot = result; @@ -209,35 +247,48 @@ export const makeBidRequestsHook = (fn, adUnits, ...args) => { const setPpsConfigFromTargetingSet = (next, targetingSet) => { // set gpt config const auctionsIds = getAuctionsIdsFromTargeting(targetingSet); - const signals = getSignalsIntersection(getSignalsArrayByAuctionsIds(auctionsIds)); - window.googletag.setConfig && window.googletag.setConfig({pps: { taxonomies: signals }}); + const signals = getSignalsIntersection( + getSignalsArrayByAuctionsIds(auctionsIds) + ); + window.googletag.setConfig && + window.googletag.setConfig({ pps: { taxonomies: signals } }); next(targetingSet); }; -const handleSetGptConfig = moduleConfig => { +const handleSetGptConfig = (moduleConfig) => { _currentConfig = pick(moduleConfig, [ - 'enabled', enabled => enabled !== false, - 'customGptSlotMatching', customGptSlotMatching => - typeof customGptSlotMatching === 'function' && customGptSlotMatching, - 'customPbAdSlot', customPbAdSlot => typeof customPbAdSlot === 'function' && customPbAdSlot, - 'customPreAuction', customPreAuction => typeof customPreAuction === 'function' && customPreAuction, - 'useDefaultPreAuction', useDefaultPreAuction => useDefaultPreAuction ?? true, + "enabled", + (enabled) => enabled !== false, + "customGptSlotMatching", + (customGptSlotMatching) => + typeof customGptSlotMatching === "function" && customGptSlotMatching, + "customPbAdSlot", + (customPbAdSlot) => typeof customPbAdSlot === "function" && customPbAdSlot, + "customPreAuction", + (customPreAuction) => + typeof customPreAuction === "function" && customPreAuction, + "useDefaultPreAuction", + (useDefaultPreAuction) => useDefaultPreAuction ?? true, ]); if (_currentConfig.enabled) { if (!hooksAdded) { - getHook('makeBidRequests').before(makeBidRequestsHook); - getHook('targetingDone').after(setPpsConfigFromTargetingSet) + getHook("makeBidRequests").before(makeBidRequestsHook); + getHook("targetingDone").after(setPpsConfigFromTargetingSet); hooksAdded = true; } } else { logInfo(`${MODULE_NAME}: Turning off module`); _currentConfig = {}; - getHook('makeBidRequests').getHooks({hook: makeBidRequestsHook}).remove(); - getHook('targetingDone').getHooks({hook: setPpsConfigFromTargetingSet}).remove(); + getHook("makeBidRequests").getHooks({ hook: makeBidRequestsHook }).remove(); + getHook("targetingDone") + .getHooks({ hook: setPpsConfigFromTargetingSet }) + .remove(); hooksAdded = false; } }; -config.getConfig('gptPreAuction', config => handleSetGptConfig(config.gptPreAuction)); +config.getConfig("gptPreAuction", (config) => + handleSetGptConfig(config.gptPreAuction) +); handleSetGptConfig({});