@bidkernel/analytics 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,3 +1,289 @@
1
+ // ../logger/src/index.ts
2
+ var LogLevel = {
3
+ DEBUG: "DEBUG",
4
+ INFO: "INFO",
5
+ WARN: "WARN",
6
+ ERROR: "ERROR"
7
+ };
8
+ var LOG_LEVEL_MAP = {
9
+ [LogLevel.DEBUG]: 10,
10
+ [LogLevel.INFO]: 20,
11
+ [LogLevel.WARN]: 30,
12
+ [LogLevel.ERROR]: 40
13
+ };
14
+ var COLORS = {
15
+ badge: "color: #2dd4bf; font-weight: bold",
16
+ // teal - [ads] badge
17
+ badgeWarn: "background: #f59e0b; color: #fff; padding: 2px 4px; border-radius: 3px; font-weight: bold",
18
+ // amber - [ads] badge (warning)
19
+ badgeError: "background: #ef4444; color: #fff; padding: 2px 4px; border-radius: 3px; font-weight: bold",
20
+ // red - [ads] badge (error)
21
+ dim: "color: #6b7280",
22
+ // gray - timestamp
23
+ event: "color: #38bdf8; font-weight: bold",
24
+ // blue - event name
25
+ eventWarn: "color: #f59e0b; font-weight: bold",
26
+ // amber - event name (warning)
27
+ eventError: "color: #ef4444; font-weight: bold",
28
+ // red - event name (error)
29
+ reset: "color: inherit"
30
+ // back to default
31
+ };
32
+ var logCounter = 0;
33
+ var localGlobalListeners = /* @__PURE__ */ new Set();
34
+ function getGlobalListeners() {
35
+ if (typeof window !== "undefined") {
36
+ const win = window;
37
+ if (!win.__bidkernelLogListeners) {
38
+ win.__bidkernelLogListeners = /* @__PURE__ */ new Set();
39
+ }
40
+ return win.__bidkernelLogListeners;
41
+ }
42
+ return localGlobalListeners;
43
+ }
44
+ function formatTime(ms) {
45
+ if (ms < 0 || !Number.isFinite(ms)) ms = 0;
46
+ if (ms < 1e3) return `${ms.toFixed(2)}ms`;
47
+ const s = ms / 1e3;
48
+ if (s < 60) return `${s.toFixed(2)}s`;
49
+ const m = Math.floor(s / 60);
50
+ if (m < 60) return `${m}m ${(s % 60).toFixed(2)}s`;
51
+ const h = Math.floor(m / 60);
52
+ return `${h}h ${m % 60}m ${(s % 60).toFixed(2)}s`;
53
+ }
54
+ function normalizeLogLevel(level) {
55
+ if (typeof level === "string") {
56
+ const upper = level.toUpperCase();
57
+ if (upper === "DEBUG" || upper === "INFO" || upper === "WARN" || upper === "ERROR") {
58
+ return upper;
59
+ }
60
+ }
61
+ return LogLevel.INFO;
62
+ }
63
+ var Logger = class _Logger {
64
+ _prefix;
65
+ _level;
66
+ _loadedAt;
67
+ _now;
68
+ _console;
69
+ _customFormatTime;
70
+ _listeners = /* @__PURE__ */ new Set();
71
+ constructor(options = {}) {
72
+ this._prefix = options.prefix ?? "[bidkernel]";
73
+ this._level = normalizeLogLevel(options.logLevel ?? LogLevel.INFO);
74
+ this._now = options.now;
75
+ this._console = options.console;
76
+ this._customFormatTime = options.formatTime;
77
+ if (options.onLog) {
78
+ this._listeners.add(options.onLog);
79
+ }
80
+ this._loadedAt = options.loadedAt ?? (this._now ? this._now() : typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now());
81
+ }
82
+ get prefix() {
83
+ return this._prefix;
84
+ }
85
+ set prefix(val) {
86
+ this._prefix = val;
87
+ }
88
+ get logLevel() {
89
+ return this._level;
90
+ }
91
+ set logLevel(val) {
92
+ this._level = normalizeLogLevel(val);
93
+ }
94
+ getLevel() {
95
+ return this._level;
96
+ }
97
+ setLevel(level) {
98
+ this._level = normalizeLogLevel(level);
99
+ }
100
+ getPrefix() {
101
+ return this._prefix;
102
+ }
103
+ setPrefix(prefix) {
104
+ this._prefix = prefix;
105
+ }
106
+ resetTiming(loadedAt) {
107
+ this._loadedAt = loadedAt ?? (this._now ? this._now() : typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now());
108
+ }
109
+ getLoadedAt() {
110
+ return this._loadedAt;
111
+ }
112
+ addListener(listener) {
113
+ this._listeners.add(listener);
114
+ return () => {
115
+ this._listeners.delete(listener);
116
+ };
117
+ }
118
+ removeListener(listener) {
119
+ this._listeners.delete(listener);
120
+ }
121
+ isEnabled(level) {
122
+ const target = normalizeLogLevel(level);
123
+ return (LOG_LEVEL_MAP[target] ?? 20) >= (LOG_LEVEL_MAP[this._level] ?? 20);
124
+ }
125
+ formatTime(ms) {
126
+ if (this._customFormatTime) {
127
+ return this._customFormatTime(ms);
128
+ }
129
+ return formatTime(ms);
130
+ }
131
+ _getConsole() {
132
+ if (this._console) return this._console;
133
+ if (typeof console !== "undefined") return console;
134
+ return void 0;
135
+ }
136
+ _getElapsed() {
137
+ const current = this._now ? this._now() : typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
138
+ return Math.max(0, current - this._loadedAt);
139
+ }
140
+ _dispatchRecord(record) {
141
+ for (const l of this._listeners) {
142
+ try {
143
+ l(record);
144
+ } catch {
145
+ }
146
+ }
147
+ const globalListeners = getGlobalListeners();
148
+ for (const gl of globalListeners) {
149
+ if (!this._listeners.has(gl)) {
150
+ try {
151
+ gl(record);
152
+ } catch {
153
+ }
154
+ }
155
+ }
156
+ if (typeof window !== "undefined" && typeof window.dispatchEvent === "function") {
157
+ try {
158
+ window.dispatchEvent(new CustomEvent("__bidkernel_log__", { detail: record }));
159
+ } catch {
160
+ }
161
+ }
162
+ }
163
+ log(level, nameOrMsg, ...args) {
164
+ const normLevel = normalizeLogLevel(level);
165
+ if (!this.isEnabled(normLevel)) {
166
+ return;
167
+ }
168
+ const elapsed = this._getElapsed();
169
+ const formattedTimeStr = this.formatTime(elapsed);
170
+ const nowEpoch = Date.now();
171
+ const recordId = `bk_log_${nowEpoch}_${++logCounter}`;
172
+ const record = {
173
+ id: recordId,
174
+ timestamp: nowEpoch,
175
+ elapsedMs: elapsed,
176
+ level: normLevel,
177
+ prefix: this._prefix,
178
+ message: nameOrMsg,
179
+ args,
180
+ data: args.length === 1 ? args[0] : args.length > 1 ? args : void 0
181
+ };
182
+ this._dispatchRecord(record);
183
+ const c = this._getConsole();
184
+ if (!c) return;
185
+ let badgeStyle = COLORS.badge;
186
+ let eventStyle = COLORS.event;
187
+ if (normLevel === LogLevel.WARN) {
188
+ badgeStyle = COLORS.badgeWarn;
189
+ eventStyle = COLORS.eventWarn;
190
+ } else if (normLevel === LogLevel.ERROR) {
191
+ badgeStyle = COLORS.badgeError;
192
+ eventStyle = COLORS.eventError;
193
+ }
194
+ const fmt = `%c${this._prefix}%c ${formattedTimeStr} %c${nameOrMsg}%c`;
195
+ const styles = [badgeStyle, COLORS.dim, eventStyle, COLORS.reset];
196
+ const callArgs = [fmt, ...styles];
197
+ if (args.length > 0) {
198
+ callArgs.push(...args);
199
+ }
200
+ switch (normLevel) {
201
+ case LogLevel.DEBUG:
202
+ if (typeof c.log === "function") {
203
+ c.log(...callArgs);
204
+ } else if (typeof c.debug === "function") {
205
+ c.debug(...callArgs);
206
+ }
207
+ break;
208
+ case LogLevel.INFO:
209
+ if (typeof c.info === "function") {
210
+ c.info(...callArgs);
211
+ } else if (typeof c.log === "function") {
212
+ c.log(...callArgs);
213
+ }
214
+ break;
215
+ case LogLevel.WARN:
216
+ if (typeof c.warn === "function") {
217
+ c.warn(...callArgs);
218
+ } else if (typeof c.log === "function") {
219
+ c.log(...callArgs);
220
+ }
221
+ break;
222
+ case LogLevel.ERROR:
223
+ if (typeof c.error === "function") {
224
+ c.error(...callArgs);
225
+ } else if (typeof c.log === "function") {
226
+ c.log(...callArgs);
227
+ }
228
+ break;
229
+ default:
230
+ if (typeof c.log === "function") {
231
+ c.log(...callArgs);
232
+ }
233
+ break;
234
+ }
235
+ }
236
+ debug(nameOrMsg, ...args) {
237
+ this.log(LogLevel.DEBUG, nameOrMsg, ...args);
238
+ }
239
+ info(nameOrMsg, ...args) {
240
+ this.log(LogLevel.INFO, nameOrMsg, ...args);
241
+ }
242
+ warn(nameOrMsg, ...args) {
243
+ this.log(LogLevel.WARN, nameOrMsg, ...args);
244
+ }
245
+ error(nameOrMsg, ...args) {
246
+ this.log(LogLevel.ERROR, nameOrMsg, ...args);
247
+ }
248
+ logEvent(event) {
249
+ if (!event) return;
250
+ if (event.data !== void 0) {
251
+ this.log(event.level, event.eventName, event.data);
252
+ } else {
253
+ this.log(event.level, event.eventName);
254
+ }
255
+ }
256
+ child(subNamespace, options = {}) {
257
+ let childPrefix = this._prefix;
258
+ if (subNamespace) {
259
+ const formattedSub = subNamespace.startsWith("[") && subNamespace.endsWith("]") ? subNamespace : `[${subNamespace}]`;
260
+ childPrefix = `${this._prefix}${formattedSub}`;
261
+ }
262
+ return new _Logger({
263
+ prefix: childPrefix,
264
+ logLevel: options.logLevel ?? this._level,
265
+ loadedAt: options.loadedAt ?? this._loadedAt,
266
+ now: options.now ?? this._now,
267
+ console: options.console ?? this._console,
268
+ formatTime: options.formatTime ?? this._customFormatTime,
269
+ ...options
270
+ });
271
+ }
272
+ withPrefix(prefix) {
273
+ return new _Logger({
274
+ prefix,
275
+ logLevel: this._level,
276
+ loadedAt: this._loadedAt,
277
+ now: this._now,
278
+ console: this._console,
279
+ formatTime: this._customFormatTime
280
+ });
281
+ }
282
+ };
283
+ function createLogger(options) {
284
+ return new Logger(options);
285
+ }
286
+
1
287
  // ../../protogen/trace_event.ts
