• 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

96.8
/modules/ooloAnalyticsAdapter.js
1
import { _each, deepClone, pick, deepSetValue, logError, logInfo } from '../src/utils.js';
1✔
2
import { getOrigin } from '../libraries/getOrigin/index.js';
3
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'
4
import adapterManager from '../src/adapterManager.js'
5
import { EVENTS } from '../src/constants.js'
6
import { ajax } from '../src/ajax.js'
7
import { config } from '../src/config.js'
8

9
const baseUrl = 'https://pbdata.oolo.io/'
1✔
10
const ENDPOINTS = {
1✔
11
  CONFIG: 'https://config-pbdata.oolo.io',
12
  PAGE_DATA: baseUrl + 'page',
13
  AUCTION: baseUrl + 'auctionData',
14
  BID_WON: baseUrl + 'bidWonData',
15
  AD_RENDER_FAILED: baseUrl + 'adRenderFailedData',
16
  RAW: baseUrl + 'raw',
17
  HBCONFIG: baseUrl + 'hbconfig',
18
}
19

20
const pbModuleVersion = '1.0.0'
1✔
21
const prebidVersion = '$prebid.version$'
1✔
22
const analyticsType = 'endpoint'
1✔
23
const ADAPTER_CODE = 'oolo'
1✔
24
const AUCTION_END_SEND_TIMEOUT = 1500
1✔
25
// TODO: consider using the Prebid-generated page view ID instead of generating a custom one
26
export const PAGEVIEW_ID = +generatePageViewId()
1✔
27

28
const {
29
  AUCTION_INIT,
30
  AUCTION_END,
31
  BID_REQUESTED,
32
  BID_RESPONSE,
33
  NO_BID,
34
  BID_WON,
35
  BID_TIMEOUT,
36
  AD_RENDER_FAILED
37
} = EVENTS
1✔
38

39
const SERVER_EVENTS = {
1✔
40
  AUCTION: 'auction',
41
  WON: 'bidWon',
42
  AD_RENDER_FAILED: 'adRenderFailed'
43
}
44

45
const SERVER_BID_STATUS = {
1✔
46
  NO_BID: 'noBid',
47
  BID_REQUESTED: 'bidRequested',
48
  BID_RECEIVED: 'bidReceived',
49
  BID_TIMEDOUT: 'bidTimedOut',
50
  BID_WON: 'bidWon'
51
}
52

53
let auctions = {}
1✔
54
let initOptions = {}
1✔
55
const eventsQueue = []
1✔
56

57
const onAuctionInit = (args) => {
1✔
58
  const { auctionId, adUnits, timestamp } = args
13✔
59

60
  const auction = auctions[auctionId] = {
13✔
61
    ...args,
62
    adUnits: {},
63
    auctionStart: timestamp,
64
    _sentToServer: false
65
  }
66

67
  handleCustomFields(auction, AUCTION_INIT, args)
13✔
68

69
  _each(adUnits, adUnit => {
13✔
70
    auction.adUnits[adUnit.code] = {
26✔
71
      ...adUnit,
72
      auctionId,
73
      adunid: adUnit.code,
74
      bids: {},
75
    }
76
  })
77
}
78

79
const onBidRequested = (args) => {
1✔
80
  const { auctionId, bids, start, timeout } = args
11✔
81
  const _start = start || Date.now()
11!
82
  const auction = auctions[auctionId]
11✔
83
  const auctionAdUnits = auction.adUnits
11✔
84

85
  bids.forEach(bid => {
11✔
86
    const { adUnitCode } = bid
33✔
87
    const bidId = parseBidId(bid)
33✔
88

89
    auctionAdUnits[adUnitCode].bids[bidId] = {
33✔
90
      ...bid,
91
      timeout,
92
      start: _start,
93
      rs: _start - auction.auctionStart,
94
      bidStatus: SERVER_BID_STATUS.BID_REQUESTED,
95
    }
96
  })
97
}
98

99
const onBidResponse = (args) => {
1✔
100
  const { auctionId, adUnitCode } = args
10✔
101
  const auction = auctions[auctionId]
10✔
102
  const bidId = parseBidId(args)
10✔
103
  const bid = auction.adUnits[adUnitCode].bids[bidId]
10✔
104

105
  Object.assign(bid, args, {
10✔
106
    bidStatus: SERVER_BID_STATUS.BID_RECEIVED,
107
    end: args.responseTimestamp,
108
    re: args.responseTimestamp - auction.auctionStart
109
  })
110
}
111

