@bidkernel/analytics 0.24.0 → 0.27.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.js CHANGED
@@ -23,6 +23,7 @@ __export(src_exports, {
23
23
  BidkernelPrebidAnalytics: () => BidkernelPrebidAnalytics,
24
24
  CACHED_BID_TTL_MS: () => CACHED_BID_TTL_MS,
25
25
  ImaAdsManagerStub: () => ImaAdsManagerStub,
26
+ LogLevel: () => LogLevel,
26
27
  PrebidEventDeduper: () => PrebidEventDeduper,
27
28
  attachImaAdsManager: () => attachImaAdsManager,
28
29
  attachVideoPlayer: () => attachVideoPlayer,
@@ -34,6 +35,7 @@ __export(src_exports, {
34
35
  isSessionActive: () => isSessionActive,
35
36
  isTrustedEndpoint: () => isTrustedEndpoint,
36
37
  normalizeImaEventName: () => normalizeImaEventName,
38
+ normalizeLogLevel: () => normalizeLogLevel,
37
39
  onSessionResume: () => onSessionResume,
38
40
  registerPrebidAnalytics: () => registerPrebidAnalytics
39
41
  });
@@ -345,6 +347,14 @@ var TraceEventType = {
345
347
  CLICK: 12,
346
348
  /** AD_RENDER_FAILED - Prebid failed to render the winning ad */
347
349
  AD_RENDER_FAILED: 13,
350
+ /**
351
+ * WARN - A wrapper condition worth reporting that is not a failure: a slot with no
352
+ * fitting sizes, a video load the watchdog cut short. Carries its own
353
+ * event_name, like ERROR. Publishers gate these with warnings_enabled;
354
+ * ERROR is never gated. Before this type these events reached the adapter
355
+ * and were dropped for want of one, so warnings_enabled controlled nothing.
356
+ */
357
+ WARN: 17,
348
358
  UNRECOGNIZED: -1
349
359
  };
350
360
  var BidderOutcome = {
@@ -1051,6 +1061,14 @@ var EVENT_NAME_TO_TYPE = {
1051
1061
  timeInView: TraceEventType.TIME_IN_VIEW,
1052
1062
  viewable: TraceEventType.VIEWABLE
1053
1063
  };
1064
+ var LEVEL_TO_TYPE = {
1065
+ WARN: TraceEventType.WARN,
1066
+ ERROR: TraceEventType.ERROR
1067
+ };
1068
+ var SELF_NAMING_TYPES = /* @__PURE__ */ new Set([
1069
+ TraceEventType.ERROR,
1070
+ TraceEventType.WARN
1071
+ ]);
1054
1072
  var REVENUE_FLUSH_DELAY_MS = 3e3;
1055
1073
  var REVENUE_FLUSH_TYPES = /* @__PURE__ */ new Set([
1056
1074
  TraceEventType.IMPRESSION,
@@ -1318,11 +1336,26 @@ function parseBidDimensions(bid) {
1318
1336
  height: Number.isFinite(bid?.height) ? bid.height : 0
1319
1337
  };
1320
1338
  }
1339
+ var defaultLogger = createLogger({
1340
+ prefix: "[analytics]",
1341
+ logLevel: "INFO"
1342
+ });
1321
1343
  var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1322
1344
  static activeInstances = /* @__PURE__ */ new Set();
1345
+ static allInstances = /* @__PURE__ */ new Set();
1323
1346
  static getActiveInstances() {
1324
1347
  return _BidkernelPrebidAnalytics.activeInstances;
1325
1348
  }
1349
+ static setLogLevel(level) {
1350
+ const norm = normalizeLogLevel(level);
1351
+ defaultLogger.setLevel(norm);
1352
+ for (const inst of _BidkernelPrebidAnalytics.allInstances) {
1353
+ inst.setLogLevel(norm);
1354
+ }
1355
+ }
1356
+ static getLogLevel() {
1357
+ return defaultLogger.getLevel();
1358
+ }
1326
1359
  /**
1327
1360
  * Allows or forbids localStorage writes for every instance on the page.
1328
1361
  * Collection and delivery are unaffected: only the persisted session id,
@@ -1361,6 +1394,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1361
1394
  slotViewabilityRecords = /* @__PURE__ */ new Map();
1362
1395
  elementToSlotId = /* @__PURE__ */ new Map();
1363
1396
  slotRefreshIndices = /* @__PURE__ */ new Map();
1397
+ slotAdSessionCounters = /* @__PURE__ */ new Map();
1364
1398
  slotLastAuctionIds = /* @__PURE__ */ new Map();
1365
1399
  pendingThresholdListeners = /* @__PURE__ */ new Map();
1366
1400
  pendingViewableListeners = /* @__PURE__ */ new Map();
@@ -1404,11 +1438,12 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1404
1438
  errorsEnabled: config.errorsEnabled ?? true,
1405
1439
  viewabilityEnabled: config.viewabilityEnabled ?? true,
1406
1440
  storageAllowed: config.storageAllowed ?? true,
1407
- logLevel: config.logLevel || "INFO",
1441
+ logLevel: config.logLevel ? normalizeLogLevel(config.logLevel) : defaultLogger.getLevel(),
1408
1442
  pbjsGlobalName: config.pbjsGlobalName || "pbjs",
1409
1443
  attachPbjsListeners: config.attachPbjsListeners ?? true,
1410
1444
  revenueFlushDelayMs: Number.isFinite(config.revenueFlushDelayMs) && config.revenueFlushDelayMs >= 0 ? config.revenueFlushDelayMs : REVENUE_FLUSH_DELAY_MS
1411
1445
  };
1446
+ _BidkernelPrebidAnalytics.allInstances.add(this);
1412
1447
  this.logger = createLogger({
1413
1448
  prefix: "[analytics]",
1414
1449
  logLevel: this.config.logLevel
@@ -1428,6 +1463,15 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
1428
1463
  };
1429
1464
  this.boundVisibilityChange = () => this.handleVisibilityChange();
1430
1465
  }
1466
+ setLogLevel(level) {
1467
+ const norm = normalizeLogLevel(level);
1468
+ this.config.logLevel = norm;
1469
+ this.logger.setLevel(norm);
1470
+ defaultLogger.setLevel(norm);
1471
+ }
1472
+ getLogLevel() {
1473
+ return this.logger.getLevel();
1474
+ }
1431
1475
  enable() {
1432
1476
  if (this.isEnabled) return;
1433
1477
  this.isEnabled = true;
@@ -2064,6 +2108,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2064
2108
  this.unobserveSlot(slotId);
2065
2109
  this.slotViewabilityRecords.delete(slotId);
2066
2110
  this.slotRefreshIndices.delete(slotId);
2111
+ this.slotAdSessionCounters.delete(slotId);
2067
2112
  this.slotLastAuctionIds.delete(slotId);
2068
2113
  this.pendingThresholdListeners.delete(slotId);
2069
2114
  this.pendingViewableListeners.delete(slotId);
@@ -2141,9 +2186,37 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2141
2186
  }
2142
2187
  return auctionMap;
2143
2188
  }
2144
- hasImpressionEmitted(slotId, refreshIndex, auctionId, creativeId) {
2189
+ nextSlotAdSession(slotId) {
2190
+ const next = (this.slotAdSessionCounters.get(slotId) ?? 0) + 1;
2191
+ this.slotAdSessionCounters.set(slotId, next);
2192
+ return `ad-session-${next}`;
2193
+ }
2194
+ hasImpressionEmitted(slotId, refreshIndex, auctionId, creativeId, adId) {
2145
2195
  const rIndex = refreshIndex ?? this.slotRefreshIndices.get(slotId) ?? 0;
2146
2196
  const baseSlotKey = `${escapeKeyPart(slotId)}:${rIndex}`;
2197
+ if (adId) {
2198
+ if (auctionId) {
2199
+ if (this.slotEmittedImpressionKeys.has(
2200
+ `${baseSlotKey}:auc:${escapeKeyPart(auctionId)}:ad:${escapeKeyPart(adId)}`
2201
+ ) || this.slotEmittedImpressionKeys.has(`${baseSlotKey}:ad:${escapeKeyPart(adId)}`)) {
2202
+ return true;
2203
+ }
2204
+ } else if (this.slotEmittedImpressionKeys.has(`${baseSlotKey}:ad:${escapeKeyPart(adId)}`)) {
2205
+ return true;
2206
+ }
2207
+ if (creativeId && creativeId !== adId) {
2208
+ if (auctionId) {
2209
+ if (this.slotEmittedImpressionKeys.has(
2210
+ `${baseSlotKey}:auc:${escapeKeyPart(auctionId)}:${escapeKeyPart(creativeId)}`
2211
+ ) || this.slotEmittedImpressionKeys.has(`${baseSlotKey}:${escapeKeyPart(creativeId)}`)) {
2212
+ return true;
2213
+ }
2214
+ } else if (this.slotEmittedImpressionKeys.has(`${baseSlotKey}:${escapeKeyPart(creativeId)}`)) {
2215
+ return true;
2216
+ }
2217
+ }
2218
+ return false;
2219
+ }
2147
2220
  if (creativeId) {
2148
2221
  if (auctionId) {
2149
2222
  return this.slotEmittedImpressionKeys.has(
@@ -2157,18 +2230,33 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2157
2230
  }
2158
2231
  return this.slotEmittedImpressionKeys.has(baseSlotKey);
2159
2232
  }
2160
- markImpressionEmitted(slotId, refreshIndex, auctionId, creativeId) {
2233
+ markImpressionEmitted(slotId, refreshIndex, auctionId, creativeId, adId) {
2161
2234
  const baseSlotKey = `${escapeKeyPart(slotId)}:${refreshIndex}`;
2162
- this.addImpressionKey(baseSlotKey);
2163
- if (creativeId) {
2164
- this.addImpressionKey(`${baseSlotKey}:${escapeKeyPart(creativeId)}`);
2165
- }
2166
- if (auctionId) {
2167
- this.addImpressionKey(`${baseSlotKey}:auc:${escapeKeyPart(auctionId)}`);
2168
- if (creativeId) {
2169
- this.addImpressionKey(
2170
- `${baseSlotKey}:auc:${escapeKeyPart(auctionId)}:${escapeKeyPart(creativeId)}`
2171
- );
2235
+ const hasIdentity = Boolean(adId || creativeId);
2236
+ if (hasIdentity) {
2237
+ if (adId) {
2238
+ this.addImpressionKey(`${baseSlotKey}:ad:${escapeKeyPart(adId)}`);
2239
+ if (auctionId) {
2240
+ this.addImpressionKey(
2241
+ `${baseSlotKey}:auc:${escapeKeyPart(auctionId)}:ad:${escapeKeyPart(adId)}`
2242
+ );
2243
+ }
2244
+ }
2245
+ if (creativeId && creativeId !== adId) {
2246
+ this.addImpressionKey(`${baseSlotKey}:${escapeKeyPart(creativeId)}`);
2247
+ if (auctionId) {
2248
+ this.addImpressionKey(
2249
+ `${baseSlotKey}:auc:${escapeKeyPart(auctionId)}:${escapeKeyPart(creativeId)}`
2250
+ );
2251
+ }
2252
+ }
2253
+ if (auctionId) {
2254
+ this.addImpressionKey(`${baseSlotKey}:auc:${escapeKeyPart(auctionId)}`);
2255
+ }
2256
+ } else {
2257
+ this.addImpressionKey(baseSlotKey);
2258
+ if (auctionId) {
2259
+ this.addImpressionKey(`${baseSlotKey}:auc:${escapeKeyPart(auctionId)}`);
2172
2260
  }
2173
2261
  }
2174
2262
  }
@@ -2181,6 +2269,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2181
2269
  const auctionId = options?.auctionId || rawBid.auctionId || cached?.auctionId || "";
2182
2270
  const transactionId = options?.transactionId || rawBid.transactionId || cached?.transactionId || "";
2183
2271
  const creativeId = rawBid.creativeId || cached?.bidTrace?.creativeId || options?.bid?.creativeId || "";
2272
+ const adId = options?.adId || rawBid.adId || options?.bid?.adId || "";
2184
2273
  const mediaType = options?.mediaType || rawBid.mediaType || cached?.bidTrace?.mediaType || "banner";
2185
2274
  const targetSlot = resolvedSlotId || adUnitCode;
2186
2275
  const rec = (resolvedSlotId ? this.slotViewabilityRecords.get(resolvedSlotId) : void 0) || (adUnitCode ? this.slotViewabilityRecords.get(adUnitCode) : void 0);
@@ -2221,7 +2310,13 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2221
2310
  }
2222
2311
  }
2223
2312
  const currentRefreshIndex = options?.refreshIndex ?? (resolvedSlotId ? this.slotRefreshIndices.get(resolvedSlotId) ?? (adUnitCode ? this.slotRefreshIndices.get(adUnitCode) : void 0) ?? (rec ? rec.refreshIndex : 0) : 0);
2224
- const alreadyEmitted = resolvedSlotId && this.hasImpressionEmitted(resolvedSlotId, currentRefreshIndex, auctionId, creativeId) || adUnitCode && adUnitCode !== resolvedSlotId && this.hasImpressionEmitted(adUnitCode, currentRefreshIndex, auctionId, creativeId);
2313
+ const alreadyEmitted = resolvedSlotId && this.hasImpressionEmitted(
2314
+ resolvedSlotId,
2315
+ currentRefreshIndex,
2316
+ auctionId,
2317
+ creativeId,
2318
+ adId
2319
+ ) || adUnitCode && adUnitCode !== resolvedSlotId && this.hasImpressionEmitted(adUnitCode, currentRefreshIndex, auctionId, creativeId, adId);
2225
2320
  if (alreadyEmitted) {
2226
2321
  this.log(
2227
2322
  "DEBUG",
@@ -2230,9 +2325,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2230
2325
  return false;
2231
2326
  }
2232
2327
  if (resolvedSlotId)
2233
- this.markImpressionEmitted(resolvedSlotId, currentRefreshIndex, auctionId, creativeId);
2328
+ this.markImpressionEmitted(resolvedSlotId, currentRefreshIndex, auctionId, creativeId, adId);
2234
2329
  if (adUnitCode && adUnitCode !== resolvedSlotId)
2235
- this.markImpressionEmitted(adUnitCode, currentRefreshIndex, auctionId, creativeId);
2330
+ this.markImpressionEmitted(adUnitCode, currentRefreshIndex, auctionId, creativeId, adId);
2236
2331
  this.enqueue(TraceEventType.IMPRESSION, "impression", {
2237
2332
  auctionId,
2238
2333
  transactionId,
@@ -2330,9 +2425,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2330
2425
  }
2331
2426
  }
2332
2427
  trackRawEvent(level, eventName, data) {
2333
- const eventType = EVENT_NAME_TO_TYPE[eventName] ?? (level === "ERROR" ? TraceEventType.ERROR : void 0);
2428
+ const eventType = LEVEL_TO_TYPE[level] ?? EVENT_NAME_TO_TYPE[eventName];
2334
2429
  if (eventType === void 0) return;
2335
- this.enqueue(eventType, eventName, data, level);
2430
+ this.enqueue(eventType, eventName, data);
2336
2431
  }
2337
2432
  /**
2338
2433
  * Record the wrapper's Live Floors decision for an auction and ad unit,
@@ -2371,6 +2466,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2371
2466
  navigate(pageviewId, pageUrl) {
2372
2467
  this.disable();
2373
2468
  this.slotRefreshIndices.clear();
2469
+ this.slotAdSessionCounters.clear();
2374
2470
  this.floorDecisions.clear();
2375
2471
  this.pendingThresholdListeners.clear();
2376
2472
  this.config.pageviewId = pageviewId || generateUUID();
@@ -2721,9 +2817,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2721
2817
  isDuplicate(eventName, data) {
2722
2818
  return this.deduper.isDuplicate(eventName, data);
2723
2819
  }
2724
- enqueue(type, eventName, data, level) {
2820
+ enqueue(type, eventName, data) {
2725
2821
  if (!this.isEnabled) return;
2726
- if (!this.shouldSample(type, level)) return;
2822
+ if (!this.shouldSample(type)) return;
2727
2823
  if (this.managesSessionId && sessionNeedsSync()) {
2728
2824
  this.config.sessionId = getOrCreateSessionId();
2729
2825
  }
@@ -2732,8 +2828,8 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2732
2828
  timestampMs: Date.now(),
2733
2829
  type,
2734
2830
  // Typed events have a fixed name that ingest derives from `type`; only
2735
- // ERROR events carry theirs, which names the failure.
2736
- eventName: type === TraceEventType.ERROR ? eventName : "",
2831
+ // ERROR and WARN carry theirs, which names the failure or condition.
2832
+ eventName: SELF_NAMING_TYPES.has(type) ? eventName : "",
2737
2833
  auctionId: idToBytes(String(data.auctionId || "")),
2738
2834
  transactionId: idToBytes(String(data.transactionId || "")),
2739
2835
  adUnitCode: data.adUnitCode || data.elementId || "",
@@ -2813,13 +2909,12 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2813
2909
  }, this.config.revenueFlushDelayMs);
2814
2910
  }
2815
2911
  }
2816
- shouldSample(type, level) {
2912
+ shouldSample(type) {
2817
2913
  if (type === TraceEventType.ERROR) {
2818
2914
  this.errorCount++;
2819
- if (this.errorCount > MAX_ERRORS_PER_SESSION) return false;
2820
- return this.config.errorsEnabled;
2915
+ return this.errorCount <= MAX_ERRORS_PER_SESSION;
2821
2916
  }
2822
- if (level === "WARN") {
2917
+ if (type === TraceEventType.WARN) {
2823
2918
  return this.config.warningsEnabled;
2824
2919
  }
2825
2920
  return this.config.auctionEnabled;
@@ -3074,10 +3169,6 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
3074
3169
  this.logger.log(level, msg, ...args);
3075
3170
  }
3076
3171
  };
3077
- var defaultLogger = createLogger({
3078
- prefix: "[analytics]",
3079
- logLevel: "INFO"
3080
- });
3081
3172
  function extractAnalyticsOptions(config, allowProviderless = true) {
3082
3173
  if (!config) return null;
3083
3174
  if (Array.isArray(config)) {
@@ -3600,9 +3691,29 @@ function attachImaAdsManager(analytics, adsManager, options) {
3600
3691
  return cached;
3601
3692
  };
3602
3693
  let adStarted = false;
3694
+ let activeAdSession = null;
3695
+ const mintAdSession = (initialAd) => {
3696
+ const nextSession = typeof self.nextSlotAdSession === "function" ? self.nextSlotAdSession(slotId) : `ad-session-${(self.slotAdSessionCounters?.get(slotId) ?? 0) + 1}`;
3697
+ if (self.slotAdSessionCounters && typeof self.nextSlotAdSession !== "function") {
3698
+ const c = (self.slotAdSessionCounters.get(slotId) ?? 0) + 1;
3699
+ self.slotAdSessionCounters.set(slotId, c);
3700
+ }
3701
+ const adId = (typeof initialAd?.getAdId === "function" ? initialAd.getAdId() : initialAd?.adId ?? initialAd?.id) || "";
3702
+ const creativeId = (typeof initialAd?.getCreativeId === "function" ? initialAd.getCreativeId() : initialAd?.creativeId) || "";
3703
+ activeAdSession = {
3704
+ sessionId: nextSession,
3705
+ adId: adId || void 0,
3706
+ creativeId: creativeId || void 0
3707
+ };
3708
+ return activeAdSession;
3709
+ };
3710
+ const onAdLoaded = (event) => {
3711
+ const ad = typeof event?.getAd === "function" ? event.getAd() : event?.ad;
3712
+ mintAdSession(ad);
3713
+ self.log("DEBUG", "IMA AdEvent.LOADED received", { slotId, activeAdSession });
3714
+ };
3603
3715
  const onAdStartedOrImpression = (event) => {
3604
3716
  adStarted = true;
3605
- self.log("DEBUG", "IMA AdEvent.STARTED / IMPRESSION received", event);
3606
3717
  const ad = typeof event?.getAd === "function" ? event.getAd() : event?.ad;
3607
3718
  const adData = {};
3608
3719
  if (ad) {
@@ -3612,15 +3723,28 @@ function attachImaAdsManager(analytics, adsManager, options) {
3612
3723
  adData.duration = typeof ad.getDuration === "function" ? ad.getDuration() : ad.duration;
3613
3724
  adData.advertiserName = typeof ad.getAdvertiserName === "function" ? ad.getAdvertiserName() : "";
3614
3725
  }
3726
+ if (!activeAdSession || adData.adId && activeAdSession.adId && activeAdSession.adId !== adData.adId) {
3727
+ mintAdSession(ad);
3728
+ } else {
3729
+ if (!activeAdSession.adId && adData.adId) {
3730
+ activeAdSession.adId = adData.adId;
3731
+ }
3732
+ if (!activeAdSession.creativeId && adData.creativeId) {
3733
+ activeAdSession.creativeId = adData.creativeId;
3734
+ }
3735
+ }
3736
+ const session = activeAdSession || mintAdSession(ad);
3615
3737
  const cached = getWinningBid(adData);
3616
3738
  const resolvedSlotId = options?.slotId && options.slotId !== "video" ? options.slotId : options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || options?.slotId || options?.adUnitCode || "video";
3617
3739
  const resolvedAdUnitCode = options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || resolvedSlotId;
3618
3740
  const resolvedAuctionId = auctionId || cached?.auctionId || "";
3619
3741
  const resolvedTransactionId = transactionId || cached?.transactionId || "";
3742
+ const creativeId = session.creativeId || adData.creativeId || cached?.bidTrace?.creativeId || options?.bid?.creativeId || "";
3743
+ const stableAdIdentity = session.adId || adData.adId || creativeId || session.sessionId;
3620
3744
  const mergedBid = {
3621
3745
  ...cached?.rawBid || options?.bid,
3622
3746
  mediaType: "video",
3623
- creativeId: adData.creativeId || cached?.bidTrace?.creativeId || options?.bid?.creativeId || ""
3747
+ creativeId
3624
3748
  };
3625
3749
  const emitted = self.recordImpression(resolvedSlotId, {
3626
3750
  adUnitCode: resolvedAdUnitCode,
@@ -3628,6 +3752,7 @@ function attachImaAdsManager(analytics, adsManager, options) {
3628
3752
  transactionId: resolvedTransactionId,
3629
3753
  mediaType: "video",
3630
3754
  bid: mergedBid,
3755
+ adId: stableAdIdentity,
3631
3756
  metadata: {
3632
3757
  ...options?.metadata,
3633
3758
  media_type: "video",
@@ -3635,6 +3760,16 @@ function attachImaAdsManager(analytics, adsManager, options) {
3635
3760
  ...Number.isFinite(adData.duration) ? { ad_duration_s: String(adData.duration) } : {}
3636
3761
  }
3637
3762
  });
3763
+ let rawType = typeof event?.type === "string" ? event.type : typeof event?.getType === "function" ? event.getType() : typeof event === "string" ? event : "";
3764
+ if (rawType.toLowerCase().startsWith("adevent.")) {
3765
+ rawType = rawType.slice(8);
3766
+ }
3767
+ const eventName = rawType ? rawType.toUpperCase() : "STARTED/IMPRESSION";
3768
+ self.log(
3769
+ "DEBUG",
3770
+ `IMA AdEvent.${eventName} received${emitted ? "" : " (second event for this ad, already counted)"}`,
3771
+ event
3772
+ );
3638
3773
  if (emitted && options?.onImpression) {
3639
3774
  try {
3640
3775
  options.onImpression(resolvedSlotId, { ad, bid: mergedBid });
@@ -3669,6 +3804,7 @@ function attachImaAdsManager(analytics, adsManager, options) {
3669
3804
  });
3670
3805
  };
3671
3806
  const onAdError = (event) => {
3807
+ activeAdSession = null;
3672
3808
  const cached = getWinningBid();
3673
3809
  const resolvedAdUnitCode = options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || slotId;
3674
3810
  const err = recordImaAdError(analytics, event, {
@@ -3691,6 +3827,7 @@ function attachImaAdsManager(analytics, adsManager, options) {
3691
3827
  const adEventType = googleIma?.AdEvent?.Type || {};
3692
3828
  const adErrorEventType = googleIma?.AdErrorEvent?.Type || {};
3693
3829
  const rawListeners = [
3830
+ { type: adEventType.LOADED || "loaded", handler: onAdLoaded },
3694
3831
  { type: adEventType.STARTED || "started", handler: onAdStartedOrImpression },
3695
3832
  { type: adEventType.IMPRESSION || "impression", handler: onAdStartedOrImpression },
3696
3833
  {
@@ -3702,7 +3839,19 @@ function attachImaAdsManager(analytics, adsManager, options) {
3702
3839
  type: adEventType.THIRD_QUARTILE || "thirdQuartile",
3703
3840
  handler: () => onMilestone("thirdQuartile")
3704
3841
  },
3705
- { type: adEventType.COMPLETE || "complete", handler: () => onMilestone("complete") },
3842
+ {
3843
+ type: adEventType.COMPLETE || "complete",
3844
+ handler: () => {
3845
+ activeAdSession = null;
3846
+ onMilestone("complete");
3847
+ }
3848
+ },
3849
+ {
3850
+ type: adEventType.ALL_ADS_COMPLETED || "allAdsCompleted",
3851
+ handler: () => {
3852
+ activeAdSession = null;
3853
+ }
3854
+ },
3706
3855
  { type: adEventType.CLICK || "click", handler: onAdClick },
3707
3856
  { type: adErrorEventType.AD_ERROR || "adError", handler: onAdError }
3708
3857
  ];
@@ -3721,6 +3870,7 @@ function attachImaAdsManager(analytics, adsManager, options) {
3721
3870
  }
3722
3871
  }
3723
3872
  const cleanup = () => {
3873
+ activeAdSession = null;
3724
3874
  attached.delete(analytics);
3725
3875
  for (const { type, handler } of listeners) {
3726
3876
  try {
@@ -3987,6 +4137,8 @@ function normalizeImaEventName(name) {
3987
4137
  return "volumeChanged";
3988
4138
  case "loaded":
3989
4139
  return "loaded";
4140
+ case "alladscompleted":
4141
+ return "allAdsCompleted";
3990
4142
  case "aderror":
3991
4143
  case "error":
3992
4144
  return "adError";
@@ -4102,6 +4254,7 @@ function getbidkernel(alias = "bidkernel") {
4102
4254
  BidkernelPrebidAnalytics,
4103
4255
  CACHED_BID_TTL_MS,
4104
4256
  ImaAdsManagerStub,
4257
+ LogLevel,
4105
4258
  PrebidEventDeduper,
4106
4259
  attachImaAdsManager,
4107
4260
  attachVideoPlayer,
@@ -4113,6 +4266,7 @@ function getbidkernel(alias = "bidkernel") {
4113
4266
  isSessionActive,
4114
4267
  isTrustedEndpoint,
4115
4268
  normalizeImaEventName,
4269
+ normalizeLogLevel,
4116
4270
  onSessionResume,
4117
4271
  registerPrebidAnalytics
4118
4272
  });