2
288
  import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
3
289
  var TraceEventType = {
@@ -967,8 +1253,264 @@ function parseBidDimensions(bid) {
967
1253
  height: Number.isFinite(bid?.height) ? bid.height : 0
968
1254
  };
969
1255
  }
1256
+ var adsLoaderListenerMap = /* @__PURE__ */ new WeakMap();
1257
+ function hookAdsManagerLoadedEvent(loadedEventCtor) {
1258
+ if (!loadedEventCtor) return;
1259
+ try {
1260
+ const loadedProto = loadedEventCtor.prototype;
1261
+ if (loadedProto && typeof loadedProto.getAdsManager === "function" && !loadedProto.getAdsManager.__bidkernelHooked) {
1262
+ const originalGetAdsManager = loadedProto.getAdsManager;
1263
+ const hookedGetAdsManager = function(...args) {
1264
+ const adsManager = originalGetAdsManager.apply(this, args);
1265
+ if (adsManager) {
1266
+ for (const instance of BidkernelPrebidAnalytics.getActiveInstances()) {
1267
+ try {
1268
+ instance.attachImaAdsManager(adsManager);
1269
+ } catch {
1270
+ }
1271
+ }
1272
+ }
1273
+ return adsManager;
1274
+ };
1275
+ hookedGetAdsManager.__bidkernelHooked = true;
1276
+ loadedProto.getAdsManager = hookedGetAdsManager;
1277
+ }
1278
+ } catch {
1279
+ }
1280
+ }
1281
+ function hookAdsManagerPrototype(adsManagerCtorOrProto) {
1282
+ if (!adsManagerCtorOrProto) return;
1283
+ try {
1284
+ const proto = adsManagerCtorOrProto.prototype || adsManagerCtorOrProto;
1285
+ if (proto && typeof proto.init === "function" && !proto.init.__bidkernelHooked) {
1286
+ const origInit = proto.init;
1287
+ const hookedInit = function(...args) {
1288
+ for (const instance of BidkernelPrebidAnalytics.getActiveInstances()) {
1289
+ try {
1290
+ instance.attachImaAdsManager(this);
1291
+ } catch {
1292
+ }
1293
+ }
1294
+ return origInit.apply(this, args);
1295
+ };
1296
+ hookedInit.__bidkernelHooked = true;
1297
+ proto.init = hookedInit;
1298
+ }
1299
+ if (proto && typeof proto.start === "function" && !proto.start.__bidkernelHooked) {
1300
+ const origStart = proto.start;
1301
+ const hookedStart = function(...args) {
1302
+ for (const instance of BidkernelPrebidAnalytics.getActiveInstances()) {
1303
+ try {
1304
+ instance.attachImaAdsManager(this);
1305
+ } catch {
1306
+ }
1307
+ }
1308
+ return origStart.apply(this, args);
1309
+ };
1310
+ hookedStart.__bidkernelHooked = true;
1311
+ proto.start = hookedStart;
1312
+ }
1313
+ } catch {
1314
+ }
1315
+ }
1316
+ function hookAdsLoader(adsLoaderCtor) {
1317
+ if (!adsLoaderCtor) return;
1318
+ try {
1319
+ const proto = adsLoaderCtor.prototype;
1320
+ if (!proto) return;
1321
+ if (typeof proto.addEventListener === "function" && !proto.addEventListener.__bidkernelHooked) {
1322
+ const origAddEventListener = proto.addEventListener;
1323
+ const hookedAddEventListener = function(type, listener, ...rest) {
1324
+ if ((type === "adsManagerLoaded" || type === (this?.AdsManagerLoadedEvent?.Type?.ADS_MANAGER_LOADED || "adsManagerLoaded")) && typeof listener === "function") {
1325
+ let wrappedListener = adsLoaderListenerMap.get(listener);
1326
+ if (!wrappedListener) {
1327
+ wrappedListener = function(event) {
1328
+ if (event && typeof event.getAdsManager === "function" && !event.getAdsManager.__bidkernelHooked) {
1329
+ const origGetAdsManager = event.getAdsManager;
1330
+ event.getAdsManager = function(...args) {
1331
+ const adsManager = origGetAdsManager.apply(this, args);
1332
+ if (adsManager) {
1333
+ for (const sdk of BidkernelPrebidAnalytics.getActiveInstances()) {
1334
+ try {
1335
+ sdk.attachImaAdsManager(adsManager);
1336
+ } catch {
1337
+ }
1338
+ }
1339
+ }
1340
+ return adsManager;
1341
+ };
1342
+ event.getAdsManager.__bidkernelHooked = true;
1343
+ }
1344
+ return listener.apply(this, arguments);
1345
+ };
1346
+ adsLoaderListenerMap.set(listener, wrappedListener);
1347
+ }
1348
+ return origAddEventListener.call(this, type, wrappedListener, ...rest);
1349
+ }
1350
+ return origAddEventListener.call(this, type, listener, ...rest);
1351
+ };
1352
+ hookedAddEventListener.__bidkernelHooked = true;
1353
+ proto.addEventListener = hookedAddEventListener;
1354
+ }
1355
+ if (typeof proto.removeEventListener === "function" && !proto.removeEventListener.__bidkernelHooked) {
1356
+ const origRemoveEventListener = proto.removeEventListener;
1357
+ const hookedRemoveEventListener = function(type, listener, ...rest) {
1358
+ const wrapped = typeof listener === "function" ? adsLoaderListenerMap.get(listener) : void 0;
1359
+ return origRemoveEventListener.call(this, type, wrapped || listener, ...rest);
1360
+ };
1361
+ hookedRemoveEventListener.__bidkernelHooked = true;
1362
+ proto.removeEventListener = hookedRemoveEventListener;
1363
+ }
1364
+ } catch {
1365
+ }
1366
+ }
1367
+ function hookImaPrototype(ima) {
1368
+ if (!ima || typeof ima !== "object") return;
1369
+ try {
1370
+ if (ima.AdsManagerLoadedEvent) {
1371
+ hookAdsManagerLoadedEvent(ima.AdsManagerLoadedEvent);
1372
+ }
1373
+ const loadedDesc = Object.getOwnPropertyDescriptor(ima, "AdsManagerLoadedEvent");
1374
+ if (!loadedDesc || loadedDesc.configurable) {
1375
+ let _loadedEvent = ima.AdsManagerLoadedEvent;
1376
+ try {
1377
+ Object.defineProperty(ima, "AdsManagerLoadedEvent", {
1378
+ configurable: true,
1379
+ enumerable: true,
1380
+ get() {
1381
+ return _loadedEvent;
1382
+ },
1383
+ set(val) {
1384
+ _loadedEvent = val;
1385
+ hookAdsManagerLoadedEvent(val);
1386
+ }
1387
+ });
1388
+ } catch {
1389
+ }
1390
+ }
1391
+ if (ima.AdsLoader) {
1392
+ hookAdsLoader(ima.AdsLoader);
1393
+ }
1394
+ const loaderDesc = Object.getOwnPropertyDescriptor(ima, "AdsLoader");
1395
+ if (!loaderDesc || loaderDesc.configurable) {
1396
+ let _loader = ima.AdsLoader;
1397
+ try {
1398
+ Object.defineProperty(ima, "AdsLoader", {
1399
+ configurable: true,
1400
+ enumerable: true,
1401
+ get() {
1402
+ return _loader;
1403
+ },
1404
+ set(val) {
1405
+ _loader = val;
1406
+ hookAdsLoader(val);
1407
+ }
1408
+ });
1409
+ } catch {
1410
+ }
1411
+ }
1412
+ if (ima.AdsManager) {
1413
+ hookAdsManagerPrototype(ima.AdsManager);
1414
+ }
1415
+ const mgrDesc = Object.getOwnPropertyDescriptor(ima, "AdsManager");
1416
+ if (!mgrDesc || mgrDesc.configurable) {
1417
+ let _mgr = ima.AdsManager;
1418
+ try {
1419
+ Object.defineProperty(ima, "AdsManager", {
1420
+ configurable: true,
1421
+ enumerable: true,
1422
+ get() {
1423
+ return _mgr;
1424
+ },
1425
+ set(val) {
1426
+ _mgr = val;
1427
+ hookAdsManagerPrototype(val);
1428
+ }
1429
+ });
1430
+ } catch {
1431
+ }
1432
+ }
1433
+ } catch {
1434
+ }
1435
+ }
1436
+ function initImaInterception() {
1437
+ if (typeof window === "undefined") return;
1438
+ const win = window;
1439
+ if (win.google?.ima) {
1440
+ hookImaPrototype(win.google.ima);
1441
+ }
1442
+ if (win.google && typeof win.google === "object") {
1443
+ const imaDesc = Object.getOwnPropertyDescriptor(win.google, "ima");
1444
+ if (!imaDesc || imaDesc.configurable) {
1445
+ let _ima = win.google.ima;
1446
+ try {
1447
+ Object.defineProperty(win.google, "ima", {
1448
+ configurable: true,
1449
+ enumerable: true,
1450
+ get() {
1451
+ return _ima;
1452
+ },
1453
+ set(val) {
1454
+ _ima = val;
1455
+ hookImaPrototype(val);
1456
+ }
1457
+ });
1458
+ } catch {
1459
+ }
1460
+ }
1461
+ }
1462
+ const googleDesc = Object.getOwnPropertyDescriptor(win, "google");
1463
+ if (!googleDesc || googleDesc.configurable) {
1464
+ let _google = win.google;
1465
+ try {
1466
+ Object.defineProperty(win, "google", {
1467
+ configurable: true,
1468
+ enumerable: true,
1469
+ get() {
1470
+ return _google;
1471
+ },
1472
+ set(val) {
1473
+ _google = val;
1474
+ if (_google && typeof _google === "object") {
1475
+ if (_google.ima) {
1476
+ hookImaPrototype(_google.ima);
1477
+ }
1478
+ const iDesc = Object.getOwnPropertyDescriptor(_google, "ima");
1479
+ if (!iDesc || iDesc.configurable) {
1480
+ let _i = _google.ima;
1481
+ try {
1482
+ Object.defineProperty(_google, "ima", {
1483
+ configurable: true,
1484
+ enumerable: true,
1485
+ get() {
1486
+ return _i;
1487
+ },
1488
+ set(iv) {
1489
+ _i = iv;
1490
+ hookImaPrototype(iv);
1491
+ }
1492
+ });
1493
+ } catch {
1494
+ }
1495
+ }
1496
+ }
1497
+ }
1498
+ });
1499
+ } catch {
1500
+ }
1501
+ }
1502
+ }
1503
+ if (typeof window !== "undefined") {
1504
+ initImaInterception();
1505
+ }
970
1506
  var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
971
1507
  static activeInstances = /* @__PURE__ */ new Set();
1508
+ static getActiveInstances() {
1509
+ return _BidkernelPrebidAnalytics.activeInstances;
1510
+ }
1511
+ static initImaInterception() {
1512
+ initImaInterception();
1513
+ }
972
1514
  config;
973
1515
  queue = [];
974
1516
  errorCount = 0;
@@ -1005,6 +1547,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1005
1547
  videoDetachCleanups = /* @__PURE__ */ new Set();
1006
1548
  // Compacted bidder participation map per auction: auctionId -> Map<`${bidder}:${adUnitCode}`, BidderOutcomeEntry>
1007
1549
  auctionBidderOutcomes = /* @__PURE__ */ new Map();
1550
+ logger;
1008
1551
  constructor(config) {
1009
1552
  const requestedEndpoint = config.endpoint || "";
1010
1553
  const endpoint = !requestedEndpoint || isTrustedEndpoint(requestedEndpoint) ? requestedEndpoint : "";
@@ -1025,6 +1568,10 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1025
1568
  pbjsGlobalName: config.pbjsGlobalName || "pbjs",
1026
1569
  attachPbjsListeners: config.attachPbjsListeners ?? true
1027
1570
  };
1571
+ this.logger = createLogger({
1572
+ prefix: "[bidkernel][prebid-analytics]",
1573
+ logLevel: this.config.logLevel
1574
+ });
1028
1575
  if (requestedEndpoint && !endpoint) {
1029
1576
  this.log(
1030
1577
  "ERROR",
@@ -1041,6 +1588,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1041
1588
  if (this.isEnabled) return;
1042
1589
  this.isEnabled = true;
1043
1590
  _BidkernelPrebidAnalytics.activeInstances.add(this);
1591
+ this.logger.setLevel(this.config.logLevel);
1044
1592
  if (!this.config.endpoint) {
1045
1593
  this.log("WARN", "Endpoint is empty. Analytics events will not be transmitted.");
1046
1594
  }
@@ -1132,6 +1680,10 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1132
1680
  }
1133
1681
  this.flushTimer = setInterval(() => this.flush(), FLUSH_INTERVAL_MS);
1134
1682
  this.resendPersistedBatches();
1683
+ initImaInterception();
1684
+ if (window.google?.ima) {
1685
+ hookImaPrototype(window.google.ima);
1686
+ }
1135
1687
  }