112
const onNoBid = (args) => {
1✔
113
  const { auctionId, adUnitCode } = args
10✔
114
  const bidId = parseBidId(args)
10✔
115
  const end = Date.now()
10✔
116
  const auction = auctions[auctionId]
10✔
117
  const bid = auction.adUnits[adUnitCode].bids[bidId]
10✔
118

119
  Object.assign(bid, args, {
10✔
120
    bidStatus: SERVER_BID_STATUS.NO_BID,
121
    end,
122
    re: end - auction.auctionStart
123
  })
124
}
125

126
const onBidWon = (args) => {
1✔
127
  const { auctionId, adUnitCode } = args
5✔
128
  const bidId = parseBidId(args)
5✔
129
  const bid = auctions[auctionId].adUnits[adUnitCode].bids[bidId]
5✔
130

131
  Object.assign(bid, args, {
5✔
132
    bidStatus: SERVER_BID_STATUS.BID_WON,
133
    isW: true,
134
    isH: true
135
  })
136

137
  if (auctions[auctionId]._sentToServer) {
5✔
138
    const payload = {
1✔
139
      auctionId,
140
      adunid: adUnitCode,
141
      bid: mapBid(bid, BID_WON)
142
    }
143

144
    sendEvent(SERVER_EVENTS.WON, payload)
1✔
145
  }
146
}
147

148
const onBidTimeout = (args) => {
1✔
149
  _each(args, bid => {
8✔
150
    const { auctionId, adUnitCode } = bid
8✔
151
    const bidId = parseBidId(bid)
8✔
152
    const bidCache = auctions[auctionId].adUnits[adUnitCode].bids[bidId]
8✔
153

154
    Object.assign(bidCache, bid, {
8✔
155
      bidStatus: SERVER_BID_STATUS.BID_TIMEDOUT,
156
    })
157
  })
158
}
159

160
const onAuctionEnd = (args) => {
1✔
161
  const { auctionId, adUnits, ...restAuctionEnd } = args
10✔
162

163
  Object.assign(auctions[auctionId], restAuctionEnd, {
10✔
164
    auctionEnd: args.auctionEnd || Date.now()
20✔
165
  })
166

167
  // wait for bidWon before sending to server
168
  setTimeout(() => {
10✔
169
    auctions[auctionId]._sentToServer = true
9✔
170
    const finalAuctionData = buildAuctionData(auctions[auctionId])
9✔
171

172
    sendEvent(SERVER_EVENTS.AUCTION, finalAuctionData)
9✔
173
  }, initOptions.serverConfig.BID_WON_TIMEOUT || AUCTION_END_SEND_TIMEOUT)
19✔
174
}
175

176
const onAdRenderFailed = (args) => {
1✔
177
  const data = deepClone(args)
1✔
178
  data.timestamp = Date.now()
1✔
179

180
  if (data.bid) {
1!
UNCOV
181
    data.bid = mapBid(data.bid, AD_RENDER_FAILED)
×
182
  }
183

184
  sendEvent(SERVER_EVENTS.AD_RENDER_FAILED, data)
1✔
185
}
186

187
var ooloAdapter = Object.assign(
1✔
188
  adapter({ analyticsType }), {
189
    track({ eventType, args }) {
68✔
190
      // wait for server configuration before processing the events
191
      if (typeof initOptions.serverConfig !== 'undefined' && eventsQueue.length === 0) {
68✔
192
        handleEvent(eventType, args)
59✔
193
      } else {
194
        eventsQueue.push({ eventType, args })
9✔
195
      }
196
    }
197
  }
198
)
199

200
function handleEvent(eventType, args) {
201
  try {
68✔
202
    const { sendRaw } = initOptions.serverConfig.events[eventType]
68✔
203
    if (sendRaw) {
12✔
204
      sendEvent(eventType, args, true)
5✔
205
    }
206
  } catch (e) { }
207

208
  switch (eventType) {
68✔
209
    case AUCTION_INIT:
210
      onAuctionInit(args)
13✔
211
      break
13✔
212
    case BID_REQUESTED:
213
      onBidRequested(args)
11✔
214
      break
11✔
215
    case NO_BID:
216
      onNoBid(args)
10✔
217
      break
10✔
218
    case BID_RESPONSE:
219
      onBidResponse(args)
10✔
220
      break
10✔
221
    case BID_WON:
222
      onBidWon(args)
5✔
223
      break
5✔
224
    case BID_TIMEOUT:
225
      onBidTimeout(args)
8✔
226
      break
8✔
227
    case AUCTION_END:
228
      onAuctionEnd(args)
10✔
229
      break
10✔
230
    case AD_RENDER_FAILED:
231
      onAdRenderFailed(args)
1✔
232
      break
1✔
233
  }
234
}
235

236
function sendEvent(eventType, args, isRaw) {
237
  const data = deepClone(args)
16✔
238

239
  Object.assign(data, buildCommonDataProperties(), {
16✔
240
    eventType
241
  })
242

243
  if (isRaw) {
16✔
244
    let rawEndpoint
245
    try {
5✔
246
      const { endpoint, omitRawFields } = initOptions.serverConfig.events[eventType]
5✔
247
      rawEndpoint = endpoint
5✔
248
      handleCustomRawFields(data, omitRawFields)
5✔
249
    } catch (e) { }
250
    ajaxCall(rawEndpoint || ENDPOINTS.RAW, () => { }, JSON.stringify(data))
5✔
251
  } else {
252
    let endpoint
253
    if (eventType === SERVER_EVENTS.AD_RENDER_FAILED) {
11✔
254
      endpoint = ENDPOINTS.AD_RENDER_FAILED
1✔
255
    } else if (eventType === SERVER_EVENTS.WON) {
10✔
256
      endpoint = ENDPOINTS.BID_WON
1✔
257
    } else {
258
      endpoint = ENDPOINTS.AUCTION
9✔
259
    }
260

261
    ajaxCall(endpoint, () => { }, JSON.stringify(data))
11✔
262
  }
263
}
264

265
function checkEventsQueue() {
266
  while (eventsQueue.length) {
13✔
267
    const event = eventsQueue.shift()
9✔
268
    handleEvent(event.eventType, event.args)
9✔
269
  }
270
}
271

272
function buildAuctionData(auction) {
273
  const auctionData = deepClone(auction)
11✔
274
  const keysToRemove = ['adUnitCodes', 'auctionStatus', 'bidderRequests', 'bidsReceived', 'noBids', 'winningBids', 'timestamp', 'config']
11✔
275

276
  keysToRemove.forEach(key => {
11✔
277
    delete auctionData[key]
88✔
278
  })
279

280
  handleCustomFields(auctionData, AUCTION_END, auction)
11✔
281

282
  // turn bids object into array of objects
283
  Object.keys(auctionData.adUnits).forEach(adUnit => {
11✔
284
    const adUnitObj = auctionData.adUnits[adUnit]
20✔
285
    adUnitObj.bids = Object.keys(adUnitObj.bids).map(key => mapBid(adUnitObj.bids[key]))
29✔
286
    delete adUnitObj['adUnitCode']
20✔
287
    delete adUnitObj['code']
20✔
288
    delete adUnitObj['transactionId']
20✔
289
  })
290

291
  // turn adUnits objects into array of adUnits
292
  auctionData.adUnits = Object.keys(auctionData.adUnits).map(key => auctionData.adUnits[key])
20✔
293

294
  return auctionData
11✔
295
}
296

297
function buildCommonDataProperties() {
298
  return {
30✔
299
    pvid: PAGEVIEW_ID,
300
    pid: initOptions.pid,
301
    pbModuleVersion
302
  }
303
}
304

305
function buildLogMessage(message) {
306
  return `oolo: ${message}`
16✔
307
}
308

309
function parseBidId(bid) {
310
  return bid.bidId || bid.requestId
66✔
311
}
312

