• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

prebid / Prebid.js / 19437775255

17 Nov 2025 05:00PM UTC coverage: 96.213% (-0.02%) from 96.231%
19437775255

push

github

web-flow
sevioBidAdapter_bugfix: Send all sizes instead of just maxSize (#14133)

* Send all sizes instead of just maxSize

* Added tests to cover modifs in the sizes that we are sending

53222 of 65234 branches covered (81.59%)

10 of 10 new or added lines in 2 files covered. (100.0%)

304 existing lines in 58 files now uncovered.

202715 of 210693 relevant lines covered (96.21%)

71.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.77
/modules/sizeMappingV2.js
1
/**
1✔
2
 * This module adds support for the new size mapping spec, Advanced Size Mapping. It's documented here. https://github.com/prebid/Prebid.js/issues/4129
3
 * The implementation is an alternative to global sizeConfig. It introduces 'Ad Unit' & 'Bidder' level sizeConfigs and also supports 'labels' for conditional
4
 * rendering. Read full API documentation on Prebid.org, http://prebid.org/dev-docs/modules/sizeMappingV2.html
5
 */
6

7
import {
8
  deepClone,
9
  getWinDimensions,
10
  isArray,
11
  isArrayOfNums,
12
  isValidMediaTypes,
13
  logError,
14
  logInfo,
15
  logWarn
16
} from '../src/utils.js';
17

18
import {getHook} from '../src/hook.js';
19
import {adUnitSetupChecks} from '../src/prebid.js';
20

21
/**
22
 * @typedef {import('../src/adapters/bidderFactory.js').AdUnit} AdUnit
23
 */
24

25
// Allows for stubbing of these functions while writing unit tests.
26
export const internal = {
1✔
27
  checkBidderSizeConfigFormat,
28
  getActiveSizeBucket,
29
  getFilteredMediaTypes,
30
  getAdUnitDetail,
31
  getRelevantMediaTypesForBidder,
32
  isLabelActivated
33
};
34

35
const V2_ADUNITS = new WeakMap();
1✔
36

37
/*
38
  Returns "true" if at least one of the adUnits in the adUnits array is using an Ad Unit and/or Bidder level sizeConfig,
39
  otherwise, returns "false."
40
*/
41
export function isUsingNewSizeMapping(adUnits) {
42
  return !!adUnits.find(adUnit => {
4✔
43
    if (V2_ADUNITS.has(adUnit)) return V2_ADUNITS.get(adUnit);
6!
44
    if (adUnit.mediaTypes) {
6✔
45
      // checks for the presence of sizeConfig property at the adUnit.mediaTypes object
46
      for (const mediaType of Object.keys(adUnit.mediaTypes)) {
6✔
47
        if (adUnit.mediaTypes[mediaType].sizeConfig) {
12✔
48
          V2_ADUNITS.set(adUnit, true);
2✔
49
          return true;
2✔
50
        }
51
      }
52
      for (const bid of adUnit.bids && isArray(adUnit.bids) ? adUnit.bids : []) {
4!
53
        if (bid.sizeConfig) {
6✔
54
          V2_ADUNITS.set(adUnit, true);
1✔
55
          return true;
1✔
56
        }
57
      }
58
      V2_ADUNITS.set(adUnit, false);
3✔
59
      return false;
3✔
60
    }
61
    return false;
×
62
  });
63
}
64

65
/**
66
  This hooked function executes before the function 'checkAdUnitSetup', that is defined in /src/prebid.js. It's necessary to run this funtion before
67
  because it applies a series of checks in order to determine the correctness of the 'sizeConfig' array, which, the original 'checkAdUnitSetup' function
68
  does not recognize.
69
  @param {*} adUnits
70
  @returns {*} validateAdUnits - Unrecognized properties are deleted.
71
 */
72
export function checkAdUnitSetupHook(adUnits) {
73
  const validateSizeConfig = function (mediaType, sizeConfig, adUnitCode) {
33✔
74
    let isValid = true;
85✔
75
    const associatedProperty = {
85✔
76
      banner: 'sizes',
77
      video: 'playerSize',
78
      native: 'active'
79
    }
80
    const propertyName = associatedProperty[mediaType];
85✔
81
    const conditionalLogMessages = {
85✔
82
      banner: 'Removing mediaTypes.banner from ad unit.',
83
      video: 'Removing mediaTypes.video.sizeConfig from ad unit.',
84
      native: 'Removing mediaTypes.native.sizeConfig from ad unit.'
85
    }
86
    if (Array.isArray(sizeConfig)) {
85✔
87
      sizeConfig.forEach((config, index) => {
82✔
88
        const keys = Object.keys(config);
256✔
89
        /*
90
          Check #1 (Applies to 'banner', 'video' and 'native' media types.)
91
          Verify that all config objects include 'minViewPort' and 'sizes' property.
92
          If they do not, return 'false'.
93
        */
94
        if (!(keys.includes('minViewPort') && keys.includes(propertyName))) {
256✔
95
          logError(`Ad unit ${adUnitCode}: Missing required property 'minViewPort' or 'sizes' from 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`);
4✔
96
          isValid = false;
4✔
97
          return;
4✔
98
        }
99
        /*
100
          Check #2 (Applies to 'banner', 'video' and 'native' media types.)
101
          Verify that 'config.minViewPort' property is in [width, height] format.
102
          If not, return false.
103
        */
104
        if (!isArrayOfNums(config.minViewPort, 2)) {
252✔
105
          logError(`Ad unit ${adUnitCode}: Invalid declaration of 'minViewPort' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`);
4✔
106
          isValid = false;
4✔
107
          return;
4✔
108
        }
109
        /*
110
          Check #3 (Applies only to 'banner' and 'video' media types.)
111
          Verify that 'config.sizes' (in case of banner) or 'config.playerSize' (in case of video)
112
          property is in [width, height] format. If not, return 'false'.
113
        */
114
        if (mediaType === 'banner' || mediaType === 'video') {
248✔
115
          let showError = false;
166✔
116
          if (Array.isArray(config[propertyName])) {
166✔
117
            const validatedSizes = adUnitSetupChecks.validateSizes(config[propertyName]);
165✔
118
            if (config[propertyName].length > 0 && validatedSizes.length === 0) {
165✔
119
              isValid = false;
3✔
120
              showError = true;
3✔
121
            }
122
          } else {
123
            // Either 'sizes' or 'playerSize' is not declared as an array, which makes it invalid by default.
124
            isValid = false;
1✔
125
            showError = true;
1✔
126
          }
127
          if (showError) {
166✔
128
            logError(`Ad unit ${adUnitCode}: Invalid declaration of '${propertyName}' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`);
4✔
129
            return;
4✔
130
          }
131
        }
132
        /*
133
          Check #4 (Applies only to 'native' media type)
134
          Verify that 'config.active' is a 'boolean'.
135
          If not, return 'false'.
136
        */
137
        if (FEATURES.NATIVE && mediaType === 'native') {
244✔
138
          if (typeof config[propertyName] !== 'boolean') {
82✔
139
            logError(`Ad unit ${adUnitCode}: Invalid declaration of 'active' in 'mediaTypes.${mediaType}.sizeConfig[${index}]'. ${conditionalLogMessages[mediaType]}`);
1✔
140
            isValid = false;
1✔
141
          }
142
        }
143
      });
144
    } else {
145
      logError(`Ad unit ${adUnitCode}: Invalid declaration of 'sizeConfig' in 'mediaTypes.${mediaType}.sizeConfig'. ${conditionalLogMessages[mediaType]}`);
3✔
146
      isValid = false;
3✔
147
      return isValid;
3✔
148
    }
149

150
    // If all checks have passed, isValid should equal 'true'
151
    return isValid;
82✔
152
  }
153
  const validatedAdUnits = [];
33✔
154
  adUnits.forEach(adUnit => {
33✔
155
    adUnit = adUnitSetupChecks.validateAdUnit(adUnit);
63✔
156
    if (adUnit == null) return;
63✔
157

158
    const mediaTypes = adUnit.mediaTypes;
61✔
159
    let validatedBanner, validatedVideo, validatedNative;
160

161
    if (mediaTypes.banner) {
61✔
162
      if (mediaTypes.banner.sizes) {
59✔
163
        // Ad unit is using 'mediaTypes.banner.sizes' instead of the new property 'sizeConfig'. Apply the old checks!
164
        validatedBanner = adUnitSetupChecks.validateBannerMediaType(adUnit);
30✔
165
      } else if (mediaTypes.banner.sizeConfig) {
29✔
166
        // Ad unit is using the 'sizeConfig' property, 'mediaTypes.banner.sizeConfig'. Apply the new checks!
167
        validatedBanner = deepClone(adUnit);
27✔
168
        const isBannerValid = validateSizeConfig('banner', mediaTypes.banner.sizeConfig, adUnit.code);
27✔
169
        if (!isBannerValid) {
27✔
170
          delete validatedBanner.mediaTypes.banner;
9✔
171
        } else {
172
          /*
173
            Make sure 'sizes' field is always an array of arrays. If not, make it so.
174
            For example, [] becomes [[]], and [360, 400] becomes [[360, 400]]
175
          */
176
          validatedBanner.mediaTypes.banner.sizeConfig.forEach(config => {
18✔
177
            if (!Array.isArray(config.sizes[0])) {
71✔
178
              config.sizes = [config.sizes];
19✔
179
            }
180
          });
181
        }
182
      } else {
183
        // Ad unit is invalid since it's mediaType property does not have either 'sizes' or 'sizeConfig' declared.
184
        logError(`Ad unit ${adUnit.code}: 'mediaTypes.banner' does not contain either 'sizes' or 'sizeConfig' property. Removing 'mediaTypes.banner' from ad unit.`);
2✔
185
        validatedBanner = deepClone(adUnit);
2✔
186
        delete validatedBanner.mediaTypes.banner;
2✔
187
      }
188
    }
189

190
    if (FEATURES.VIDEO && mediaTypes.video) {
61✔
191
      if (mediaTypes.video.playerSize) {
59✔
192
        // Ad unit is using 'mediaTypes.video.playerSize' instead of the new property 'sizeConfig'. Apply the old checks!
193
        validatedVideo = validatedBanner ? adUnitSetupChecks.validateVideoMediaType(validatedBanner) : adUnitSetupChecks.validateVideoMediaType(adUnit);
30✔
194
      } else if (mediaTypes.video.sizeConfig) {
29✔
195
        // Ad unit is using the 'sizeConfig' property, 'mediaTypes.video.sizeConfig'. Apply the new checks!
196
        validatedVideo = validatedBanner || deepClone(adUnit);
29!
197
        const isVideoValid = validateSizeConfig('video', mediaTypes.video.sizeConfig, adUnit.code);
29✔
198
        if (!isVideoValid) {
29✔
199
          delete validatedVideo.mediaTypes.video.sizeConfig;
4✔
200
        } else {
201
          /*
202
            Make sure 'playerSize' field is always an array of arrays. If not, make it so.
203
            For example, [] becomes [[]], and [640, 400] becomes [[640, 400]]
204
          */
205
          validatedVideo.mediaTypes.video.sizeConfig.forEach(config => {
25✔
206
            if (!Array.isArray(config.playerSize[0])) {
74✔
207
              config.playerSize = [config.playerSize];
50✔
208
            }
209
          });
210
        }
211
      }
212
    }
213

214
    if (FEATURES.NATIVE && mediaTypes.native) {
61✔
215
      // Apply the old native checks
216
      validatedNative = validatedVideo ? adUnitSetupChecks.validateNativeMediaType(validatedVideo) : validatedBanner ? adUnitSetupChecks.validateNativeMediaType(validatedBanner) : adUnitSetupChecks.validateNativeMediaType(adUnit);
32✔
217

218
      // Apply the new checks if 'mediaTypes.native.sizeConfig' detected
219
      if (mediaTypes.native.sizeConfig) {
32✔
220
        const isNativeValid = validateSizeConfig('native', mediaTypes.native.sizeConfig, adUnit.code);
29✔
221
        if (!isNativeValid) {
29✔
222
          delete validatedNative.mediaTypes.native.sizeConfig;
3✔
223
        }
224
      }
225
    }
226

227
    const validatedAdUnit = Object.assign({}, validatedBanner, validatedVideo, validatedNative);
61✔
228
    validatedAdUnits.push(validatedAdUnit);
61✔
229
  });
230
  return validatedAdUnits;
33✔
231
}
232

233
getHook('checkAdUnitSetup').before(function (fn, adUnits) {
1✔
UNCOV
234
  const usingNewSizeMapping = isUsingNewSizeMapping(adUnits);
×
UNCOV
235
  if (usingNewSizeMapping) {
×
236
    // if adUnits are found using the sizeMappingV2 spec, we run additional checks on them for checking the validity of sizeConfig object
237
    // in addition to running the base checks on the mediaType object and return the adUnit without calling the base function.
238
    adUnits = checkAdUnitSetupHook(adUnits);
×
239
    return fn.bail(adUnits);
×
240
  } else {
241
    // if presence of sizeMappingV2 spec is not detected on adUnits, we default back to the original checks defined in the base function.
UNCOV
242
    return fn.call(this, adUnits);
×
243
  }
244
});
245

246
// checks if the sizeConfig object declared at the Bidder level is in the right format or not.
247
export function checkBidderSizeConfigFormat(sizeConfig) {
248
  let didCheckPass = true;
21✔
249
  if (Array.isArray(sizeConfig) && sizeConfig.length > 0) {
21✔
250
    sizeConfig.forEach(config => {
19✔
251
      const keys = Object.keys(config);
35✔
252
      if ((keys.includes('minViewPort') &&
35✔
253
        keys.includes('relevantMediaTypes')) &&
254
        isArrayOfNums(config.minViewPort, 2) &&
255
        Array.isArray(config.relevantMediaTypes) &&
256
        config.relevantMediaTypes.length > 0 &&
257
        (config.relevantMediaTypes.length > 1 ? (config.relevantMediaTypes.every(mt => (['banner', 'video', 'native'].includes(mt))))
15✔
258
          : (['none', 'banner', 'video', 'native'].indexOf(config.relevantMediaTypes[0]) > -1))) {
259
        didCheckPass = didCheckPass && true;
23✔
260
      } else {
261
        didCheckPass = false;
12✔
262
      }
263
    });
264
  } else {
265
    didCheckPass = false;
2✔
266
  }
267
  return didCheckPass;
21✔
268
}
269

270
getHook('setupAdUnitMediaTypes').before(function (fn, adUnits, labels) {
1✔
UNCOV
271
  if (isUsingNewSizeMapping(adUnits)) {
×
272
    return fn.bail(setupAdUnitMediaTypes(adUnits, labels));
×
273
  } else {
UNCOV
274
    return fn.call(this, adUnits, labels);
×
275
  }
276
});
277

278
/**
279
 * Given an Ad Unit or a Bid as an input, returns a boolean telling if the Ad Unit/ Bid is active based on label checks
280
 * @param {*} bidOrAdUnit - Either the Ad Unit object or the Bid object
281
 * @param {Array<string>} activeLabels - List of active labels passed as an argument to pbjs.requestBids function
282
 * @param {string} adUnitCode - Unique string identifier for an Ad Unit.
283
 * @param {number} adUnitInstance - Instance count of an 'Identical' ad unit.
284
 * @returns {boolean} Represents if the Ad Unit or the Bid is active or not
285
 */
286
export function isLabelActivated(bidOrAdUnit, activeLabels, adUnitCode, adUnitInstance) {
287
  let labelOperator;
288
  const labelsFound = Object.keys(bidOrAdUnit).filter(prop => prop === 'labelAny' || prop === 'labelAll');
88✔
289
  if (labelsFound && labelsFound.length > 1) {
28✔
290
    logWarn(`Size Mapping V2:: ${(bidOrAdUnit.code)
4✔
291
      ? (`Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has multiple label operators. Using the first declared operator: ${labelsFound[0]}`)
292
      : (`Ad Unit: ${adUnitCode}(${adUnitInstance}), Bidder: ${bidOrAdUnit.bidder} => Bidder has multiple label operators. Using the first declared operator: ${labelsFound[0]}`)}`);
293
  }
294
  labelOperator = labelsFound[0];
28✔
295

296
  if (labelOperator && !activeLabels) {
28✔
297
    logWarn(`Size Mapping V2:: ${(bidOrAdUnit.code)
2✔
298
      ? (`Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Found '${labelOperator}' on ad unit, but 'labels' is not set. Did you pass 'labels' to pbjs.requestBids() ?`)
299
      : (`Ad Unit: ${adUnitCode}(${adUnitInstance}), Bidder: ${bidOrAdUnit.bidder} => Found '${labelOperator}' on bidder, but 'labels' is not set. Did you pass 'labels' to pbjs.requestBids() ?`)}`);
300
    return true;
2✔
301
  }
302

303
  if (labelOperator === 'labelAll' && Array.isArray(bidOrAdUnit[labelOperator])) {
26✔
304
    if (bidOrAdUnit.labelAll.length === 0) {
4✔
305
      logWarn(`Size Mapping V2:: Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has declared property 'labelAll' with an empty array.`);
1✔
306
      return true;
1✔
307
    }
308
    return bidOrAdUnit.labelAll.every(label => activeLabels.includes(label));
12✔
309
  } else if (labelOperator === 'labelAny' && Array.isArray(bidOrAdUnit[labelOperator])) {
22✔
310
    if (bidOrAdUnit.labelAny.length === 0) {
7✔
311
      logWarn(`Size Mapping V2:: Ad Unit: ${bidOrAdUnit.code}(${adUnitInstance}) => Ad unit has declared property 'labelAny' with an empty array.`);
1✔
312
      return true;
1✔
313
    }
314
    return bidOrAdUnit.labelAny.some(label => activeLabels.includes(label));
6✔
315
  }
316
  return true;
15✔
317
}
318

319
/**
320
 * Processes the MediaTypes object and calculates the active size buckets for each Media Type. Uses `window.innerWidth` and `window.innerHeight`
321
 * to calculate the width and height of the active Viewport.
322
 * @param {*} mediaTypes Contains information about supported media types for an Ad Unit and size information for each of those types
323
 * @returns {*} Filtered mediaTypes object with relevant media types filtered by size buckets based on activeViewPort size
324
 */
325
export function getFilteredMediaTypes(mediaTypes) {
326
  let
327
    activeViewportWidth,
328
    activeViewportHeight,
329
    transformedMediaTypes;
330

331
  transformedMediaTypes = deepClone(mediaTypes);
1✔
332

333
  const activeSizeBucket = {
1✔
334
    banner: undefined,
335
    video: undefined,
336
    native: undefined
337
  }
338

339
  activeViewportWidth = getWinDimensions().innerWidth;
1✔
340
  activeViewportHeight = getWinDimensions().innerHeight;
1✔
341

342
  const activeViewport = [activeViewportWidth, activeViewportHeight];
1✔
343
  Object.keys(mediaTypes).forEach(mediaType => {
1✔
344
    const sizeConfig = mediaTypes[mediaType].sizeConfig;
3✔
345
    if (sizeConfig) {
3✔
346
      activeSizeBucket[mediaType] = getActiveSizeBucket(sizeConfig, activeViewport);
3✔
347
      const filteredSizeConfig = sizeConfig.filter(config => config.minViewPort === activeSizeBucket[mediaType] && isSizeConfigActivated(mediaType, config));
10✔
348
      transformedMediaTypes[mediaType] = Object.assign({ filteredSizeConfig }, mediaTypes[mediaType]);
3✔
349

350
      // transform mediaTypes object
351
      const config = {
3✔
352
        banner: 'sizes',
353
        video: 'playerSize'
354
      };
355

356
      if (transformedMediaTypes[mediaType].filteredSizeConfig.length > 0) {
3✔
357
        // map sizes or playerSize property in filteredSizeConfig object to transformedMediaTypes.banner.sizes if mediaType is banner
358
        // or transformedMediaTypes.video.playerSize if the mediaType in video.
359
        // doesn't apply to native mediaType since native doesn't have any property defining 'sizes' or 'playerSize'.
360
        if (mediaType !== 'native') {
1✔
361
          transformedMediaTypes[mediaType][config[mediaType]] = transformedMediaTypes[mediaType].filteredSizeConfig[0][config[mediaType]];
1✔
362
        }
363
      } else {
364
        delete transformedMediaTypes[mediaType];
2✔
365
      }
366
    }
367
  })
368

369
  // filter out 'undefined' values from activeSizeBucket object and attach sizes/playerSize information against the active size bucket.
370
  const sizeBucketToSizeMap = Object
1✔
371
    .keys(activeSizeBucket)
372
    .filter(mediaType => activeSizeBucket[mediaType] !== undefined)
3✔
373
    .reduce((sizeBucketToSizeMap, mediaType) => {
374
      sizeBucketToSizeMap[mediaType] = {
3✔
375
        activeSizeBucket: activeSizeBucket[mediaType],
376
        activeSizeDimensions: (mediaType === 'banner') ? (
3✔
377
          // banner mediaType gets deleted incase no sizes are specified for a given size bucket, that's why this check is necessary
378
          (transformedMediaTypes.banner) ? (transformedMediaTypes.banner.sizes) : ([])
1!
379
        ) : ((mediaType === 'video') ? (
2✔
380
          // video mediaType gets deleted incase no playerSize is specified for a given size bucket, that's why this check is necessary
381
          (transformedMediaTypes.video) ? (transformedMediaTypes.video.playerSize) : ([])
1!
382
        ) : ('NA'))
383
      };
384
      return sizeBucketToSizeMap;
3✔
385
    }, {});
386

387
  return { sizeBucketToSizeMap, activeViewport, transformedMediaTypes };
1✔
388
}
389

390
/**
391
 * Evaluates the given sizeConfig object and checks for various properties to determine if the sizeConfig is active or not. For example,
392
 * let's suppose the sizeConfig is for a Banner media type. Then, if the sizes property is found empty, it returns false, else returns true.
393
 * In case of a Video media type, it checks the playerSize property. If found empty, returns false, else returns true.
394
 * In case of a Native media type, it checks the active property. If found false, returns false, if found true, returns true.
395
 * @param {string} mediaType It can be 'banner', 'native' or 'video'
396
 * @param {*} sizeConfig Represents the sizeConfig object which is active based on the current viewport size
397
 * @returns {boolean} Represents if the size config is active or not
398
 */
399
export function isSizeConfigActivated(mediaType, sizeConfig) {
400
  switch (mediaType) {
10✔
401
    case 'banner':
402
      // we need this check, sizeConfig.sizes[0].length > 0, in place because a sizeBucket can have sizes: [],
403
      // gets converted to sizes: [[]] in the checkAdUnitSetupHook function
404
      return sizeConfig.sizes && sizeConfig.sizes.length > 0 && sizeConfig.sizes[0].length > 0;
3✔
405
    case 'video':
406
      // for why we need the last check, read the above comment
407
      return sizeConfig.playerSize && sizeConfig.playerSize.length > 0 && sizeConfig.playerSize[0].length > 0;
3✔
408
    case 'native':
409
      return sizeConfig.active;
3✔
410
    default:
411
      return false;
1✔
412
  }
413
}
414

415
/**
416
 * Returns the active size bucket for a given media type
417
 * @param {*[]} sizeConfig SizeConfig defines the characteristics of an Ad Unit categorised into multiple size buckets per media type
418
 * @param {Array} activeViewport Viewport size of the browser in the form [w, h] (w -> width, h -> height)
419
 * Calculated at the time of making call to pbjs.requestBids function
420
 * @returns {Array} The active size bucket matching the activeViewPort, for example: [750, 0]
421
 */
422
export function getActiveSizeBucket(sizeConfig, activeViewport) {
423
  let activeSizeBucket = [];
11✔
424
  sizeConfig
11✔
425
    .sort((a, b) => a.minViewPort[0] - b.minViewPort[0])
16✔
426
    .forEach(config => {
427
      if (activeViewport[0] >= config.minViewPort[0]) {
27✔
428
        if (activeViewport[1] >= config.minViewPort[1]) {
25✔
429
          activeSizeBucket = config.minViewPort;
24✔
430
        } else {
431
          activeSizeBucket = [];
1✔
432
        }
433
      }
434
    })
435
  return activeSizeBucket;
11✔
436
}
437

438
export function getRelevantMediaTypesForBidder(sizeConfig, activeViewport) {
439
  const mediaTypes = new Set();
9✔
440
  if (internal.checkBidderSizeConfigFormat(sizeConfig)) {
9✔
441
    const activeSizeBucket = internal.getActiveSizeBucket(sizeConfig, activeViewport);
6✔
442
    sizeConfig.filter(config => config.minViewPort === activeSizeBucket)[0]['relevantMediaTypes'].forEach((mt) => mediaTypes.add(mt));
11✔
443
  }
444
  return mediaTypes;
9✔
445
}
446

447
export function getAdUnitDetail(adUnit, labels, adUnitInstance) {
448
  const isLabelActivated = internal.isLabelActivated(adUnit, labels, adUnit.code, adUnitInstance);
2✔
449
  const { sizeBucketToSizeMap, activeViewport, transformedMediaTypes } = isLabelActivated && internal.getFilteredMediaTypes(adUnit.mediaTypes);
2✔
450
  isLabelActivated && logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${adUnitInstance}) => Active size buckets after filtration: `, sizeBucketToSizeMap);
2✔
451
  return {
2✔
452
    activeViewport,
453
    transformedMediaTypes,
454
    isLabelActivated,
455
  };
456
}
457

458
export function setupAdUnitMediaTypes(adUnits, labels) {
459
  const duplCounter = {};
9✔
460
  return adUnits.reduce((result, adUnit) => {
9✔
461
    const instance = (() => {
9✔
462
      if (!duplCounter.hasOwnProperty(adUnit.code)) {
9✔
463
        duplCounter[adUnit.code] = 1;
9✔
464
      }
465
      return duplCounter[adUnit.code]++;
9✔
466
    })();
467
    if (adUnit.mediaTypes && isValidMediaTypes(adUnit.mediaTypes)) {
9✔
468
      const { activeViewport, transformedMediaTypes, isLabelActivated } = internal.getAdUnitDetail(adUnit, labels, instance);
8✔
469
      if (isLabelActivated) {
8✔
470
        if (Object.keys(transformedMediaTypes).length === 0) {
7✔
471
          logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}) => Ad unit disabled since there are no active media types after sizeConfig filtration.`);