1136
1688
  }
1137
1689
  disable() {
@@ -1612,6 +2164,72 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1612
2164
  this.cachedWinningBids.delete(oldest.value);
1613
2165
  }
1614
2166
  }
2167
+ /**
2168
+ * Searches cached winning bids for an entry matching the given filters (creativeId,
2169
+ * adId, or mediaType), falling back to the most recent winning video bid.
2170
+ */
2171
+ findCachedWinningBid(filter) {
2172
+ const now = Date.now();
2173
+ const isConsumed = (entry) => {
2174
+ return this.hasImpressionEmitted(
2175
+ entry.adUnitCode,
2176
+ void 0,
2177
+ entry.auctionId,
2178
+ entry.bidTrace.creativeId
2179
+ );
2180
+ };
2181
+ if (filter?.creativeId || filter?.adId) {
2182
+ for (const entry of Array.from(this.cachedWinningBids.values())) {
2183
+ if (now - entry.timestamp > CACHED_BID_TTL_MS) continue;
2184
+ if (filter.creativeId && (entry.bidTrace.creativeId === filter.creativeId || entry.rawBid?.creativeId === filter.creativeId) || filter.adId && (entry.rawBid?.adId === filter.adId || entry.adUnitCode === filter.adId)) {
2185
+ return entry;
2186
+ }
2187
+ }
2188
+ }
2189
+ let bestUnconsumedMatch;
2190
+ if (filter?.mediaType) {
2191
+ for (const entry of Array.from(this.cachedWinningBids.values())) {
2192
+ if (now - entry.timestamp > CACHED_BID_TTL_MS) continue;
2193
+ const isEntryVideo = entry.bidTrace.mediaType === filter.mediaType || entry.rawBid?.mediaType === filter.mediaType || filter.mediaType === "video" && entry.rawBid?.mediaTypes?.video !== void 0;
2194
+ if (isEntryVideo) {
2195
+ if (!isConsumed(entry)) {
2196
+ if (!bestUnconsumedMatch || entry.timestamp < bestUnconsumedMatch.timestamp) {
2197
+ bestUnconsumedMatch = entry;
2198
+ }
2199
+ }
2200
+ }
2201
+ }
2202
+ if (bestUnconsumedMatch) return bestUnconsumedMatch;
2203
+ let bestFallbackMatch;
2204
+ for (const entry of Array.from(this.cachedWinningBids.values())) {
2205
+ if (now - entry.timestamp > CACHED_BID_TTL_MS) continue;
2206
+ const isEntryVideo = entry.bidTrace.mediaType === filter.mediaType || entry.rawBid?.mediaType === filter.mediaType || filter.mediaType === "video" && entry.rawBid?.mediaTypes?.video !== void 0;
2207
+ if (isEntryVideo) {
2208
+ if (!bestFallbackMatch || entry.timestamp > bestFallbackMatch.timestamp) {
2209
+ bestFallbackMatch = entry;
2210
+ }
2211
+ }
2212
+ }
2213
+ if (bestFallbackMatch) return bestFallbackMatch;
2214
+ }
2215
+ for (const entry of Array.from(this.cachedWinningBids.values())) {
2216
+ if (now - entry.timestamp > CACHED_BID_TTL_MS) continue;
2217
+ if (!isConsumed(entry)) {
2218
+ if (!bestUnconsumedMatch || entry.timestamp > bestUnconsumedMatch.timestamp) {
2219
+ bestUnconsumedMatch = entry;
2220
+ }
2221
+ }
2222
+ }
2223
+ if (bestUnconsumedMatch) return bestUnconsumedMatch;
2224
+ let bestRecent;
2225
+ for (const entry of Array.from(this.cachedWinningBids.values())) {
2226
+ if (now - entry.timestamp > CACHED_BID_TTL_MS) continue;
2227
+ if (!bestRecent || entry.timestamp > bestRecent.timestamp) {
2228
+ bestRecent = entry;
2229
+ }
2230
+ }
2231
+ return bestRecent;
2232
+ }
1615
2233
  /** Records a dedup key, evicting oldest-first at the cap. */