313
function mapBid({
314
  bidStatus,
315
  start,
316
  end,
317
  mediaType,
318
  creativeId,
319
  originalCpm,
320
  originalCurrency,
321
  source,
322
  netRevenue,
323
  currency,
324
  width,
325
  height,
326
  timeToRespond,
327
  responseTimestamp,
328
  ...rest
30✔
329
}, eventType) {
30✔
330
  const bidObj = {
30✔
331
    bst: bidStatus,
332
    s: start,
333
    e: responseTimestamp || end,
50✔
334
    mt: mediaType,
335
    crId: creativeId,
336
    oCpm: originalCpm,
337
    oCur: originalCurrency,
338
    src: source,
339
    nrv: netRevenue,
340
    cur: currency,
341
    w: width,
342
    h: height,
343
    ttr: timeToRespond,
344
    ...rest,
345
  }
346

347
  delete bidObj['bidRequestsCount']
30✔
348
  delete bidObj['bidderRequestId']
30✔
349
  delete bidObj['bidderRequestsCount']
30✔
350
  delete bidObj['bidderWinsCount']
30✔
351
  delete bidObj['schain']
30✔
352
  delete bidObj['refererInfo']
30✔
353
  delete bidObj['statusMessage']
30✔
354
  delete bidObj['status']
30✔
355
  delete bidObj['adUrl']
30✔
356
  delete bidObj['ad']
30✔
357
  delete bidObj['usesGenericKeys']
30✔
358
  delete bidObj['requestTimestamp']
30✔
359

360
  try {
30✔
361
    handleCustomFields(bidObj, eventType || BID_RESPONSE, rest)
30✔
362
  } catch (e) { }
363

364
  return bidObj
30✔
365
}
366

367
function handleCustomFields(obj, eventType, args) {
368
  try {
54✔
369
    const { pickFields, omitFields } = initOptions.serverConfig.events[eventType]
54✔
370

371
    if (pickFields && obj && args) {
12✔
372
      Object.assign(obj, pick(args, pickFields))
4✔
373
    }
374

375
    if (omitFields && obj && args) {
12✔
376
      omitFields.forEach(field => {
4✔
377
        deepSetValue(obj, field, undefined)
10✔
378
      })
379
    }
380
  } catch (e) { }
381
}
382

383
function handleCustomRawFields(obj, omitRawFields) {
384
  try {
5✔
385
    if (omitRawFields && obj) {
5✔
386
      omitRawFields.forEach(field => {
1✔
387
        deepSetValue(obj, field, undefined)
1✔
388
      })
389
    }
390
  } catch (e) { }
391
}
392

393
function getServerConfig() {
394
  const defaultConfig = { events: {} }
15✔
395

396
  ajaxCall(
15✔
397
    ENDPOINTS.CONFIG + '?pid=' + initOptions.pid,
398
    {
399
      success: function (data) {
400
        try {
7✔
401
          initOptions.serverConfig = JSON.parse(data) || defaultConfig
7!
402
        } catch (e) {
UNCOV
403
          initOptions.serverConfig = defaultConfig
×
404
        }
405
        checkEventsQueue()
7✔
406
      },
407
      error: function () {
408
        initOptions.serverConfig = defaultConfig
6✔
409
        checkEventsQueue()
6✔
410
      }
411
    },
412
    null
413
  )
414
}
415

416
function sendPage() {
417
  setTimeout(() => {
15✔
418
    const payload = {
14✔
419
      timestamp: Date.now(),
420
      screenWidth: window.screen.width,
421
      screenHeight: window.screen.height,
422
      url: window.location.href,
423
      protocol: window.location.protocol,
424
      origin: getOrigin(),
425
      referrer: getTopWindowReferrer(),
426
      pbVersion: prebidVersion,
427
    }
428

429
    Object.assign(payload, buildCommonDataProperties(), getPagePerformance())
14✔
430
    ajaxCall(ENDPOINTS.PAGE_DATA, () => { }, JSON.stringify(payload))
14✔
431
  }, 0)
432
}
433

434
function sendHbConfigData() {
435
  const conf = {}
15✔
436
  const pbjsConfig = config.getConfig()
15✔
437
  // Check if pbjsConfig.userSync exists and has userIds property
438
  if (pbjsConfig.userSync && pbjsConfig.userSync.userIds) {
15!
439
    // Delete the userIds property
UNCOV
440
    delete pbjsConfig.userSync.userIds;
×
441
  }
442

443
  Object.keys(pbjsConfig).forEach(key => {
15✔
444
    if (key[0] !== '_') {
210✔
445
      conf[key] = pbjsConfig[key]
210✔
446
    }
447
  })
448

449
  ajaxCall(ENDPOINTS.HBCONFIG, () => { }, JSON.stringify(conf))
15✔
450
}
451