1✔
472
        } else {
473
          adUnit.mediaTypes = transformedMediaTypes;
6✔
474
          adUnit.bids = adUnit.bids.reduce((bids, bid) => {
6✔
475
            if (internal.isLabelActivated(bid, labels, adUnit.code, instance)) {
12✔
476
              if (bid.sizeConfig) {
10✔
477
                const relevantMediaTypes = internal.getRelevantMediaTypesForBidder(bid.sizeConfig, activeViewport);
5✔
478
                if (relevantMediaTypes.size === 0) {
5✔
479
                  logError(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => 'sizeConfig' is not configured properly. This bidder won't be eligible for sizeConfig checks and will remain active.`);
1✔
480
                  bids.push(bid);
1✔
481
                } else if (!relevantMediaTypes.has('none')) {
4✔
482
                  let modified = false;
3✔
483
                  const bidderMediaTypes = Object.fromEntries(
3✔
484
                    Object.entries(transformedMediaTypes)
485
                      .filter(([key, val]) => {
4✔
486
                        if (!relevantMediaTypes.has(key)) {
4✔
487
                          modified = true;
2✔
488
                          return false;
2✔
489
                        }
490
                        return true;
2✔
491
                      })
492
                  );
493
                  if (Object.keys(bidderMediaTypes).length > 0) {
3✔
494
                    if (modified) {
2✔
495
                      bid.mediaTypes = bidderMediaTypes;
1✔
496
                    }
497
                    bids.push(bid);
2✔
498
                  } else {
499
                    logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => 'relevantMediaTypes' does not match with any of the active mediaTypes at the Ad Unit level. This bidder is disabled.`);
1✔
500
                  }
501
                } else {
502
                  logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => 'relevantMediaTypes' is set to 'none' in sizeConfig for current viewport size. This bidder is disabled.`);
1✔
503
                }
504
              } else {
505
                bids.push(bid);
5✔
506
              }
507
            } else {
508
              logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}), Bidder: ${bid.bidder} => Label check for this bidder has failed. This bidder is disabled.`);
2✔
509
            }
510
            return bids;
12✔
511
          }, []);
512
          result.push(adUnit);
6✔
513
        }
514
      } else {
515
        logInfo(`Size Mapping V2:: Ad Unit: ${adUnit.code}(${instance}) => Ad unit is disabled due to failing label check.`);
1✔
516
      }
517
    } else {
518
      logWarn(`Size Mapping V2:: Ad Unit: ${adUnit.code} => Ad unit has declared invalid 'mediaTypes' or has not declared a 'mediaTypes' property`);
1✔
519
    }
520
    return result;
9✔
521
  }, [])
522
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc