diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 3c2c364fafd..3d72986230e 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -17,6 +17,7 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; import {isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; // **************************** UTILS ************************** // const BIDDER_CODE = '33across'; @@ -373,7 +374,7 @@ function _getProduct(bidRequest) { // BUILD REQUESTS: BANNER function _buildBannerORTB(bidRequest) { const bannerAdUnit = deepAccess(bidRequest, 'mediaTypes.banner', {}); - const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); + const element = _getAdSlotHTMLElement(bidRequest); const sizes = _transformSizes(bannerAdUnit.sizes); @@ -478,6 +479,7 @@ function _getViewability(element, topWin, { w, h } = {}) { : 0; } +// TODO use utils/adUnits once that's unified in 11 function _mapAdUnitPathToElementId(adUnitCode) { if (isGptPubadsDefined()) { // eslint-disable-next-line no-undef @@ -500,9 +502,9 @@ function _mapAdUnitPathToElementId(adUnitCode) { return null; } -function _getAdSlotHTMLElement(adUnitCode) { - return document.getElementById(adUnitCode) || - document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); +function _getAdSlotHTMLElement(bidRequest) { + return getAdUnitElement(bidRequest) || + document.getElementById(_mapAdUnitPathToElementId(bidRequest.adUnitCode)); } /** diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index 9d04e166600..6de60552a22 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -25,6 +25,7 @@ import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { userSync } from '../src/userSync.js'; import { validateOrtbFields } from '../src/prebid.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'adagio'; const LOG_PREFIX = 'Adagio:'; @@ -466,7 +467,7 @@ const OUTSTREAM_RENDERER = { return; } - const el = document.getElementById(bid.adUnitCode); + const el = getAdUnitElement(bid); renderer.bootstrap(config, el, override); }, diff --git a/modules/adagioRtdProvider.js b/modules/adagioRtdProvider.js index dfc6361234e..201d6d0e5e2 100644 --- a/modules/adagioRtdProvider.js +++ b/modules/adagioRtdProvider.js @@ -495,6 +495,7 @@ function getElementFromTopWindow(element, currentWindow) { }; function getSlotPosition(divId) { + // TODO: this should use getAdUnitElement if (!isSafeFrameWindow() && !canAccessWindowTop()) { return ''; } diff --git a/modules/adnuntiusAnalyticsAdapter.js b/modules/adnuntiusAnalyticsAdapter.js index 6de06332e3e..1bfbdc1e68c 100644 --- a/modules/adnuntiusAnalyticsAdapter.js +++ b/modules/adnuntiusAnalyticsAdapter.js @@ -3,6 +3,7 @@ import {ajax} from '../src/ajax.js'; import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import { EVENTS } from '../src/constants.js'; import adapterManager from '../src/adapterManager.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const URL = 'https://analytics.adnuntius.com/prebid'; const REQUEST_SENT = 1; @@ -36,7 +37,7 @@ const adnAnalyticsAdapter = Object.assign(adapter({url: '', analyticsType: 'endp cache.auctions[args.auctionId].gdprApplies = args.gdprConsent ? args.gdprConsent.gdprApplies : undefined; cache.auctions[args.auctionId].gdprConsent = args.gdprConsent ? args.gdprConsent.consentString : undefined; - const container = document.getElementById(bidReq.adUnitCode); + const container = getAdUnitElement(bidReq); const containerAttr = container ? container.getAttribute('data-adunitid') : undefined; const adUnitId = containerAttr || undefined; diff --git a/modules/adotBidAdapter.js b/modules/adotBidAdapter.js index 121c9960ade..052be840333 100644 --- a/modules/adotBidAdapter.js +++ b/modules/adotBidAdapter.js @@ -7,6 +7,7 @@ import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { isArray, isBoolean, isFn, isPlainObject, isStr, logError, replaceAuctionPrice } from '../src/utils.js'; import { OUTSTREAM } from '../src/video.js'; import { NATIVE_ASSETS_IDS as NATIVE_ID_MAPPING, NATIVE_ASSETS as NATIVE_PLACEMENTS } from '../libraries/braveUtils/nativeAssets.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -495,7 +496,7 @@ function buildRenderer(bid, mediaType) { ad.renderer.push(() => { const domContainer = container ? document.querySelector(container) - : document.getElementById(adUnitCode); + : getAdUnitElement(ad) const player = new window.VASTPlayer(domContainer); diff --git a/modules/adrelevantisBidAdapter.js b/modules/adrelevantisBidAdapter.js index 7f2d850a23a..5fb877f5110 100644 --- a/modules/adrelevantisBidAdapter.js +++ b/modules/adrelevantisBidAdapter.js @@ -21,6 +21,7 @@ import {getANKeywordParam} from '../libraries/appnexusUtils/anKeywords.js'; import {chunk} from '../libraries/chunk/chunk.js'; import {transformSizes} from '../libraries/sizeUtils/tranformSize.js'; import {hasUserInfo, hasAppDeviceInfo, hasAppId} from '../libraries/adrelevantisUtils/bidderUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -250,10 +251,9 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { - var el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); +function hidedfpContainer(bid) { + var el = getAdUnitElement(bid).querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } @@ -261,7 +261,7 @@ function hidedfpContainer(elementId) { function outstreamRender(bid) { // push to render queue because ANOutstreamVideo may not be loaded yet - hidedfpContainer(bid.adUnitCode); + hidedfpContainer(bid); bid.renderer.push(() => { window.ANOutstreamVideo.renderAd({ tagId: bid.adResponse.tag_id, diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index c710789640d..5eb2a8a483e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -35,6 +35,7 @@ import { import {convertCamelToUnderscore, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js'; import {chunk} from '../libraries/chunk/chunk.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -1177,11 +1178,10 @@ function buildNativeRequest(params) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { +function hidedfpContainer(container) { try { - const el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); + const el = container.querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } @@ -1190,10 +1190,10 @@ function hidedfpContainer(elementId) { } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document.getElementById(elementId).querySelectorAll("script[id^='sas_script']"); + const el = container.querySelectorAll("script[id^='sas_script']"); if (el[0].nextSibling && el[0].nextSibling.localName === 'iframe') { el[0].nextSibling.style.setProperty('display', 'none'); } @@ -1203,8 +1203,9 @@ function hideSASIframe(elementId) { } function outstreamRender(bid, doc) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); // push to render queue because ANOutstreamVideo may not be loaded yet bid.renderer.push(() => { const win = doc?.defaultView || window; diff --git a/modules/bidViewabilityIO.js b/modules/bidViewabilityIO.js index 195b551c85b..201a779bb32 100644 --- a/modules/bidViewabilityIO.js +++ b/modules/bidViewabilityIO.js @@ -2,6 +2,7 @@ import { logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import * as events from '../src/events.js'; import {EVENTS} from '../src/constants.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const MODULE_NAME = 'bidViewabilityIO'; const CONFIG_ENABLED = 'enabled'; @@ -80,7 +81,7 @@ export const init = () => { events.on(EVENTS.AD_RENDER_SUCCEEDED, ({doc, bid, id}) => { if (isSupportedMediaType(bid)) { const viewable = new IntersectionObserver(viewCallbackFactory(bid), getViewableOptions(bid)); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); viewable.observe(element); } }); diff --git a/modules/concertBidAdapter.js b/modules/concertBidAdapter.js index a83c078ccef..0af69b71f32 100644 --- a/modules/concertBidAdapter.js +++ b/modules/concertBidAdapter.js @@ -4,6 +4,7 @@ import { getStorageManager } from '../src/storageManager.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -70,7 +71,7 @@ export const spec = { payload.slots = validBidRequests.map((bidRequest) => { eids.push(...(bidRequest.userIdAsEids || [])); - const adUnitElement = document.getElementById(bidRequest.adUnitCode); + const adUnitElement = getAdUnitElement(bidRequest); const coordinates = getOffset(adUnitElement); const slot = { diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 7b22de3aa1d..b5a749af56b 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -25,6 +25,7 @@ import { BANNER, VIDEO, } from '../src/mediaTypes.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'connatix'; @@ -111,7 +112,7 @@ export function _getViewability(element, topWin, { w, h } = {}) { } export function detectViewability(bid) { - const { params, adUnitCode } = bid; + const { params } = bid; const viewabilityContainerIdentifier = params.viewabilityContainerIdentifier; @@ -137,7 +138,7 @@ export function detectViewability(bid) { bidParamSizes = typeof bidParamSizes === 'undefined' && bid.mediaType && bid.mediaType.video && bid.mediaType.video.playerSize ? bid.mediaType.video.playerSize : bidParamSizes; bidParamSizes = typeof bidParamSizes === 'undefined' && bid.mediaType && bid.mediaType.video && isNumber(bid.mediaType.video.w) && isNumber(bid.mediaType.h) ? [bid.mediaType.video.w, bid.mediaType.video.h] : bidParamSizes; minSize = _getMinSize(bidParamSizes ?? []) - element = document.getElementById(adUnitCode); + element = getAdUnitElement(bid); } if (_isViewabilityMeasurable(element)) { diff --git a/modules/contxtfulRtdProvider.js b/modules/contxtfulRtdProvider.js index 4c319c9b48a..f711c300b8b 100644 --- a/modules/contxtfulRtdProvider.js +++ b/modules/contxtfulRtdProvider.js @@ -292,6 +292,7 @@ function getDivIdPosition(divId) { let domElement; + // TODO: this should use getAdUnitElement if (inIframe() === true) { const ws = getWindowSelf(); const currentElement = ws.document.getElementById(divId); @@ -335,6 +336,7 @@ function tryGetDivIdPosition(divIdMethod) { return undefined; } +// TODO unified adUnit/element association in 11 function tryMultipleDivIdPositions(adUnit) { const divMethods = [ // ortb2\ diff --git a/modules/cwireBidAdapter.js b/modules/cwireBidAdapter.js index 875dfdedf67..ccf6697987b 100644 --- a/modules/cwireBidAdapter.js +++ b/modules/cwireBidAdapter.js @@ -11,6 +11,7 @@ import { getBoundingClientRect } from "../libraries/boundingClientRect/boundingC import { hasPurpose1Consent } from "../src/utils/gdpr.js"; import { sendBeacon } from "../src/ajax.js"; import { isAutoplayEnabled } from "../libraries/autoplayDetection/autoplay.js"; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -35,7 +36,7 @@ export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); */ function slotDimensions(bid) { const adUnitCode = bid.adUnitCode; - const slotEl = document.getElementById(adUnitCode); + const slotEl = getAdUnitElement(bid); if (slotEl) { logInfo(`Slot element found: ${adUnitCode}`); diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index 7ef55e31784..ab8c3ce5874 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -420,6 +420,7 @@ function _mapAdUnitPathToElementId(adUnitCode) { } function _getAdSlotHTMLElement(adUnitCode) { + // TODO: this should use getAdUnitElement return document.getElementById(adUnitCode) || document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); } diff --git a/modules/fanBidAdapter.js b/modules/fanBidAdapter.js index 04247011751..266f121812c 100644 --- a/modules/fanBidAdapter.js +++ b/modules/fanBidAdapter.js @@ -6,6 +6,7 @@ import { getBidFloor } from '../libraries/currencyUtils/floor.js'; import { getStorageManager } from '../src/storageManager.js'; import { Renderer } from '../src/Renderer.js'; import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'freedomadnetwork'; const BIDDER_VERSION = '0.2.0'; @@ -349,8 +350,7 @@ function createRenderer(bid, videoPlayerUrl) { try { renderer.setRender(function (bidResponse) { - const divId = document.getElementById(bid.adUnitCode) ? bid.adUnitCode : getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId; - const adUnit = document.getElementById(divId); + const adUnit = getAdUnitElement(bidResponse) ?? document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId) if (!window.createOutstreamPlayer) { logWarn('Renderer error: outstream player is not available'); diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 66e74badf5e..d4d6c888057 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -16,6 +16,7 @@ import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js'; import {ortb25Translator} from '../libraries/ortb2.5Translator/translator.js'; import {getCurrencyFromBidderRequest} from '../libraries/ortb2Utils/currency.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const ENDPOINTS = { 'gamoshi': 'https://rtb.gamoshi.io', 'cleanmedianet': 'https://bidder.cleanmediaads.com' @@ -250,7 +251,7 @@ function renderOutstream(bid) { window['GamoshiPlayer'].renderAd({ id: unitId, debug: window.location.href.indexOf('pbjsDebug') >= 0, - placement: document.getElementById(bid.adUnitCode), + placement: getAdUnitElement(bid), width: bid.width, height: bid.height, events: { diff --git a/modules/h12mediaBidAdapter.js b/modules/h12mediaBidAdapter.js index 963ae660e57..0b1a050a153 100644 --- a/modules/h12mediaBidAdapter.js +++ b/modules/h12mediaBidAdapter.js @@ -2,6 +2,7 @@ import { inIframe, logError, logMessage, deepAccess, getWinDimensions } from '.. import { registerBidder } from '../src/adapters/bidderFactory.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportSize } from '../libraries/viewport/viewport.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'h12media'; const DEFAULT_URL = 'https://bidder.h12-media.com/prebid/'; const DEFAULT_CURRENCY = 'USD'; @@ -30,7 +31,7 @@ export const spec = { pubsubid = ''; } const pubcontainerid = bidderParams.pubcontainerid; - const adUnitElement = document.getElementById(pubcontainerid || bidRequest.adUnitCode); + const adUnitElement = pubcontainerid ? document.getElementById(pubcontainerid) : getAdUnitElement(bidRequest); const ishidden = !isVisible(adUnitElement); const framePos = getFramePos(); const coords = isiframe ? { diff --git a/modules/hypelabBidAdapter.js b/modules/hypelabBidAdapter.js index bc562b84cb3..8edd78232b3 100644 --- a/modules/hypelabBidAdapter.js +++ b/modules/hypelabBidAdapter.js @@ -5,6 +5,7 @@ import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRa import { ajax } from '../src/ajax.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getWalletPresence, getWalletProviderFlags } from '../libraries/hypelabUtils/hypelabUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; export const BIDDER_CODE = 'hypelab'; export const ENDPOINT_URL = 'https://api.hypelab.com'; @@ -55,7 +56,7 @@ function buildRequests(validBidRequests, bidderRequest) { winDimensions?.innerHeight || 0 ), ]; - const pp = getPosition(request.adUnitCode); + const pp = getPosition(request); const payload = { property_slug: request.params.property_slug, @@ -121,8 +122,8 @@ function getBidFloor(bid, sizes) { return floor; } -function getPosition(id) { - const element = document.getElementById(id); +function getPosition(bidRequest) { + const element = getAdUnitElement(bidRequest); if (!element) return null; const rect = getBoundingClientRect(element); return [rect.left, rect.top]; diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index da01c3daa07..eedccabac52 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -23,14 +23,16 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { INSTREAM, OUTSTREAM } from '../src/video.js'; import { Renderer } from '../src/Renderer.js'; import {getGptSlotInfoForAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const divIdCache = {}; -export function getDivIdFromAdUnitCode(adUnitCode) { +export function getDivIdFromAdUnit(adUnitCode, target) { if (divIdCache[adUnitCode]) { return divIdCache[adUnitCode]; } - const divId = document.getElementById(adUnitCode) ? adUnitCode : getGptSlotInfoForAdUnitCode(adUnitCode).divId; + const element = getAdUnitElement(target); + const divId = element?.id ? element.id : getGptSlotInfoForAdUnitCode(adUnitCode).divId; divIdCache[adUnitCode] = divId; return divId; } @@ -1357,7 +1359,7 @@ function createNativeImps(validBidRequest, nativeImps) { nativeImps[validBidRequest.adUnitCode].tagId = deepAccess(validBidRequest, 'params.tagId'); const adUnitCode = validBidRequest.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, validBidRequest); nativeImps[validBidRequest.adUnitCode].adUnitCode = adUnitCode; nativeImps[validBidRequest.adUnitCode].divId = divId; } @@ -1379,7 +1381,7 @@ function createVideoImps(validBidRequest, videoImps) { videoImps[validBidRequest.adUnitCode].tagId = deepAccess(validBidRequest, 'params.tagId'); const adUnitCode = validBidRequest.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, validBidRequest); videoImps[validBidRequest.adUnitCode].adUnitCode = adUnitCode; videoImps[validBidRequest.adUnitCode].divId = divId; } @@ -1418,7 +1420,7 @@ function createBannerImps(validBidRequest, missingBannerSizes, bannerImps, bidde } const adUnitCode = validBidRequest.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, validBidRequest); bannerImps[validBidRequest.adUnitCode].adUnitCode = adUnitCode; bannerImps[validBidRequest.adUnitCode].divId = divId; @@ -1486,7 +1488,7 @@ function createMissingBannerImp(bid, imp, newSize) { function outstreamRenderer(bid) { bid.renderer.push(function () { const adUnitCode = bid.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, bid); if (!divId) { logWarn(`IX Bid Adapter: adUnitCode: ${divId} not found on page.`); return; diff --git a/modules/livewrappedAnalyticsAdapter.js b/modules/livewrappedAnalyticsAdapter.js index 37b73368fdc..515a88b9b53 100644 --- a/modules/livewrappedAnalyticsAdapter.js +++ b/modules/livewrappedAnalyticsAdapter.js @@ -4,6 +4,7 @@ import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import { EVENTS } from '../src/constants.js'; import adapterManager from '../src/adapterManager.js'; import { getGlobal } from '../src/prebidGlobal.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const ANALYTICSTYPE = 'endpoint'; const URL = 'https://lwadm.com/analytics/10'; @@ -41,7 +42,7 @@ const livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTY cache.auctions[args.auctionId].gdprApplies = args.gdprConsent ? args.gdprConsent.gdprApplies : undefined; cache.auctions[args.auctionId].gdprConsent = args.gdprConsent ? args.gdprConsent.consentString : undefined; let lwFloor; - const container = document.getElementById(bidRequest.adUnitCode); + const container = getAdUnitElement(bidRequest); let adUnitId = container ? container.getAttribute('data-adunitid') : undefined; adUnitId = adUnitId != null ? adUnitId : undefined; diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 0224c951374..1ed553a30d0 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -5,6 +5,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; import {getDNT} from '../libraries/dnt/index.js'; function MarsmediaAdapter() { @@ -167,7 +168,7 @@ function MarsmediaAdapter() { bidSizes = bidSizes.filter(size => isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index a2922c6cd3e..9123f05c601 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -31,6 +31,7 @@ import { } from '../libraries/appnexusUtils/anKeywords.js'; import {convertCamelToUnderscore} from '../libraries/appnexusUtils/anUtils.js'; import {chunk} from '../libraries/chunk/chunk.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -933,19 +934,18 @@ function buildNativeRequest(params) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Mediafuse renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { - var el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); +function hidedfpContainer(container) { + var el = container.querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document.getElementById(elementId).querySelectorAll("script[id^='sas_script']"); + const el = container.querySelectorAll("script[id^='sas_script']"); if (el[0].nextSibling && el[0].nextSibling.localName === 'iframe') { el[0].nextSibling.style.setProperty('display', 'none'); } @@ -955,8 +955,9 @@ function hideSASIframe(elementId) { } function outstreamRender(bid) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); // push to render queue because ANOutstreamVideo may not be loaded bid.renderer.push(() => { window.ANOutstreamVideo.renderAd({ diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 18a557c8617..6e6685ef737 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -23,6 +23,7 @@ import {GLOBAL_VENDOR_ID, MEDIANET} from '../libraries/medianetUtils/constants.j import {getGlobal} from '../src/prebidGlobal.js'; import {getBoundingClientRect} from '../libraries/boundingClientRect/boundingClientRect.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -133,11 +134,11 @@ function getWindowSize() { } } -function getCoordinates(adUnitCode) { - let element = document.getElementById(adUnitCode); - if (!element && adUnitCode.indexOf('/') !== -1) { +function getCoordinates(bidRequest) { + let element = getAdUnitElement(bidRequest); + if (!element && bidRequest.adUnitCode.indexOf('/') !== -1) { // now it means that adUnitCode is GAM AdUnitPath - const {divId} = getGptSlotInfoForAdUnitCode(adUnitCode); + const {divId} = getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode); if (isStr(divId)) { element = document.getElementById(divId); } @@ -239,7 +240,7 @@ function slotParams(bidRequest, bidderRequests) { if (bidFloor) { params.bidfloor = bidFloor; } - const coordinates = getCoordinates(bidRequest.adUnitCode); + const coordinates = getCoordinates(bidRequest); if (coordinates && params.banner && params.banner.length !== 0) { const normCoordinates = normalizeCoordinates(coordinates); params.ext.coordinates = normCoordinates; diff --git a/modules/msftBidAdapter.js b/modules/msftBidAdapter.js index 6155b91e778..1416dcb89cf 100644 --- a/modules/msftBidAdapter.js +++ b/modules/msftBidAdapter.js @@ -31,6 +31,7 @@ import { logWarn, mergeDeep } from "../src/utils.js"; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = "msft"; const DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout']; @@ -502,12 +503,10 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { +function hidedfpContainer(container) { try { - const el = document - .getElementById(elementId) + const el = container .querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty("display", "none"); @@ -517,11 +516,10 @@ function hidedfpContainer(elementId) { } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document - .getElementById(elementId) + const el = container .querySelectorAll("script[id^='sas_script']"); if (el[0]?.nextSibling?.localName === "iframe") { el[0].nextSibling.style.setProperty("display", "none"); @@ -539,8 +537,9 @@ function handleOutstreamRendererEvents(bid, id, eventName) { } function outstreamRender(bid, doc) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); // push to render queue because ANOutstreamVideo may not be loaded yet bid.renderer.push(() => { const win = doc?.defaultView || window; diff --git a/modules/nexverseBidAdapter.js b/modules/nexverseBidAdapter.js index 91e78b807bd..6aef2b2d078 100644 --- a/modules/nexverseBidAdapter.js +++ b/modules/nexverseBidAdapter.js @@ -8,6 +8,7 @@ import { getDeviceModel, buildEndpointUrl, isBidRequestValid, parseNativeRespons import {getStorageManager} from '../src/storageManager.js'; import {MODULE_TYPE_UID} from '../src/activities/modules.js'; import { config } from '../src/config.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'nexverse'; @@ -191,7 +192,7 @@ function buildOpenRtbRequest(bid, bidderRequest) { const imps = []; // Calculate viewability percentage for the ad unit - const adUnitElement = document.getElementById(bid.adUnitCode); + const adUnitElement = getAdUnitElement(bid); let viewabilityPercentage = 0; if (adUnitElement) { const rect = getBoundingClientRect(adUnitElement); diff --git a/modules/omsBidAdapter.js b/modules/omsBidAdapter.js index fd7be06409e..8bac9c8c04c 100644 --- a/modules/omsBidAdapter.js +++ b/modules/omsBidAdapter.js @@ -16,6 +16,7 @@ import {percentInView} from '../libraries/percentInView/percentInView.js'; import {getUserSyncParams} from '../libraries/userSyncUtils/userSyncUtils.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; import {getBidFloor, isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'oms'; const URL = 'https://rt.marphezis.com/hb'; @@ -43,7 +44,7 @@ function buildRequests(bidReqs, bidderRequest) { bidSizes = bidSizes.filter(size => isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) : 'na'; const viewabilityAmountRounded = isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount); diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 827291f5407..8486a982050 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -9,6 +9,7 @@ import { deepClone, logError, deepAccess, getWinDimensions } from '../src/utils. import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { toOrtbNativeRequest } from '../src/native.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -358,14 +359,14 @@ function setGeneralInfo(bidRequest) { if (params.dealId) { this['dealId'] = params.dealId; } - const coords = getSpaceCoords(bidRequest.adUnitCode); + const coords = getSpaceCoords(bidRequest); if (coords) { this['coords'] = coords; } } -function getSpaceCoords(id) { - const space = document.getElementById(id); +function getSpaceCoords(bidRequest) { + const space = getAdUnitElement(bidRequest); try { const { top, left, width, height } = getBoundingClientRect(space); let window = space.ownerDocument.defaultView; diff --git a/modules/onomagicBidAdapter.js b/modules/onomagicBidAdapter.js index c3176d7abcc..7e380d540c0 100644 --- a/modules/onomagicBidAdapter.js +++ b/modules/onomagicBidAdapter.js @@ -12,6 +12,7 @@ import {BANNER} from '../src/mediaTypes.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; import {getBidFloor, isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'onomagic'; const URL = 'https://bidder.onomagic.com/hb'; @@ -39,7 +40,7 @@ function buildRequests(bidReqs, bidderRequest) { bidSizes = bidSizes.filter(size => isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index e0b61880fb7..87617623284 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -9,6 +9,7 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { NATIVE_ASSET_TYPES, NATIVE_IMAGE_TYPES, PREBID_NATIVE_DATA_KEYS_TO_ORTB, NATIVE_KEYS_THAT_ARE_NOT_ASSETS, NATIVE_KEYS } from '../src/constants.js'; import { addDealCustomTargetings, addPMPDeals } from '../libraries/dealUtils/dealUtils.js'; import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -599,7 +600,7 @@ const BB_RENDERER = { } const rendererId = BB_RENDERER.getRendererId(PUBLICATION, bid.rendererCode); - const ele = document.getElementById(bid.adUnitCode); // NB convention + const ele = getAdUnitElement(bid); const renderer = window.bluebillywig.renderers.find(r => r._id === rendererId); if (renderer) renderer.bootstrap(config, ele); diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 477da80d420..cb8101bbae7 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -23,6 +23,7 @@ import { } from '../src/utils.js'; import {getAllOrtbKeywords} from '../libraries/keywords/keywords.js'; import {getUserSyncParams} from '../libraries/userSyncUtils/userSyncUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -827,7 +828,7 @@ function hideSmartAdServerIframe(adUnit) { function renderBid(bid) { // hide existing ad units - const adUnitElement = document.getElementById(bid.adUnitCode); + const adUnitElement = getAdUnitElement(bid); hideGoogleAdsDiv(adUnitElement); hideSmartAdServerIframe(adUnitElement); diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js index f93ed814a0a..2e9ca96f6f7 100644 --- a/modules/seedtagBidAdapter.js +++ b/modules/seedtagBidAdapter.js @@ -5,6 +5,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { _map, getWinDimensions, isArray, triggerPixel } from '../src/utils.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -123,7 +124,7 @@ function buildBidRequest(validBidRequest) { supplyTypes: mediaTypes, adUnitId: params.adUnitId, adUnitCode: validBidRequest.adUnitCode, - geom: geom(validBidRequest.adUnitCode), + geom: geom(validBidRequest), placement: params.placement, requestCount: validBidRequest.bidderRequestsCount || 1, }; @@ -217,8 +218,8 @@ function ttfb() { return ttfb >= 0 && ttfb <= performance.now() ? ttfb : 0; } -function geom(adunitCode) { - const slot = document.getElementById(adunitCode); +function geom(bidRequest) { + const slot = getAdUnitElement(bidRequest); if (slot) { const { top, left, width, height } = getBoundingClientRect(slot); const viewport = { diff --git a/modules/sparteoBidAdapter.js b/modules/sparteoBidAdapter.js index 13cb0198594..350c3109984 100644 --- a/modules/sparteoBidAdapter.js +++ b/modules/sparteoBidAdapter.js @@ -91,6 +91,7 @@ function createRenderer(rendererConfig) { } function outstreamRender(bid) { + // TODO this should use getAdUnitElement if (!document.getElementById(bid.adUnitCode)) { logError(`Sparteo Bid Adapter: Video renderer did not started. bidResponse.adUnitCode is probably not a DOM element : ${bid.adUnitCode}`); return; diff --git a/modules/stroeerCoreBidAdapter.js b/modules/stroeerCoreBidAdapter.js index aa9f656aa24..ec29df5a045 100644 --- a/modules/stroeerCoreBidAdapter.js +++ b/modules/stroeerCoreBidAdapter.js @@ -156,6 +156,7 @@ const isMainPageAccessible = () => { } const elementInView = (elementId) => { + // TODO this should use getAdUnitElement const resolveElement = (elId) => { const win = getWindowSelf(); diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 3b39dd3db03..276fd335e7b 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -11,6 +11,7 @@ import {getConnectionType} from '../libraries/connectionInfo/connectionUtils.js' import {getViewportCoordinates} from '../libraries/viewport/viewport.js'; import {percentInView} from '../libraries/percentInView/percentInView.js'; import {getBoundingClientRect} from '../libraries/boundingClientRect/boundingClientRect.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; @@ -139,9 +140,9 @@ export function getDeviceExtSignals(existingExt = {}) { }; } -export function getElementSignals(adUnitCode) { +export function getElementSignals(bidRequest) { try { - const element = document.getElementById(adUnitCode); + const element = getAdUnitElement(bidRequest); if (!element) return null; const rect = getBoundingClientRect(element); @@ -419,7 +420,7 @@ function fillTaboolaImpData(bid, imp) { deepSetValue(imp, 'ext.prebid.bidderRequestsCount', bid.bidderRequestsCount); deepSetValue(imp, 'ext.prebid.bidderWinsCount', bid.bidderWinsCount); - const elementSignals = getElementSignals(bid.adUnitCode); + const elementSignals = getElementSignals(bid); if (elementSignals) { if (elementSignals.viewability !== undefined) { deepSetValue(imp, 'ext.viewability', elementSignals.viewability); diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index 45bac54e64c..f0fec36df1e 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -13,6 +13,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {isSlotMatchingAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'underdogmedia'; const UDM_ADAPTER_VERSION = '7.30V'; @@ -109,7 +110,7 @@ export const spec = { sizes = flatten(sizes, parseSizesInput(bidParamSizes)); siteId = +bidParam.params.siteId; const adUnitCode = bidParam.adUnitCode - const element = _getAdSlotHTMLElement(adUnitCode) + const element = _getAdSlotHTMLElement(bidParam) const minSize = _getMinSize(bidParamSizes) placementObject.sizes = parseSizesInput(bidParamSizes) @@ -234,9 +235,9 @@ function _getMinSize(bidParamSizes) { return bidParamSizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min) } -function _getAdSlotHTMLElement(adUnitCode) { - return document.getElementById(adUnitCode) || - document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); +function _getAdSlotHTMLElement(bidRequest) { + return getAdUnitElement(bidRequest) || + document.getElementById(_mapAdUnitPathToElementId(bidRequest.adUnitCode)); } function _mapAdUnitPathToElementId(adUnitCode) { diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index badc0911270..01b8760d085 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -7,6 +7,7 @@ import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingC import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'undertone'; const URL = 'https://hb.undertone.com/hb'; @@ -38,8 +39,8 @@ function getGdprQueryParams(gdprConsent) { return `gdpr=${gdpr}&gdprstr=${gdprstr}`; } -function getBannerCoords(id) { - const element = document.getElementById(id); +function getBannerCoords(bidRequest) { + const element = getAdUnitElement(bidRequest); if (element) { const {left, top} = getBoundingClientRect(element); const viewport = getViewportCoordinates(); @@ -109,7 +110,7 @@ export const spec = { validBidRequests.forEach(bidReq => { const bid = { bidRequestId: bidReq.bidId, - coordinates: getBannerCoords(bidReq.adUnitCode), + coordinates: getBannerCoords(bidReq), hbadaptor: 'prebid', url: pageUrl, domain: domain, diff --git a/modules/valuadBidAdapter.js b/modules/valuadBidAdapter.js index 6a32d80b806..d6af61d8077 100644 --- a/modules/valuadBidAdapter.js +++ b/modules/valuadBidAdapter.js @@ -12,6 +12,7 @@ import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { config } from '../src/config.js'; import { getBoundingBox, percentInView } from '../libraries/percentInView/percentInView.js'; import {isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'valuad'; const GVL_ID = 1478; @@ -106,7 +107,7 @@ const converter = ortbConverter({ const size = {w: adSize[0], h: adSize[1]}; - const element = document.getElementById(bid.adUnitCode) || document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode)?.divId); + const element = getAdUnitElement(bid) || document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode)?.divId); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), size) : 0; const rect = element && getBoundingBox(element, size); diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 801c68acc2d..5b09faa41dd 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -7,6 +7,7 @@ import {getStorageManager} from '../src/storageManager.js'; import {getGptSlotInfoForAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; import { getBidFromResponse } from '../libraries/processResponse/index.js'; import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'visx'; const GVLID = 154; @@ -295,7 +296,7 @@ function makeVideo(videoParams = {}) { } function buildImpObject(bid) { - const { params: { uid }, bidId, mediaTypes, sizes, adUnitCode } = bid; + const { params: { uid }, bidId, mediaTypes, sizes } = bid; const video = mediaTypes && _isVideoBid(bid) && _isValidVideoBid(bid) && makeVideo(mediaTypes.video); const banner = makeBanner((mediaTypes && mediaTypes.banner) || (!video && { sizes })); const impObject = { @@ -308,7 +309,7 @@ function buildImpObject(bid) { }; if (impObject.banner) { - impObject.ext.bidder.adslotExists = _isAdSlotExists(adUnitCode); + impObject.ext.bidder.adslotExists = _isAdSlotExists(bid); } if (bid.ortb2Imp?.ext?.gpid) { @@ -410,12 +411,12 @@ function _isValidVideoBid(bid, logErrors = false) { return result; } -function _isAdSlotExists(adUnitCode) { - if (document.getElementById(adUnitCode)) { +function _isAdSlotExists(bidRequest) { + if (getAdUnitElement(bidRequest)) { return true; } - const gptAdSlot = getGptSlotInfoForAdUnitCode(adUnitCode); + const gptAdSlot = getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode); if (gptAdSlot.divId && document.getElementById(gptAdSlot.divId)) { return true; } diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index 7a8dec47a28..aa4327bdf8f 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -4,6 +4,7 @@ import {deepClone, parseQueryStringParameters, parseSizesInput} from '../src/uti import {getStorageManager} from '../src/storageManager.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'widespace'; const WS_ADAPTER_VERSION = '2.0.1'; @@ -53,7 +54,7 @@ export const spec = { 'inFrame': 1, 'sid': bid.params.sid, 'lcuid': LC_UID, - 'vol': isInHostileIframe ? '' : visibleOnLoad(document.getElementById(bid.adUnitCode)), + 'vol': isInHostileIframe ? '' : visibleOnLoad(getAdUnitElement(bid)), 'gdprCmp': bidderRequest && bidderRequest.gdprConsent ? 1 : 0, 'hb': '1', 'hb.cd': CUST_DATA ? encodedParamValue(CUST_DATA) : '', diff --git a/modules/yandexBidAdapter.js b/modules/yandexBidAdapter.js index 901bbcf29de..ef7b8910c7d 100644 --- a/modules/yandexBidAdapter.js +++ b/modules/yandexBidAdapter.js @@ -7,6 +7,7 @@ import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingC import { ajax } from '../src/ajax.js'; import { config as pbjsConfig } from '../src/config.js'; import { isWebdriverEnabled } from '../libraries/webdriver/webdriver.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid @@ -183,7 +184,7 @@ export const spec = { queryParams['tcf-consent'] = consentString; } - const adUnitElement = document.getElementById(bidRequest.params.pubcontainerid || bidRequest.adUnitCode); + const adUnitElement = bidRequest.params.pubcontainerid ? document.getElementById(bidRequest.params.pubcontainerid) : getAdUnitElement(bidRequest); const windowContext = getContext(adUnitElement); const isIframe = inIframe(); const coords = isIframe ? getFramePosition() : { diff --git a/src/adUnits.ts b/src/adUnits.ts index 2cb94f788e3..644ced4df47 100644 --- a/src/adUnits.ts +++ b/src/adUnits.ts @@ -88,6 +88,11 @@ export interface AdUnitDefinition { * Used by setTargetingForGPTAsync() to match which auction is for which ad slot. */ code: AdUnitCode; + /** + * A DOM element corresponding to this ad unit. + * By default, this is `document.getElementById(adUnit.code)`. + */ + element?: HTMLElement; /** * Bid requests representing demand partners and associated parameters. */ diff --git a/src/adapterManager.ts b/src/adapterManager.ts index 7c0faf40d1d..d569bbf0a2c 100644 --- a/src/adapterManager.ts +++ b/src/adapterManager.ts @@ -214,6 +214,7 @@ const ADUNIT_BID_PROPERTIES = [ 'nativeParams', 'nativeOrtbRequest', 'renderer', + 'element', ] as const; type GetBidsOptions = { diff --git a/src/auction.ts b/src/auction.ts index dff01d6421b..a6aa0c85665 100644 --- a/src/auction.ts +++ b/src/auction.ts @@ -33,7 +33,7 @@ import {getMinBidCacheTTL, onMinBidCacheTTLChange} from './bidTTL.js'; import type {Bid, BidResponse} from "./bidfactory.ts"; import type {AdUnitCode, BidderCode, Identifier, ORTBFragments} from './types/common.d.ts'; import type {TargetingMap} from "./targeting.ts"; -import type {AdUnit} from "./adUnits.ts"; +import type {AdUnit, AdUnitDefinition} from "./adUnits.ts"; import type {MediaType} from "./mediaTypes.ts"; import type {VideoContext} from "./video.ts"; import { isActivityAllowed } from './activities/rules.js'; @@ -661,6 +661,7 @@ declare module './bidfactory' { } interface BaseBid { + element?: AdUnitDefinition['element']; /** * true if this bid is for an interstitial slot. */ @@ -770,6 +771,7 @@ function getPreparedBidForAuction(bid: Partial, {index = auctionManager.ind const adUnit = index.getAdUnit(bid); bid.instl = adUnit?.ortb2Imp?.instl === 1; + bid.element = adUnit?.element; // a publisher-defined renderer can be used to render bids const bidRenderer = index.getBidRequest(bid)?.renderer || adUnit.renderer; diff --git a/src/secureCreatives.js b/src/secureCreatives.js index a385113e54e..99e140070df 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -15,6 +15,7 @@ import { } from './adRendering.js'; import {getCreativeRendererSource, PUC_MIN_VERSION} from './creativeRenderers.js'; import {PbPromise} from './utils/promise.js'; +import {getAdUnitElement} from './utils/adUnits.js'; import {auctionManager} from './auctionManager.js'; const { REQUEST, RESPONSE, NATIVE, EVENT } = MESSAGES; @@ -165,7 +166,7 @@ export function resizeAnchor(ins, width, height) { }) } -export function resizeRemoteCreative({instl, adId, adUnitCode, width, height}) { +export function resizeRemoteCreative({instl, element, adId, adUnitCode, width, height}) { // do not resize interstitials - the creative frame takes the full screen and sizing of the ad should // be handled within it. if (instl) return; @@ -188,7 +189,7 @@ export function resizeRemoteCreative({instl, adId, adUnitCode, width, height}) { function getElementByAdUnit(elmType) { const id = getElementIdBasedOnAdServer(adId, adUnitCode); - const parentDivEle = document.getElementById(id); + const parentDivEle = id == null ? getAdUnitElement({element, adUnitCode}) : document.getElementById(id); return parentDivEle && parentDivEle.querySelector(elmType); } @@ -205,7 +206,6 @@ export function resizeRemoteCreative({instl, adId, adUnitCode, width, height}) { return apnId; } } - return adUnitCode; } function getDfpElementId(adId) { diff --git a/src/utils/adUnits.ts b/src/utils/adUnits.ts new file mode 100644 index 00000000000..96e412910ab --- /dev/null +++ b/src/utils/adUnits.ts @@ -0,0 +1,21 @@ +import type {AdUnitDefinition} from "../adUnits.ts"; +import type {BidRequest} from "../adapterManager.ts"; +import type {Bid} from "../bidfactory.ts"; + +export function getAdUnitElement(bidRequest: BidRequest): HTMLElement +export function getAdUnitElement(bidResponse: Bid): HTMLElement +export function getAdUnitElement(adUnit: AdUnitDefinition): HTMLElement +export function getAdUnitElement(target: { + code?: string, + adUnitCode?: string, + element?: HTMLElement +}): HTMLElement | null { + if (target.element != null) { + return target.element; + } + const id = target.adUnitCode ?? target.code; + if (id) { + return document.getElementById(id); + } + return null; +} diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index b3a10ede626..5f1a05afd12 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -1278,6 +1278,12 @@ describe('auctionmanager.js', function () { expect(auction.getBidsReceived()[0].ttlBuffer).to.eql(0); }); + it('sets bidResponse.element from adUnit.element', () => { + adUnits[0].element = 'test'; + auction.callBids(); + expect(auction.getBidsReceived()[0].element).to.equal('test'); + }); + [ { request: 1, diff --git a/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js b/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js index 55cddbb0dd2..0fc8c700aff 100644 --- a/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js +++ b/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js @@ -2,7 +2,7 @@ import adnAnalyticsAdapter, { BID_WON_TIMEOUT } from 'modules/adnuntiusAnalytics import { AD_RENDER_FAILED_REASON, EVENTS, STATUS } from 'src/constants.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr.js'; -import { setConfig } from 'modules/currency.js'; +import * as adUnits from 'src/utils/adUnits'; const events = require('src/events'); const utils = require('src/utils'); @@ -301,7 +301,7 @@ describe('Adnuntius analytics adapter', function () { } sandbox.stub(events, 'getEvents').returns([]); sandbox.stub(utils, 'timestamp').returns(1519149562416); - sandbox.stub(document, 'getElementById').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); clock = sandbox.useFakeTimers(1519767013781); }); diff --git a/test/spec/modules/concertBidAdapter_spec.js b/test/spec/modules/concertBidAdapter_spec.js index 6c842e58d37..cf22b23e9ae 100644 --- a/test/spec/modules/concertBidAdapter_spec.js +++ b/test/spec/modules/concertBidAdapter_spec.js @@ -3,6 +3,7 @@ import sinon from 'sinon'; import { spec, storage } from 'modules/concertBidAdapter.js'; import { hook } from 'src/hook.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; +import * as adUnits from 'src/utils/adUnits'; describe('ConcertAdapter', function () { let bidRequests; @@ -86,7 +87,7 @@ describe('ConcertAdapter', function () { } sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('desktop_leaderboard_variable').returns(element) + sandbox.stub(adUnits, 'getAdUnitElement').returns(element) }); afterEach(function () { diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index aa9bdac75bd..e8a88775a5f 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -19,6 +19,7 @@ import adapterManager from '../../../src/adapterManager.js'; import * as ajax from '../../../src/ajax.js'; import { ADPOD, BANNER, VIDEO } from '../../../src/mediaTypes.js'; import * as winDimensions from '../../../src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; const BIDDER_CODE = 'connatix'; @@ -220,7 +221,7 @@ describe('connatixBidAdapter', function () { let getBoundingClientRectStub; let topWinMock; let querySelectorStub; - let getElementByIdStub; + let getElementStub; let sandbox; beforeEach(() => { @@ -237,7 +238,7 @@ describe('connatixBidAdapter', function () { }; querySelectorStub = sandbox.stub(window.top.document, 'querySelector'); - getElementByIdStub = sandbox.stub(document, 'getElementById'); + getElementStub = sandbox.stub(adUnits, 'getAdUnitElement'); sandbox.stub(winDimensions, 'getWinDimensions').callsFake(() => ( { document: { @@ -272,7 +273,7 @@ describe('connatixBidAdapter', function () { }); querySelectorStub.withArgs('#validElement').returns(element); - getElementByIdStub.returns(null); + getElementStub.returns(null); const result = connatixDetectViewability(bid); @@ -298,7 +299,7 @@ describe('connatixBidAdapter', function () { }); querySelectorStub.withArgs('#invalidElement').returns(null); - getElementByIdStub.withArgs('adUnitCode123').returns(element); + getElementStub.returns(element); const result = connatixDetectViewability(bid); @@ -325,7 +326,7 @@ describe('connatixBidAdapter', function () { }); // The fallback should use the adUnitCode to find the element - getElementByIdStub.withArgs('adUnitCode123').returns(element); + getElementStub.returns(element); const result = connatixDetectViewability(bid); diff --git a/test/spec/modules/cwireBidAdapter_spec.js b/test/spec/modules/cwireBidAdapter_spec.js index 1a514d33155..6943618cf51 100644 --- a/test/spec/modules/cwireBidAdapter_spec.js +++ b/test/spec/modules/cwireBidAdapter_spec.js @@ -6,6 +6,7 @@ import * as utils from "src/utils.js"; import sinon, { stub } from "sinon"; import { config } from "../../../src/config.js"; import * as autoplayLib from "../../../libraries/autoplayDetection/autoplay.js"; +import * as adUnits from 'src/utils/adUnits'; describe("C-WIRE bid adapter", () => { config.setConfig({ debug: true }); @@ -101,8 +102,8 @@ describe("C-WIRE bid adapter", () => { describe("buildRequests reads adUnit offsetWidth and offsetHeight", function () { beforeEach(function () { - const documentStub = sandbox.stub(document, "getElementById"); - documentStub.withArgs(`${bidRequests[0].adUnitCode}`).returns({ + const documentStub = sandbox.stub(adUnits, "getAdUnitElement"); + documentStub.returns({ offsetWidth: 200, offsetHeight: 250, getBoundingClientRect() { @@ -115,11 +116,9 @@ describe("C-WIRE bid adapter", () => { const request = spec.buildRequests([bidRequest], bidderRequest); const payload = JSON.parse(request.data); - const el = document.getElementById(`${bidRequest.adUnitCode}`); logInfo(JSON.stringify(payload)); - expect(el).to.exist; expect(payload.slots[0].cwExt.dimensions.width).to.equal(200); expect(payload.slots[0].cwExt.dimensions.height).to.equal(250); expect(payload.slots[0].cwExt.style.maxHeight).to.not.exist; @@ -131,8 +130,8 @@ describe("C-WIRE bid adapter", () => { }); describe("buildRequests reads style attributes", function () { beforeEach(function () { - const documentStub = sandbox.stub(document, "getElementById"); - documentStub.withArgs(`${bidRequests[0].adUnitCode}`).returns({ + const documentStub = sandbox.stub(adUnits, "getAdUnitElement"); + documentStub.returns({ style: { maxWidth: "400px", maxHeight: "350px", @@ -147,11 +146,8 @@ describe("C-WIRE bid adapter", () => { const request = spec.buildRequests([bidRequest], bidderRequest); const payload = JSON.parse(request.data); - const el = document.getElementById(`${bidRequest.adUnitCode}`); - logInfo(JSON.stringify(payload)); - expect(el).to.exist; expect(payload.slots[0].cwExt.style.maxWidth).to.eq("400px"); expect(payload.slots[0].cwExt.style.maxHeight).to.eq("350px"); }); diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 1a5bd0f1c01..39a9321fca9 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -2,7 +2,7 @@ import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { expect } from 'chai'; import { newBidder } from 'src/adapters/bidderFactory.js'; -import { spec, storage, FEATURE_TOGGLES, LOCAL_STORAGE_FEATURE_TOGGLES_KEY, REQUESTED_FEATURE_TOGGLES, combineImps, bidToVideoImp, bidToNativeImp, deduplicateImpExtFields, removeSiteIDs, addDeviceInfo, getDivIdFromAdUnitCode } from '../../../modules/ixBidAdapter.js'; +import { spec, storage, FEATURE_TOGGLES, LOCAL_STORAGE_FEATURE_TOGGLES_KEY, REQUESTED_FEATURE_TOGGLES, combineImps, bidToVideoImp, bidToNativeImp, deduplicateImpExtFields, removeSiteIDs, addDeviceInfo, getDivIdFromAdUnit } from '../../../modules/ixBidAdapter.js'; import { deepAccess, deepClone } from '../../../src/utils.js'; import * as ajaxLib from 'src/ajax.js'; import * as gptUtils from '../../../libraries/gptUtils/gptUtils.js'; @@ -5217,15 +5217,15 @@ describe('IndexexchangeAdapter', function () { const el = document.createElement('div'); el.id = adUnitCode; document.body.appendChild(el); - expect(getDivIdFromAdUnitCode(adUnitCode)).to.equal(adUnitCode); + expect(getDivIdFromAdUnit(adUnitCode, {code: adUnitCode})).to.equal(adUnitCode); document.body.removeChild(el); }); it('retrieves divId from GPT once and caches result', () => { const adUnitCode = 'div-ad2'; const stub = sinon.stub(gptUtils, 'getGptSlotInfoForAdUnitCode').returns({divId: 'gpt-div'}); - const first = getDivIdFromAdUnitCode(adUnitCode); - const second = getDivIdFromAdUnitCode(adUnitCode); + const first = getDivIdFromAdUnit(adUnitCode, {}); + const second = getDivIdFromAdUnit(adUnitCode, {}); expect(first).to.equal('gpt-div'); expect(second).to.equal('gpt-div'); expect(stub.calledOnce).to.be.true; diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js index f84d4ace1ff..d0fadf377a1 100644 --- a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -3,6 +3,7 @@ import { AD_RENDER_FAILED_REASON, EVENTS, STATUS } from 'src/constants.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr.js'; import { setConfig } from 'modules/currency.js'; +import * as adUnits from 'src/utils/adUnits'; const events = require('src/events'); const utils = require('src/utils'); @@ -323,7 +324,7 @@ describe('Livewrapped analytics adapter', function () { } sandbox.stub(events, 'getEvents').returns([]); sandbox.stub(utils, 'timestamp').returns(1519149562416); - sandbox.stub(document, 'getElementById').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); clock = sandbox.useFakeTimers(1519767013781); setConfig({ diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index cdfda655af3..d0ab86d90ec 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -2,6 +2,7 @@ import { spec } from 'modules/marsmediaBidAdapter.js'; import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { internal, resetWinDimensions } from '../../../src/utils.js'; +import * as adUnits from 'src/utils/adUnits'; var marsAdapter = spec; @@ -72,7 +73,7 @@ describe('marsmedia adapter tests', function () { ]; sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('Unit-Code').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); sandbox.stub(utils, 'getWindowTop').returns(win); sandbox.stub(utils, 'getWindowSelf').returns(win); }); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 728c68c20b1..d20206895f4 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -6,6 +6,7 @@ import { config } from '../../../src/config.js'; import {server} from '../../mocks/xhr.js'; import {resetWinDimensions} from '../../../src/utils.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; +import * as adUnits from 'src/utils/adUnits'; getGlobal().version = getGlobal().version || 'version'; const VALID_BID_REQUEST = [{ @@ -1979,17 +1980,13 @@ describe('Media.net bid adapter', function () { beforeEach(function () { getGlobal().medianetGlobals = {}; - const documentStub = sandbox.stub(document, 'getElementById'); const boundingRect = { top: 50, left: 50, bottom: 100, right: 100 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + sandbox.stub(adUnits, 'getAdUnitElement').returns({ getBoundingClientRect: () => boundingRect }); const windowSizeStub = sandbox.stub(spec, 'getWindowSize'); @@ -2089,14 +2086,14 @@ describe('Media.net bid adapter', function () { }); describe('slot visibility', function () { - let documentStub; + let elementStub; beforeEach(function () { const windowSizeStub = sandbox.stub(spec, 'getWindowSize'); windowSizeStub.returns({ w: 1000, h: 1000 }); - documentStub = sandbox.stub(document, 'getElementById'); + elementStub = sandbox.stub(adUnits, 'getAdUnitElement'); }); it('slot visibility should be 2 and ratio 0 when ad unit is BTF', function () { const boundingRect = { @@ -2105,10 +2102,7 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect }); @@ -2124,10 +2118,7 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect }); const bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); @@ -2142,10 +2133,7 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect }); const bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); @@ -2170,12 +2158,9 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs(divId).returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); + }) const bidRequest = [{...VALID_BID_REQUEST[0], adUnitCode: code}] const bidReq = spec.buildRequests(bidRequest, VALID_AUCTIONDATA); diff --git a/test/spec/modules/omsBidAdapter_spec.js b/test/spec/modules/omsBidAdapter_spec.js index 3b9c0779fb0..6f5e0ac05c9 100644 --- a/test/spec/modules/omsBidAdapter_spec.js +++ b/test/spec/modules/omsBidAdapter_spec.js @@ -3,6 +3,7 @@ import * as utils from 'src/utils.js'; import {spec} from 'modules/omsBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory.js'; import * as winDimensions from 'src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; const URL = 'https://rt.marphezis.com/hb'; @@ -83,7 +84,7 @@ describe('omsBidAdapter', function () { }]; sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('adunit-code').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); sandbox.stub(winDimensions, 'getWinDimensions').returns(win); sandbox.stub(utils, 'getWindowTop').returns(win); sandbox.stub(utils, 'getWindowSelf').returns(win); diff --git a/test/spec/modules/onomagicBidAdapter_spec.js b/test/spec/modules/onomagicBidAdapter_spec.js index d043363b34d..ab44d280797 100644 --- a/test/spec/modules/onomagicBidAdapter_spec.js +++ b/test/spec/modules/onomagicBidAdapter_spec.js @@ -3,6 +3,7 @@ import * as utils from 'src/utils.js'; import { spec } from 'modules/onomagicBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import * as winDimensions from 'src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; const URL = 'https://bidder.onomagic.com/hb'; @@ -61,7 +62,7 @@ describe('onomagicBidAdapter', function() { sandbox = sinon.createSandbox(); sandbox.stub(winDimensions, 'getWinDimensions').returns(win); - sandbox.stub(document, 'getElementById').withArgs('adunit-code').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); sandbox.stub(utils, 'getWindowTop').returns(win); sandbox.stub(utils, 'getWindowSelf').returns(win); }); diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js index 3a448c90d78..f80a95fc9ff 100644 --- a/test/spec/modules/seedtagBidAdapter_spec.js +++ b/test/spec/modules/seedtagBidAdapter_spec.js @@ -4,23 +4,13 @@ import * as utils from 'src/utils.js'; import * as mockGpt from 'test/spec/integration/faker/googletag.js'; import { config } from '../../../src/config.js'; import { BIDFLOOR_CURRENCY } from '../../../modules/seedtagBidAdapter.js'; +import * as adUnits from 'src/utils/adUnits'; const PUBLISHER_ID = '0000-0000-01'; const ADUNIT_ID = '000000'; const adUnitCode = '/19968336/header-bid-tag-0' -// create a default adunit -const slot = document.createElement('div'); -slot.id = adUnitCode; -slot.style.width = '300px' -slot.style.height = '250px' -slot.style.position = 'absolute' -slot.style.top = '10px' -slot.style.left = '20px' - -document.body.appendChild(slot); - function getSlotConfigs(mediaTypes, params) { return { params: params, @@ -60,12 +50,25 @@ const createBannerSlotConfig = (mediatypes) => { }; describe('Seedtag Adapter', function () { + let sandbox; beforeEach(function () { mockGpt.reset(); + sandbox = sinon.createSandbox(); + sandbox.stub(adUnits, 'getAdUnitElement').returns({ + getBoundingClientRect() { + return { + top: 10, + left: 20, + width: 300, + height: 250 + } + } + }); }); afterEach(function () { mockGpt.enable(); + sandbox.restore(); }); describe('isBidRequestValid method', function () { describe('returns true', function () { @@ -328,9 +331,13 @@ describe('Seedtag Adapter', function () { }); describe('BidRequests params', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - const bidRequests = data.bidRequests; + let request, data, bidRequests; + beforeEach(() => { + request = spec.buildRequests(validBidRequests, bidderRequest); + data = JSON.parse(request.data); + bidRequests = data.bidRequests; + }); + it('should request a Banner', function () { const bannerBid = bidRequests[0]; expect(bannerBid.id).to.equal('30b31c1838de1e'); @@ -369,27 +376,21 @@ describe('Seedtag Adapter', function () { const bidRequests = data.bidRequests; const bannerBid = bidRequests[0]; - // on some CI, the DOM is not initialized, so we need to check if the slot is available - const slot = document.getElementById(adUnitCode) - if (slot) { - expect(bannerBid).to.have.property('geom') - - const params = [['width', 300], ['height', 250], ['top', 10], ['left', 20], ['scrollY', 0]] - params.forEach(([param, value]) => { - expect(bannerBid.geom).to.have.property(param) - expect(bannerBid.geom[param]).to.be.a('number') - expect(bannerBid.geom[param]).to.be.equal(value) - }) - - expect(bannerBid.geom).to.have.property('viewport') - const viewportParams = ['width', 'height'] - viewportParams.forEach(param => { - expect(bannerBid.geom.viewport).to.have.property(param) - expect(bannerBid.geom.viewport[param]).to.be.a('number') - }) - } else { - expect(bannerBid).to.not.have.property('geom') - } + expect(bannerBid).to.have.property('geom') + + const params = [['width', 300], ['height', 250], ['top', 10], ['left', 20], ['scrollY', 0]] + params.forEach(([param, value]) => { + expect(bannerBid.geom).to.have.property(param) + expect(bannerBid.geom[param]).to.be.a('number') + expect(bannerBid.geom[param]).to.be.equal(value) + }) + + expect(bannerBid.geom).to.have.property('viewport') + const viewportParams = ['width', 'height'] + viewportParams.forEach(param => { + expect(bannerBid.geom.viewport).to.have.property(param) + expect(bannerBid.geom.viewport[param]).to.be.a('number') + }) }) it('should have bidfloor parameter if available', function () { diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index ed531371af7..b7ad994dc96 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -2,6 +2,8 @@ import {expect} from 'chai'; import {spec} from 'modules/undertoneBidAdapter.js'; import {BANNER, VIDEO} from '../../../src/mediaTypes.js'; import {deepClone, getWinDimensions} from '../../../src/utils.js'; +import * as adUnits from 'src/utils/adUnits'; +import {getAdUnitElement} from 'src/utils/adUnits'; const URL = 'https://hb.undertone.com/hb'; const BIDDER_CODE = 'undertone'; @@ -314,7 +316,7 @@ describe('Undertone Adapter', () => { }; sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('div-gpt-ad-1460505748561-0').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); }); afterEach(function() { diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index a24f537625e..db7c01d7067 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -8,6 +8,7 @@ import { mergeDeep } from '../../../src/utils.js'; import { setConfig as setCurrencyConfig } from '../../../modules/currency.js'; import { addFPDToBidderRequest } from '../../helpers/fpd.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; +import * as adUnits from 'src/utils/adUnits'; describe('VisxAdapter', function () { const adapter = newBidder(spec); @@ -1069,13 +1070,9 @@ describe('VisxAdapter', function () { before(function() { sandbox = sinon.createSandbox(); - documentStub = sandbox.stub(document, 'getElementById'); - documentStub.withArgs('visx-adunit-code-1').returns({ - id: 'visx-adunit-code-1' - }); - documentStub.withArgs('visx-adunit-element-2').returns({ - id: 'visx-adunit-element-2' - }); + sandbox.stub(adUnits, 'getAdUnitElement').callsFake(({adUnitCode}) => { + return ['visx-adunit-code-1', 'visx-adunit-code-2'].includes(adUnitCode); + }) getGlobal().bidderSettings = { visx: { diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 0be07704ed2..f3481950db4 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -32,6 +32,7 @@ import { TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from '../../../../src/eventTrackers.js'; +import 'src/prebid.js'; var events = require('../../../../src/events.js'); const CONFIG = { @@ -1814,6 +1815,18 @@ describe('adapterManager tests', function () { expect(sizes1).not.to.deep.equal(sizes2); }); + it('should transfer element from ad unit', () => { + adUnits[0].element = 'test'; + const requests = makeBidRequests(); + requests.flatMap(req => req.bids).forEach(bidRequest => { + if (bidRequest.adUnitCode === adUnits[0].code) { + expect(bidRequest.element).to.equal('test'); + } else { + expect(bidRequest.element).to.not.exist; + } + }); + }) + it('should transfer deferBilling from ad unit', () => { adUnits[0].deferBilling = true; const requests = makeBidRequests(); diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js index 9e3f2cab132..ea564e1f923 100644 --- a/test/spec/unit/secureCreatives_spec.js +++ b/test/spec/unit/secureCreatives_spec.js @@ -10,6 +10,7 @@ import {config as configObj} from 'src/config.js'; import * as creativeRenderers from 'src/creativeRenderers.js'; import 'src/prebid.js'; import 'modules/nativeRendering.js'; +import * as adUnits from 'src/utils/adUnits'; import {expect} from 'chai'; diff --git a/test/spec/utils/adUnits_spec.js b/test/spec/utils/adUnits_spec.js new file mode 100644 index 00000000000..89e11232359 --- /dev/null +++ b/test/spec/utils/adUnits_spec.js @@ -0,0 +1,40 @@ +import {getAdUnitElement} from '../../../src/utils/adUnits.js'; + +describe('ad unit utils', () => { + let sandbox; + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + afterEach(() => { + sandbox.restore(); + }); + describe('getAdUnitElement', () => { + beforeEach(() => { + sandbox.stub(document, 'getElementById').callsFake((id) => ({id})); + }); + it('should return null on invalid input', () => { + expect(getAdUnitElement({})).to.eql(null); + }); + it('should prefer element', () => { + expect(getAdUnitElement({ + element: 'explicit', + code: 'ignored', + adUnitCode: 'ignored' + })).to.eql('explicit'); + }); + it('should fallback to code as id', () => { + expect(getAdUnitElement({ + code: 'au' + })).to.eql({ + id: 'au' + }); + }); + it('should fallback to adUnitCode as id', () => { + expect(getAdUnitElement({ + adUnitCode: 'au' + })).to.eql({ + id: 'au' + }) + }) + }); +});