452
function getPagePerformance() {
453
  let timing
454

455
  try {
14✔
456
    timing = window.top.performance.timing
14✔
457
  } catch (e) { }
458

459
  if (!timing) {
14!
UNCOV
460
    return
×
461
  }
462

463
  const { navigationStart, domContentLoadedEventEnd, loadEventEnd } = timing
14✔
464
  const domContentLoadTime = domContentLoadedEventEnd - navigationStart
14✔
465
  const pageLoadTime = loadEventEnd - navigationStart
14✔
466

467
  return {
14✔
468
    domContentLoadTime,
469
    pageLoadTime,
470
  }
471
}
472

473
function getTopWindowReferrer() {
474
  try {
14✔
475
    return window.top.document.referrer
14✔
476
  } catch (e) {
UNCOV
477
    return ''
×
478
  }
479
}
480

481
function generatePageViewId(min = 10000, max = 90000) {
2!
482
  var randomNumber = Math.floor((Math.random() * max) + min)
2✔
483
  var currentdate = new Date()
2✔
484
  var currentTime = {
2✔
485
    getDate: currentdate.getDate(),
486
    getMonth: currentdate.getMonth(),
487
    getFullYear: currentdate.getFullYear(),
488
    getHours: currentdate.getHours(),
489
    getMinutes: currentdate.getMinutes(),
490
    getSeconds: currentdate.getSeconds(),
491
    getMilliseconds: currentdate.getMilliseconds()
492
  }
493
  return ((currentTime.getDate <= 9) ? '0' + (currentTime.getDate) : (currentTime.getDate)) + '' +
2!
494
    (currentTime.getMonth + 1 <= 9 ? '0' + (currentTime.getMonth + 1) : (currentTime.getMonth + 1)) + '' +
2!
495
    currentTime.getFullYear % 100 + '' +
496
    (currentTime.getHours <= 9 ? '0' + currentTime.getHours : currentTime.getHours) + '' +
2✔
497
    (currentTime.getMinutes <= 9 ? '0' + currentTime.getMinutes : currentTime.getMinutes) + '' +
2✔
498
    (currentTime.getSeconds <= 9 ? '0' + currentTime.getSeconds : currentTime.getSeconds) + '' +
2!
499
    (currentTime.getMilliseconds % 100 <= 9 ? '0' + (currentTime.getMilliseconds % 100) : (currentTime.getMilliseconds % 100)) + '' +
2✔
500
    (randomNumber)
501
}
502

503
function ajaxCall(endpoint, callback, data, options = {}) {
60!
504
  if (data) {
60✔
505
    options.contentType = 'application/json'
45✔
506
  }
507

508
  return ajax(endpoint, callback, data, options)
60✔
509
}
510

511
ooloAdapter.originEnableAnalytics = ooloAdapter.enableAnalytics
1✔
512
ooloAdapter.enableAnalytics = function (config) {
1✔
513
  ooloAdapter.originEnableAnalytics(config)
16✔
514
  initOptions = config ? config.options : {}
16!
515

516
  if (!initOptions.pid) {
16✔
517
    logError(buildLogMessage('enableAnalytics missing config object with "pid"'))
1✔
518
    return
1✔
519
  }
520

521
  getServerConfig()
15✔
522
  sendHbConfigData()
15✔
523

524
  if (document.readyState === 'complete') {
15!
525
    sendPage()
15✔
526
  } else {
UNCOV
527
    window.addEventListener('load', sendPage)
×
528
  }
529

530
  logInfo(buildLogMessage('enabled analytics adapter'), config)
15✔
531
  ooloAdapter.enableAnalytics = function () {
15✔
UNCOV
532
    logInfo(buildLogMessage('Analytics adapter already enabled..'))
×
533
  }
534
}
535

536
ooloAdapter.originDisableAnalytics = ooloAdapter.disableAnalytics
1✔
537
ooloAdapter.disableAnalytics = function () {
1✔
538
  auctions = {}
19✔
539
  initOptions = {}
19✔
540
  ooloAdapter.originDisableAnalytics()
19✔
541
}
542

543
adapterManager.registerAnalyticsAdapter({
1✔
544
  adapter: ooloAdapter,
545
  code: ADAPTER_CODE
546
})
547

548
// export for testing
549
export {
550
  buildAuctionData,
551
  generatePageViewId
552
}
553

554
export default ooloAdapter
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