1616
2234
  addImpressionKey(key) {
1617
2235
  if (this.slotEmittedImpressionKeys.has(key)) return;
@@ -1771,14 +2389,40 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1771
2389
  return () => {
1772
2390
  };
1773
2391
  }
2392
+ if (!adsManager.__bidkernelAttachedInstances) {
2393
+ try {
2394
+ Object.defineProperty(adsManager, "__bidkernelAttachedInstances", {
2395
+ value: /* @__PURE__ */ new Set(),
2396
+ configurable: true,
2397
+ writable: true
2398
+ });
2399
+ } catch {
2400
+ adsManager.__bidkernelAttachedInstances = /* @__PURE__ */ new Set();
2401
+ }
2402
+ }
2403
+ if (adsManager.__bidkernelAttachedInstances.has(this)) {
2404
+ return () => {
2405
+ };
2406
+ }
2407
+ adsManager.__bidkernelAttachedInstances.add(this);
1774
2408
  const slotId = options?.slotId || options?.adUnitCode || "video";
1775
2409
  const adUnitCode = options?.adUnitCode || slotId;
1776
2410
  const auctionId = options?.auctionId || "";
1777
2411
  const transactionId = options?.transactionId || "";
1778
- const getWinningBid = () => {
1779
- return (auctionId ? this.getCachedBid(`${auctionId}:${adUnitCode}`) : void 0) || (auctionId && slotId !== adUnitCode ? this.getCachedBid(`${auctionId}:${slotId}`) : void 0) || this.getCachedBid(adUnitCode) || (slotId !== adUnitCode ? this.getCachedBid(slotId) : void 0);
2412
+ const getWinningBid = (adData) => {
2413
+ let cached = (auctionId ? this.getCachedBid(`${auctionId}:${adUnitCode}`) : void 0) || (auctionId && slotId !== adUnitCode ? this.getCachedBid(`${auctionId}:${slotId}`) : void 0) || (adUnitCode !== "video" ? this.getCachedBid(adUnitCode) : void 0) || (slotId !== adUnitCode && slotId !== "video" ? this.getCachedBid(slotId) : void 0);
2414
+ if (!cached) {
2415
+ cached = this.findCachedWinningBid({
2416
+ creativeId: adData?.creativeId,
2417
+ adId: adData?.adId,
2418
+ mediaType: "video"
2419
+ });
2420
+ }
2421
+ return cached;
1780
2422
  };
2423
+ let adStarted = false;
1781
2424
  const onAdStartedOrImpression = (event) => {
2425
+ adStarted = true;
1782
2426
  this.log("DEBUG", "IMA AdEvent.STARTED / IMPRESSION received", event);
1783
2427
  const ad = typeof event?.getAd === "function" ? event.getAd() : event?.ad;
1784
2428
  const adData = {};
@@ -1789,16 +2433,20 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1789
2433
  adData.duration = typeof ad.getDuration === "function" ? ad.getDuration() : ad.duration;
1790
2434
  adData.advertiserName = typeof ad.getAdvertiserName === "function" ? ad.getAdvertiserName() : "";
1791
2435
  }
1792
- const cached = getWinningBid();
2436
+ const cached = getWinningBid(adData);
2437
+ const resolvedSlotId = options?.slotId && options.slotId !== "video" ? options.slotId : options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || options?.slotId || options?.adUnitCode || "video";
2438
+ const resolvedAdUnitCode = options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || resolvedSlotId;
2439
+ const resolvedAuctionId = auctionId || cached?.auctionId || "";
2440
+ const resolvedTransactionId = transactionId || cached?.transactionId || "";
1793
2441
  const mergedBid = {
1794
2442
  ...cached?.rawBid || options?.bid,
1795
2443
  mediaType: "video",
1796
2444
  creativeId: adData.creativeId || cached?.bidTrace?.creativeId || options?.bid?.creativeId || ""
1797
2445
  };
1798
- const emitted = this.recordImpression(slotId, {
1799
- adUnitCode,
1800
- auctionId: auctionId || cached?.auctionId,
1801
- transactionId: transactionId || cached?.transactionId,
2446
+ const emitted = this.recordImpression(resolvedSlotId, {
2447
+ adUnitCode: resolvedAdUnitCode,
2448
+ auctionId: resolvedAuctionId,
2449
+ transactionId: resolvedTransactionId,
1802
2450
  mediaType: "video",
1803
2451
  bid: mergedBid,
1804
2452
  metadata: {
@@ -1810,7 +2458,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1810
2458
  });
1811
2459
  if (emitted && options?.onImpression) {
1812
2460
  try {
1813
- options.onImpression(slotId, { ad, bid: mergedBid });
2461
+ options.onImpression(resolvedSlotId, { ad, bid: mergedBid });
1814
2462
  } catch (e) {
1815
2463
  this.log("ERROR", "Error in onImpression callback", e);
1816
2464
  }
@@ -1829,10 +2477,11 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1829
2477
  const onAdClick = (event) => {
1830
2478
  this.log("DEBUG", "IMA AdEvent.CLICK received", event);
1831
2479
  const cached = getWinningBid();
2480
+ const resolvedAdUnitCode = options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || slotId;
1832
2481
  this.enqueue(TraceEventType.CLICK, "click", {
1833
2482
  auctionId: auctionId || cached?.auctionId,
1834
2483
  transactionId: transactionId || cached?.transactionId,
1835
- adUnitCode,
2484
+ adUnitCode: resolvedAdUnitCode,
1836
2485
  bid: cached?.bidTrace || options?.bid,
1837
2486
  metadata: {
1838
2487
  ...options?.metadata,
@@ -1846,14 +2495,16 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1846
2495
  const msg = (err && typeof err.getMessage === "function" ? err.getMessage() : err?.message) || String(err || "IMA ad error");
1847
2496
  const code = (err && typeof err.getErrorCode === "function" ? err.getErrorCode() : err?.code) || "";
1848
2497
  const cached = getWinningBid();
2498
+ const resolvedAdUnitCode = options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || slotId;
1849
2499
  this.enqueue(TraceEventType.AD_RENDER_FAILED, "adRenderFailed", {
1850
2500
  auctionId: auctionId || cached?.auctionId,
1851
2501
  transactionId: transactionId || cached?.transactionId,
1852
- adUnitCode,
2502
+ adUnitCode: resolvedAdUnitCode,
1853
2503
  bid: cached?.bidTrace || options?.bid,
1854
2504
  metadata: {
1855
2505
  ...options?.metadata,
1856
- reason: "ima_ad_error",
2506
+ reason: adStarted ? "ima_playback_error" : "ima_ad_error",
2507
+ playback_phase: adStarted ? "post_start" : "pre_start",
1857
2508
  message: msg,
1858
2509
  ...code ? { ima_error_code: String(code) } : {}
1859
2510
  },
@@ -1870,7 +2521,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1870
2521
  const googleIma = typeof window !== "undefined" ? window.google?.ima : void 0;
1871
2522
  const adEventType = googleIma?.AdEvent?.Type || {};
1872
2523
  const adErrorEventType = googleIma?.AdErrorEvent?.Type || {};
1873
- const listeners = [
2524
+ const rawListeners = [
1874
2525
  { type: adEventType.STARTED || "started", handler: onAdStartedOrImpression },
1875
2526
  { type: adEventType.IMPRESSION || "impression", handler: onAdStartedOrImpression },
1876
2527
  {
@@ -1886,6 +2537,14 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1886
2537
  { type: adEventType.CLICK || "click", handler: onAdClick },
1887
2538
  { type: adErrorEventType.AD_ERROR || "adError", handler: onAdError }
1888
2539
  ];
2540
+ const seenListenerTypes = /* @__PURE__ */ new Set();
2541
+ const listeners = [];
2542
+ for (const l of rawListeners) {
2543
+ if (!seenListenerTypes.has(l.type)) {
2544
+ seenListenerTypes.add(l.type);
2545
+ listeners.push(l);
2546
+ }
2547
+ }
1889
2548
  for (const { type, handler } of listeners) {
1890
2549
  try {
1891
2550
  adsManager.addEventListener(type, handler);
@@ -1893,6 +2552,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1893
2552
  }
1894
2553
  }
1895
2554
  const cleanup = () => {
2555
+ adsManager.__bidkernelAttachedInstances?.delete(this);
1896
2556
  for (const { type, handler } of listeners) {
1897
2557
  try {
1898
2558
  adsManager.removeEventListener(type, handler);
@@ -2214,6 +2874,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2214
2874
  } else {
2215
2875
  this.pageUrl = "";
2216
2876
  }
2877
+ this.logger.resetTiming();
2217
2878
  extendSession();
2218
2879
  this.enable();
2219
2880
  }
@@ -2278,7 +2939,8 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2278
2939
  const adUnitCode = data.adUnitCode || "";
2279
2940
  const cpm = Number.isFinite(data.originalCpm) ? data.originalCpm : Number.isFinite(data.cpm) ? data.cpm : 0;
2280
2941
  const latencyMs = Number.isFinite(data.timeToRespond) ? data.timeToRespond : 0;
2281
- const mediaType = data.mediaType || "banner";
2942
+ const resMediaTypes = Object.keys(data.mediaTypes || {});
2943
+ const mediaType = data.mediaType || (data.mediaTypes?.video ? "video" : resMediaTypes.length > 0 ? resMediaTypes[0] : "banner");
2282
2944
  if (auctionId && bidder) {
2283
2945
  const auctionMap = this.getOrCreateAuctionOutcomes(auctionId);
2284
2946
  const key = `${bidder}:${adUnitCode}`;
@@ -2351,13 +3013,15 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2351
3013
  const auctionId = data.auctionId || "";
2352
3014
  const transactionId = data.transactionId || "";
2353
3015
  const adUnitCode = data.adUnitCode || data.adId || "";
3016
+ const wonMediaTypes = Object.keys(data.mediaTypes || {});
3017
+ const resolvedMediaType = data.mediaType || (data.mediaTypes?.video ? "video" : wonMediaTypes.length > 0 ? wonMediaTypes[0] : "banner");
2354
3018
  const bidTrace = {
2355
3019
  bidder: data.bidderCode || data.bidder || "",
2356
3020
  cpm: Number.isFinite(data.originalCpm) ? data.originalCpm : Number.isFinite(data.cpm) ? data.cpm : 0,
2357
3021
  currency: data.originalCurrency ?? data.currency ?? "USD",
2358
3022
  ...parseBidDimensions(data),
2359
3023
  dealId: data.dealId || "",
2360
- mediaType: data.mediaType || "banner",
3024
+ mediaType: resolvedMediaType,
2361
3025
  latencyMs: Number.isFinite(data.timeToRespond) ? data.timeToRespond : 0,
2362
3026
  advertiserDomain: data.meta?.advertiserDomains?.[0] || "",
2363
3027
  creativeId: data.creativeId || ""
@@ -2446,13 +3110,15 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2446
3110
  const slotKey = data.adUnitCode || bid.adUnitCode || "";
2447
3111
  const altKey = data.adId || bid.adId || "";
2448
3112
  const cached = (auctionId && slotKey ? this.getCachedBid(`${auctionId}:${slotKey}`) : void 0) || (auctionId && altKey ? this.getCachedBid(`${auctionId}:${altKey}`) : void 0) || (slotKey ? this.getCachedBid(slotKey) : void 0) || (altKey ? this.getCachedBid(altKey) : void 0);
3113
+ const isVideo = mediaType === "video" || bid.mediaType === "video" || bid.mediaTypes?.video !== void 0 || cached?.bidTrace?.mediaType === "video" || cached?.rawBid?.mediaType === "video" || adUnitCode && this.slotViewabilityRecords.get(adUnitCode)?.mediaType === "video";
3114
+ const resolvedMediaType = isVideo ? "video" : mediaType || cached?.bidTrace?.mediaType || "banner";
2449
3115
  const bidTrace = {
2450
3116
  bidder: bid.bidderCode || bid.bidder || cached?.bidTrace?.bidder || "",
2451
3117
  cpm: Number.isFinite(bid.originalCpm) ? bid.originalCpm : Number.isFinite(bid.cpm) ? bid.cpm : cached?.bidTrace?.cpm ?? 0,
2452
3118
  currency: bid.originalCurrency ?? bid.currency ?? cached?.bidTrace?.currency ?? "USD",
2453
3119
  ...parseBidDimensions(bid).width ? parseBidDimensions(bid) : cached?.bidTrace ? { width: cached.bidTrace.width, height: cached.bidTrace.height } : parseBidDimensions(bid),
2454
3120
  dealId: bid.dealId || cached?.bidTrace?.dealId || "",
2455
- mediaType: mediaType || cached?.bidTrace?.mediaType || "banner",
3121
+ mediaType: resolvedMediaType,
2456
3122
  latencyMs: Number.isFinite(bid.timeToRespond) ? bid.timeToRespond : cached?.bidTrace?.latencyMs ?? 0,
2457
3123
  advertiserDomain: bid.meta?.advertiserDomains?.[0] || cached?.bidTrace?.advertiserDomain || "",
2458
3124
  creativeId: bid.creativeId || cached?.bidTrace?.creativeId || ""
@@ -2491,28 +3157,35 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2491
3157
  }
2492
3158
  }
2493
3159
  const currentRefreshIndex = adUnitCode ? this.slotRefreshIndices.get(adUnitCode) ?? (record ? record.refreshIndex : 0) : 0;
2494
- const alreadyEmitted = adUnitCode ? this.hasImpressionEmitted(
2495
- adUnitCode,
2496
- currentRefreshIndex,
2497
- resolvedAuctionId,
2498
- bidTrace.creativeId
2499
- ) : false;
2500
- if (!alreadyEmitted) {
2501
- if (adUnitCode) {
2502
- this.markImpressionEmitted(
3160
+ if (!isVideo) {
3161
+ const alreadyEmitted = adUnitCode ? this.hasImpressionEmitted(
3162
+ adUnitCode,
3163
+ currentRefreshIndex,
3164
+ resolvedAuctionId,
3165
+ bidTrace.creativeId
3166
+ ) : false;
3167
+ if (!alreadyEmitted) {
3168
+ if (adUnitCode) {
3169
+ this.markImpressionEmitted(
3170
+ adUnitCode,
3171
+ currentRefreshIndex,
3172
+ resolvedAuctionId,
3173
+ bidTrace.creativeId
3174
+ );
3175
+ }
3176
+ this.enqueue(TraceEventType.IMPRESSION, "impression", {
3177
+ auctionId: resolvedAuctionId,
3178
+ transactionId: resolvedTransactionId,
2503
3179
  adUnitCode,
2504
- currentRefreshIndex,
2505
- resolvedAuctionId,
2506
- bidTrace.creativeId
2507
- );
3180
+ bid: bidTrace,
3181
+ metadata: { refresh_index: String(currentRefreshIndex) }
3182
+ });
2508
3183
  }
2509
- this.enqueue(TraceEventType.IMPRESSION, "impression", {
2510
- auctionId: resolvedAuctionId,
2511
- transactionId: resolvedTransactionId,
2512
- adUnitCode,
2513
- bid: bidTrace,
2514
- metadata: { refresh_index: String(currentRefreshIndex) }
2515
- });
3184
+ } else {
3185
+ this.log(
3186
+ "DEBUG",
3187
+ `adRenderSucceeded received for video ad unit ${adUnitCode || "unknown"}: suppressing IMPRESSION until verified video lifecycle event`
3188
+ );
2516
3189
  }
2517
3190
  if (this.config.viewabilityEnabled && typeof document !== "undefined") {
2518
3191
  let el = null;
@@ -2548,7 +3221,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2548
3221
  adUnitCode,
2549
3222
  auctionId: resolvedAuctionId,
2550
3223
  transactionId: resolvedTransactionId,
2551
- mediaType,
3224
+ mediaType: resolvedMediaType,
2552
3225
  bid: bidTrace,
2553
3226
  refreshIndex: currentRefreshIndex,
2554
3227
  emitRefreshEvent: false
@@ -2881,25 +3554,13 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2881
3554
  }
2882
3555
  }
2883
3556
  log(level, msg, ...args) {
2884
- const levels = { DEBUG: 10, INFO: 20, WARN: 30, ERROR: 40 };
2885
- if (levels[level] < levels[this.config.logLevel]) return;
2886
- const prefix = `[bidkernel][prebid-analytics][${level}]`;
2887
- switch (level) {
2888
- case "DEBUG":
2889
- console.debug(prefix, msg, ...args);
2890
- break;
2891
- case "INFO":
2892
- console.info(prefix, msg, ...args);
2893
- break;
2894
- case "WARN":
2895
- console.warn(prefix, msg, ...args);
2896
- break;
2897
- case "ERROR":
2898
- console.error(prefix, msg, ...args);
2899
- break;
2900
- }
3557
+ this.logger.log(level, msg, ...args);
2901
3558
  }
2902
3559
  };
3560
+ var defaultLogger = createLogger({
3561
+ prefix: "[bidkernel]",
3562
+ logLevel: "INFO"
3563
+ });
2903
3564
  function extractAnalyticsOptions(config, allowProviderless = true) {
2904
3565
  if (!config) return null;
2905
3566
  if (Array.isArray(config)) {
@@ -2956,8 +3617,8 @@ function registerPrebidAnalytics(pbjsGlobalName = "pbjs", defaults) {
2956
3617
  ...options
2957
3618
  };
2958
3619
  if (pinnedEndpoint && !sameEndpointOrigin(merged.endpoint || "", pinnedEndpoint)) {
2959
- console.warn(
2960
- `[bidkernel] Ignoring analytics endpoint change to ${merged.endpoint || "(empty)"}: this page is pinned to ${pinnedEndpoint}. Reload to change the ingest endpoint.`
3620
+ defaultLogger.warn(
3621
+ `Ignoring analytics endpoint change to ${merged.endpoint || "(empty)"}: this page is pinned to ${pinnedEndpoint}. Reload to change the ingest endpoint.`
2961
3622
  );
2962
3623
  merged.endpoint = pinnedEndpoint;
2963
3624
  }
@@ -2965,7 +3626,7 @@ function registerPrebidAnalytics(pbjsGlobalName = "pbjs", defaults) {
2965
3626
  try {
2966
3627
  previous.disable();
2967
3628
  } catch (e) {
2968
- console.warn("[bidkernel] Failed to disable previous analytics instance:", e);
3629
+ defaultLogger.warn("Failed to disable previous analytics instance:", e);
2969
3630
  }
2970
3631
  }
2971
3632
  const analytics = new BidkernelPrebidAnalytics(merged);
@@ -2998,7 +3659,7 @@ function registerPrebidAnalytics(pbjsGlobalName = "pbjs", defaults) {
2998
3659
  enableInstance(stashed);
2999
3660
  }
3000
3661
  } catch (e) {
3001
- console.warn("[bidkernel] Failed to register standard Prebid analytics adapter:", e);
3662
+ defaultLogger.warn("Failed to register standard Prebid analytics adapter:", e);
3002
3663
  }
3003
3664
  };
3004
3665
  if (pbjs.adapterManager && typeof pbjs.adapterManager.registerAnalyticsAdapter === "function") {
@@ -3044,6 +3705,8 @@ export {
3044
3705
  PrebidEventDeduper,
3045
3706
  getPrebidEventKey,
3046
3707
  getbidkernel,
3708
+ hookImaPrototype,
3709
+ initImaInterception,
3047
3710
  isTrustedEndpoint,
3048
3711
  registerPrebidAnalytics
3049
3712
  };