@bidkernel/analytics 0.17.0 → 0.19.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
@@ -327,7 +327,6 @@ var TraceEventType = {
327
327
  TRACE_EVENT_TYPE_UNSPECIFIED: 0,
328
328
  AUCTION_START: 1,
329
329
  AUCTION_END: 2,
330
- BID_RESPONSE: 3,
331
330
  BID_WIN: 4,
332
331
  /** IMPRESSION - ad rendered into DOM */
333
332
  IMPRESSION: 5,
@@ -358,14 +357,14 @@ var BidderOutcome = {
358
357
  };
359
358
  function createBaseTraceEventBatch() {
360
359
  return {
361
- propertyId: "",
362
- pageviewId: "",
363
- sessionId: "",
360
+ propertyId: new Uint8Array(0),
361
+ pageviewId: new Uint8Array(0),
362
+ sessionId: new Uint8Array(0),
364
363
  pageUrl: "",
365
364
  country: "",
366
365
  region: "",
367
366
  deviceType: "",
368
- userId: "",
367
+ userId: new Uint8Array(0),
369
368
  domain: "",
370
369
  events: [],
371
370
  browser: "",
@@ -377,14 +376,14 @@ function createBaseTraceEventBatch() {
377
376
  }
378
377
  var TraceEventBatch = {
379
378
  encode(message, writer = new import_wire.BinaryWriter()) {
380
- if (message.propertyId !== void 0 && message.propertyId !== "") {
381
- writer.uint32(10).string(message.propertyId);
379
+ if (message.propertyId !== void 0 && message.propertyId.length !== 0) {
380
+ writer.uint32(10).bytes(message.propertyId);
382
381
  }
383
- if (message.pageviewId !== void 0 && message.pageviewId !== "") {
384
- writer.uint32(18).string(message.pageviewId);
382
+ if (message.pageviewId !== void 0 && message.pageviewId.length !== 0) {
383
+ writer.uint32(18).bytes(message.pageviewId);
385
384
  }
386
- if (message.sessionId !== void 0 && message.sessionId !== "") {
387
- writer.uint32(26).string(message.sessionId);
385
+ if (message.sessionId !== void 0 && message.sessionId.length !== 0) {
386
+ writer.uint32(26).bytes(message.sessionId);
388
387
  }
389
388
  if (message.pageUrl !== void 0 && message.pageUrl !== "") {
390
389
  writer.uint32(34).string(message.pageUrl);
@@ -398,8 +397,8 @@ var TraceEventBatch = {
398
397
  if (message.deviceType !== void 0 && message.deviceType !== "") {
399
398
  writer.uint32(58).string(message.deviceType);
400
399
  }
401
- if (message.userId !== void 0 && message.userId !== "") {
402
- writer.uint32(66).string(message.userId);
400
+ if (message.userId !== void 0 && message.userId.length !== 0) {
401
+ writer.uint32(66).bytes(message.userId);
403
402
  }
404
403
  if (message.domain !== void 0 && message.domain !== "") {
405
404
  writer.uint32(74).string(message.domain);
@@ -437,21 +436,21 @@ var TraceEventBatch = {
437
436
  if (tag !== 10) {
438
437
  break;
439
438
  }
440
- message.propertyId = reader.string();
439
+ message.propertyId = reader.bytes();
441
440
  continue;
442
441
  }
443
442
  case 2: {
444
443
  if (tag !== 18) {
445
444
  break;
446
445
  }
447
- message.pageviewId = reader.string();
446
+ message.pageviewId = reader.bytes();
448
447
  continue;
449
448
  }
450
449
  case 3: {
451
450
  if (tag !== 26) {
452
451
  break;
453
452
  }
454
- message.sessionId = reader.string();
453
+ message.sessionId = reader.bytes();
455
454
  continue;
456
455
  }
457
456
  case 4: {
@@ -486,7 +485,7 @@ var TraceEventBatch = {
486
485
  if (tag !== 66) {
487
486
  break;
488
487
  }
489
- message.userId = reader.string();
488
+ message.userId = reader.bytes();
490
489
  continue;
491
490
  }
492
491
  case 9: {
@@ -555,12 +554,12 @@ function createBaseTraceEvent() {
555
554
  timestampMs: 0,
556
555
  type: 0,
557
556
  eventName: "",
558
- auctionId: "",
559
- transactionId: "",
557
+ auctionId: new Uint8Array(0),
558
+ transactionId: new Uint8Array(0),
560
559
  adUnitCode: "",
561
560
  bid: void 0,
562
561
  namespace: "",
563
- eventId: "",
562
+ eventId: new Uint8Array(0),
564
563
  metadata: {},
565
564
  viewableDurationMs: void 0,
566
565
  bidderOutcomes: []
@@ -577,11 +576,11 @@ var TraceEvent = {
577
576
  if (message.eventName !== void 0 && message.eventName !== "") {
578
577
  writer.uint32(26).string(message.eventName);
579
578
  }
580
- if (message.auctionId !== void 0 && message.auctionId !== "") {
581
- writer.uint32(34).string(message.auctionId);
579
+ if (message.auctionId !== void 0 && message.auctionId.length !== 0) {
580
+ writer.uint32(34).bytes(message.auctionId);
582
581
  }
583
- if (message.transactionId !== void 0 && message.transactionId !== "") {
584
- writer.uint32(42).string(message.transactionId);
582
+ if (message.transactionId !== void 0 && message.transactionId.length !== 0) {
583
+ writer.uint32(42).bytes(message.transactionId);
585
584
  }
586
585
  if (message.adUnitCode !== void 0 && message.adUnitCode !== "") {
587
586
  writer.uint32(50).string(message.adUnitCode);
@@ -592,8 +591,8 @@ var TraceEvent = {
592
591
  if (message.namespace !== void 0 && message.namespace !== "") {
593
592
  writer.uint32(66).string(message.namespace);
594
593
  }
595
- if (message.eventId !== void 0 && message.eventId !== "") {
596
- writer.uint32(74).string(message.eventId);
594
+ if (message.eventId !== void 0 && message.eventId.length !== 0) {
595
+ writer.uint32(74).bytes(message.eventId);
597
596
  }
598
597
  globalThis.Object.entries(message.metadata || {}).forEach(([key, value]) => {
599
598
  TraceEvent_MetadataEntry.encode({ key, value }, writer.uint32(82).fork()).join();
@@ -640,14 +639,14 @@ var TraceEvent = {
640
639
  if (tag !== 34) {
641
640
  break;
642
641
  }
643
- message.auctionId = reader.string();
642
+ message.auctionId = reader.bytes();
644
643
  continue;
645
644
  }
646
645
  case 5: {
647
646
  if (tag !== 42) {
648
647
  break;
649
648
  }
650
- message.transactionId = reader.string();
649
+ message.transactionId = reader.bytes();
651
650
  continue;
652
651
  }
653
652
  case 6: {
@@ -675,7 +674,7 @@ var TraceEvent = {
675
674
  if (tag !== 74) {
676
675
  break;
677
676
  }
678
- message.eventId = reader.string();
677
+ message.eventId = reader.bytes();
679
678
  continue;
680
679
  }
681
680
  case 10: {
@@ -758,24 +757,18 @@ var TraceEvent_MetadataEntry = {
758
757
  }
759
758
  };
760
759
  function createBaseBidderOutcomeEntry() {
761
- return { bidder: "", adUnitCode: "", mediaType: "", outcome: 0, latencyMs: 0 };
760
+ return { adUnitCode: "", outcome: 0, bid: void 0 };
762
761
  }
763
762
  var BidderOutcomeEntry = {
764
763
  encode(message, writer = new import_wire.BinaryWriter()) {
765
- if (message.bidder !== void 0 && message.bidder !== "") {
766
- writer.uint32(10).string(message.bidder);
767
- }
768
764
  if (message.adUnitCode !== void 0 && message.adUnitCode !== "") {
769
765
  writer.uint32(18).string(message.adUnitCode);
770
766
  }
771
- if (message.mediaType !== void 0 && message.mediaType !== "") {
772
- writer.uint32(26).string(message.mediaType);
773
- }
774
767
  if (message.outcome !== void 0 && message.outcome !== 0) {
775
768
  writer.uint32(32).int32(message.outcome);
776
769
  }
777
- if (message.latencyMs !== void 0 && message.latencyMs !== 0) {
778
- writer.uint32(41).double(message.latencyMs);
770
+ if (message.bid !== void 0) {
771
+ BidTrace.encode(message.bid, writer.uint32(50).fork()).join();
779
772
  }
780
773
  return writer;
781
774
  },
@@ -786,13 +779,6 @@ var BidderOutcomeEntry = {
786
779
  while (reader.pos < end) {
787
780
  const tag = reader.uint32();
788
781
  switch (tag >>> 3) {
789
- case 1: {
790
- if (tag !== 10) {
791
- break;
792
- }
793
- message.bidder = reader.string();
794
- continue;
795
- }
796
782
  case 2: {
797
783
  if (tag !== 18) {
798
784
  break;
@@ -800,13 +786,6 @@ var BidderOutcomeEntry = {
800
786
  message.adUnitCode = reader.string();
801
787
  continue;
802
788
  }
803
- case 3: {
804
- if (tag !== 26) {
805
- break;
806
- }
807
- message.mediaType = reader.string();
808
- continue;
809
- }
810
789
  case 4: {
811
790
  if (tag !== 32) {
812
791
  break;
@@ -814,11 +793,11 @@ var BidderOutcomeEntry = {
814
793
  message.outcome = reader.int32();
815
794
  continue;
816
795
  }
817
- case 5: {
818
- if (tag !== 41) {
796
+ case 6: {
797
+ if (tag !== 50) {
819
798
  break;
820
799
  }
821
- message.latencyMs = reader.double();
800
+ message.bid = BidTrace.decode(reader, reader.uint32());
822
801
  continue;
823
802
  }
824
803
  }
@@ -965,8 +944,28 @@ var BidTrace = {
965
944
  }
966
945
  };
967
946
 
947
+ // src/ids.ts
948
+ var CANONICAL_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
949
+ var UUID_BYTES = 16;
950
+ var utf8Encoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
951
+ var utf8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder() : null;
952
+ function idToBytes(id) {
953
+ if (!id) return new Uint8Array(0);
954
+ if (CANONICAL_UUID.test(id)) {
955
+ const hex = id.replace(/-/g, "");
956
+ const out2 = new Uint8Array(UUID_BYTES);
957
+ for (let i = 0; i < UUID_BYTES; i++) {
958
+ out2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
959
+ }
960
+ return out2;
961
+ }
962
+ if (utf8Encoder) return utf8Encoder.encode(id);
963
+ const out = new Uint8Array(id.length);
964
+ for (let i = 0; i < id.length; i++) out[i] = id.charCodeAt(i) & 255;
965
+ return out;
966
+ }
967
+
968
968
  // src/prebid-analytics.ts
969
- var BATCH_SIZE = 20;
970
969
  var FLUSH_INTERVAL_MS = 1e4;
971
970
  var MAX_ERRORS_PER_SESSION = 50;
972
971
  var MAX_QUEUE_SIZE = 200;
@@ -983,7 +982,6 @@ var PENDING_BATCH_CLEANUP_DELAY_MS = 1e4;
983
982
  var EVENT_NAME_TO_TYPE = {
984
983
  auctionStart: TraceEventType.AUCTION_START,
985
984
  auctionEnd: TraceEventType.AUCTION_END,
986
- bidResponse: TraceEventType.BID_RESPONSE,
987
985
  bidWin: TraceEventType.BID_WIN,
988
986
  adRenderFailed: TraceEventType.AD_RENDER_FAILED,
989
987
  click: TraceEventType.CLICK,
@@ -2243,7 +2241,8 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2243
2241
  }
2244
2242
  }
2245
2243
  trackRawEvent(level, eventName, data) {
2246
- const eventType = EVENT_NAME_TO_TYPE[eventName] ?? (level === "ERROR" ? TraceEventType.ERROR : TraceEventType.TRACE_EVENT_TYPE_UNSPECIFIED);
2244
+ const eventType = EVENT_NAME_TO_TYPE[eventName] ?? (level === "ERROR" ? TraceEventType.ERROR : void 0);
2245
+ if (eventType === void 0) return;
2247
2246
  this.enqueue(eventType, eventName, data, level);
2248
2247
  }
2249
2248
  setUserId(userId) {
@@ -2314,11 +2313,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2314
2313
  const key = `${bidder}:${adUnitCode}`;
2315
2314
  if (!auctionMap.has(key)) {
2316
2315
  auctionMap.set(key, {
2317
- bidder,
2318
2316
  adUnitCode,
2319
- mediaType,
2320
2317
  outcome: BidderOutcome.BIDDER_OUTCOME_NO_RESPONSE,
2321
- latencyMs: 0
2318
+ bid: { bidder, mediaType, latencyMs: 0 }
2322
2319
  });
2323
2320
  }
2324
2321
  });
@@ -2334,43 +2331,23 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2334
2331
  const latencyMs = Number.isFinite(data.timeToRespond) ? data.timeToRespond : 0;
2335
2332
  const resMediaTypes = Object.keys(data.mediaTypes || {});
2336
2333
  const mediaType = data.mediaType || (data.mediaTypes?.video ? "video" : resMediaTypes.length > 0 ? resMediaTypes[0] : "banner");
2337
- if (auctionId && bidder) {
2338
- const auctionMap = this.getOrCreateAuctionOutcomes(auctionId);
2339
- const key = `${bidder}:${adUnitCode}`;
2340
- const entry = auctionMap.get(key);
2341
- const outcome = cpm > 0 ? BidderOutcome.BIDDER_OUTCOME_BID : BidderOutcome.BIDDER_OUTCOME_NO_BID;
2342
- if (entry) {
2343
- entry.outcome = outcome;
2344
- entry.latencyMs = latencyMs;
2345
- if (mediaType) entry.mediaType = mediaType;
2346
- } else {
2347
- auctionMap.set(key, {
2348
- bidder,
2349
- adUnitCode,
2350
- mediaType,
2351
- outcome,
2352
- latencyMs
2353
- });
2354
- }
2355
- }
2356
- if (cpm > 0) {
2357
- this.enqueue(TraceEventType.BID_RESPONSE, "bidResponse", {
2358
- auctionId,
2359
- transactionId: data.transactionId || "",
2360
- adUnitCode,
2361
- bid: {
2362
- bidder,
2363
- cpm,
2364
- currency: data.originalCurrency ?? data.currency ?? "USD",
2365
- ...parseBidDimensions(data),
2366
- dealId: data.dealId || "",
2367
- mediaType,
2368
- latencyMs,
2369
- advertiserDomain: data.meta?.advertiserDomains?.[0] || "",
2370
- creativeId: data.creativeId || ""
2371
- }
2372
- });
2373
- }
2334
+ if (!auctionId || !bidder) return;
2335
+ const bid = cpm > 0 ? {
2336
+ bidder,
2337
+ cpm,
2338
+ currency: data.originalCurrency ?? data.currency ?? "USD",
2339
+ ...parseBidDimensions(data),
2340
+ dealId: data.dealId || "",
2341
+ mediaType,
2342
+ latencyMs,
2343
+ advertiserDomain: data.meta?.advertiserDomains?.[0] || "",
2344
+ creativeId: data.creativeId || ""
2345
+ } : { bidder, mediaType, latencyMs };
2346
+ this.getOrCreateAuctionOutcomes(auctionId).set(`${bidder}:${adUnitCode}`, {
2347
+ adUnitCode,
2348
+ outcome: cpm > 0 ? BidderOutcome.BIDDER_OUTCOME_BID : BidderOutcome.BIDDER_OUTCOME_NO_BID,
2349
+ bid
2350
+ });
2374
2351
  }
2375
2352
  handleBidTimeout(data) {
2376
2353
  if (this.isDuplicate("bidTimeout", data)) return;
@@ -2387,14 +2364,12 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2387
2364
  const entry = auctionMap.get(key);
2388
2365
  if (entry) {
2389
2366
  entry.outcome = BidderOutcome.BIDDER_OUTCOME_TIMEOUT;
2390
- if (latencyMs > 0) entry.latencyMs = latencyMs;
2367
+ if (latencyMs > 0 && entry.bid) entry.bid.latencyMs = latencyMs;
2391
2368
  } else {
2392
2369
  auctionMap.set(key, {
2393
- bidder,
2394
2370
  adUnitCode,
2395
- mediaType: "banner",
2396
2371
  outcome: BidderOutcome.BIDDER_OUTCOME_TIMEOUT,
2397
- latencyMs
2372
+ bid: { bidder, mediaType: "banner", latencyMs }
2398
2373
  });
2399
2374
  }
2400
2375
  }
@@ -2463,11 +2438,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2463
2438
  }
2464
2439
  } else {
2465
2440
  auctionMap.set(key, {
2466
- bidder,
2467
2441
  adUnitCode,
2468
- mediaType: "banner",
2469
2442
  outcome: BidderOutcome.BIDDER_OUTCOME_NO_BID,
2470
- latencyMs: 0
2443
+ bid: { bidder, mediaType: "banner", latencyMs: 0 }
2471
2444
  });
2472
2445
  }
2473
2446
  }
@@ -2630,12 +2603,14 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2630
2603
  if (!this.shouldSample(type, level)) return;
2631
2604
  extendSession();
2632
2605
  const protoEvent = {
2633
- eventId: generateUUID(),
2606
+ eventId: idToBytes(generateUUID()),
2634
2607
  timestampMs: Date.now(),
2635
2608
  type,
2636
- eventName,
2637
- auctionId: data.auctionId || "",
2638
- transactionId: data.transactionId || "",
2609
+ // Typed events have a fixed name that ingest derives from `type`; only
2610
+ // ERROR events carry theirs, which names the failure.
2611
+ eventName: type === TraceEventType.ERROR ? eventName : "",
2612
+ auctionId: idToBytes(String(data.auctionId || "")),
2613
+ transactionId: idToBytes(String(data.transactionId || "")),
2639
2614
  adUnitCode: data.adUnitCode || data.elementId || "",
2640
2615
  namespace: data.ns || data.namespace || ""
2641
2616
  };
@@ -2643,9 +2618,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2643
2618
  protoEvent.bid = {
2644
2619
  bidder: data.bid.bidder || "",
2645
2620
  cpm: Number.isFinite(data.bid.cpm) ? data.bid.cpm : 0,
2646
- // No defaults here: handlers with a priced bid (bidResponse, bidWon,
2647
- // impression) set currency/mediaType themselves. Defaulting for the
2648
- // rest would stamp fake "USD"/"banner" on noBid and bidRequest rows.
2621
+ // No defaults here: handlers with a priced bid (bidWon, impression)
2622
+ // set currency/mediaType themselves. Defaulting for the rest would
2623
+ // stamp fake "USD"/"banner" on rows that carried no bid.
2649
2624
  currency: data.bid.currency || "",
2650
2625
  width: Number.isFinite(data.bid.width) ? data.bid.width : 0,
2651
2626
  height: Number.isFinite(data.bid.height) ? data.bid.height : 0,
@@ -2677,11 +2652,11 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2677
2652
  protoEvent.metadata = boundedMetadata;
2678
2653
  }
2679
2654
  this.queue.push(protoEvent);
2680
- if (this.queue.length > MAX_QUEUE_SIZE) {
2681
- this.queue.splice(0, this.queue.length - MAX_QUEUE_SIZE);
2682
- }
2683
- if (this.queue.length >= BATCH_SIZE) {
2655
+ if (this.queue.length >= MAX_QUEUE_SIZE) {
2684
2656
  this.flush();
2657
+ if (this.queue.length > MAX_QUEUE_SIZE) {
2658
+ this.queue.splice(0, this.queue.length - MAX_QUEUE_SIZE);
2659
+ }
2685
2660
  } else if (REVENUE_FLUSH_TYPES.has(type) && this.revenueFlushTimer === null) {
2686
2661
  this.revenueFlushTimer = setTimeout(() => {
2687
2662
  this.revenueFlushTimer = null;
@@ -2713,14 +2688,14 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2713
2688
  if (this.queue.length === 0 || !this.config.endpoint) return null;
2714
2689
  const domain = typeof window !== "undefined" ? window.location.hostname : "";
2715
2690
  const buildBatch = (evts) => ({
2716
- propertyId: this.config.propertyId,
2717
- pageviewId: this.config.pageviewId,
2718
- sessionId: this.config.sessionId,
2691
+ propertyId: idToBytes(this.config.propertyId),
2692
+ pageviewId: idToBytes(this.config.pageviewId),
2693
+ sessionId: idToBytes(this.config.sessionId),
2719
2694
  pageUrl: this.pageUrl,
2720
2695
  country: this.config.country,
2721
2696
  region: this.config.region,
2722
2697
  deviceType: this.config.deviceType,
2723
- userId: this.config.userId,
2698
+ userId: idToBytes(this.config.userId),
2724
2699
  domain,
2725
2700
  events: evts
2726
2701
  });
@@ -2740,7 +2715,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
2740
2715
  const [dropped] = this.queue.splice(0, 1);
2741
2716
  this.log(
2742
2717
  "WARN",
2743
- `Dropping oversized event ${dropped?.eventName || dropped?.eventId} (${encoded.byteLength} bytes exceeds the ${MAX_PAYLOAD_BYTES}-byte cap on its own)`
2718
+ `Dropping oversized event (type ${dropped?.type}, ${encoded.byteLength} bytes exceeds the ${MAX_PAYLOAD_BYTES}-byte cap on its own)`
2744
2719
  );
2745
2720
  continue;
2746
2721
  }
@@ -3066,6 +3041,62 @@ function registerPrebidAnalytics(pbjsGlobalName = "pbjs", defaults) {
3066
3041
  // src/video.ts
3067
3042
  var internals = (analytics) => analytics;
3068
3043
  var adsLoaderListenerMap = /* @__PURE__ */ new WeakMap();
3044
+ var adsLoadersWithErrorListener = /* @__PURE__ */ new WeakSet();
3045
+ function describeImaError(event) {
3046
+ const err = typeof event?.getError === "function" ? event.getError() : event?.error || event;
3047
+ const call = (name) => err && typeof err[name] === "function" ? err[name]() : void 0;
3048
+ const message = call("getMessage") || err?.message || String(err || "IMA ad error");
3049
+ const code = call("getErrorCode") ?? err?.code;
3050
+ const vastCode = call("getVastErrorCode");
3051
+ const type = call("getType") ?? err?.type;
3052
+ const metadata = { message };
3053
+ if (code) metadata.error_code = String(code);
3054
+ if (vastCode) metadata.vast_error_code = String(vastCode);
3055
+ if (type) metadata.error_type = String(type);
3056
+ return { err, message, metadata };
3057
+ }
3058
+ function recordImaAdError(analytics, event, ctx) {
3059
+ const self = internals(analytics);
3060
+ const { err, message, metadata } = describeImaError(event);
3061
+ self.log("WARN", "IMA AdErrorEvent received", event);
3062
+ self.enqueue(TraceEventType.AD_RENDER_FAILED, "adRenderFailed", {
3063
+ auctionId: ctx.auctionId,
3064
+ transactionId: ctx.transactionId,
3065
+ adUnitCode: ctx.adUnitCode,
3066
+ bid: ctx.bid,
3067
+ metadata: {
3068
+ ...ctx.metadata,
3069
+ reason: ctx.adStarted ? "ima_playback_error" : "ima_ad_error",
3070
+ playback_phase: ctx.adStarted ? "post_start" : "pre_start",
3071
+ ...metadata
3072
+ },
3073
+ error: typeof err === "object" ? err : new Error(message)
3074
+ });
3075
+ return err;
3076
+ }
3077
+ function ensureAdsLoaderErrorListener(loader, addEventListener) {
3078
+ if (!loader || typeof loader !== "object" || adsLoadersWithErrorListener.has(loader)) return;
3079
+ adsLoadersWithErrorListener.add(loader);
3080
+ const type = typeof window !== "undefined" && window.google?.ima?.AdErrorEvent?.Type?.AD_ERROR || "adError";
3081
+ try {
3082
+ addEventListener.call(loader, type, (event) => {
3083
+ for (const instance of BidkernelPrebidAnalytics.getActiveInstances()) {
3084
+ try {
3085
+ const cached = findCachedWinningBid(instance, { mediaType: "video" });
3086
+ recordImaAdError(instance, event, {
3087
+ adStarted: false,
3088
+ adUnitCode: cached?.adUnitCode || "video",
3089
+ auctionId: cached?.auctionId,
3090
+ transactionId: cached?.transactionId,
3091
+ bid: cached?.bidTrace
3092
+ });
3093
+ } catch {
3094
+ }
3095
+ }
3096
+ });
3097
+ } catch {
3098
+ }
3099
+ }
3069
3100
  function hookAdsManagerLoadedEvent(loadedEventCtor) {
3070
3101
  if (!loadedEventCtor) return;
3071
3102
  try {
@@ -3133,6 +3164,7 @@ function hookAdsLoader(adsLoaderCtor) {
3133
3164
  if (typeof proto.addEventListener === "function" && !proto.addEventListener.__bidkernelHooked) {
3134
3165
  const origAddEventListener = proto.addEventListener;
3135
3166
  const hookedAddEventListener = function(type, listener, ...rest) {
3167
+ ensureAdsLoaderErrorListener(this, origAddEventListener);
3136
3168
  if ((type === "adsManagerLoaded" || type === (this?.AdsManagerLoadedEvent?.Type?.ADS_MANAGER_LOADED || "adsManagerLoaded")) && typeof listener === "function") {
3137
3169
  let wrappedListener = adsLoaderListenerMap.get(listener);
3138
3170
  if (!wrappedListener) {
@@ -3488,25 +3520,15 @@ function attachImaAdsManager(analytics, adsManager, options) {
3488
3520
  });
3489
3521
  };
3490
3522
  const onAdError = (event) => {
3491
- self.log("WARN", "IMA AdErrorEvent received", event);
3492
- const err = typeof event?.getError === "function" ? event.getError() : event?.error || event;
3493
- const msg = (err && typeof err.getMessage === "function" ? err.getMessage() : err?.message) || String(err || "IMA ad error");
3494
- const code = (err && typeof err.getErrorCode === "function" ? err.getErrorCode() : err?.code) || "";
3495
3523
  const cached = getWinningBid();
3496
3524
  const resolvedAdUnitCode = options?.adUnitCode && options.adUnitCode !== "video" ? options.adUnitCode : cached?.adUnitCode || slotId;
3497
- self.enqueue(TraceEventType.AD_RENDER_FAILED, "adRenderFailed", {
3525
+ const err = recordImaAdError(analytics, event, {
3526
+ adStarted,
3527
+ adUnitCode: resolvedAdUnitCode,
3498
3528
  auctionId: auctionId || cached?.auctionId,
3499
3529
  transactionId: transactionId || cached?.transactionId,
3500
- adUnitCode: resolvedAdUnitCode,
3501
3530
  bid: cached?.bidTrace || options?.bid,
3502
- metadata: {
3503
- ...options?.metadata,
3504
- reason: adStarted ? "ima_playback_error" : "ima_ad_error",
3505
- playback_phase: adStarted ? "post_start" : "pre_start",
3506
- message: msg,
3507
- ...code ? { ima_error_code: String(code) } : {}
3508
- },
3509
- error: typeof err === "object" ? err : new Error(msg)
3531
+ metadata: options?.metadata
3510
3532
  });
3511
3533
  if (options?.onError) {
3512
3534
  try {
@@ -3686,7 +3708,7 @@ function attachVideoPlayer(analytics, target, options) {
3686
3708
  ...options?.metadata,
3687
3709
  reason: "html5_video_error",
3688
3710
  message: msg,
3689
- ...err?.code ? { video_error_code: String(err.code) } : {}
3711
+ ...err?.code ? { error_code: String(err.code) } : {}
3690
3712
  },
3691
3713
  error: err ? new Error(msg) : void 0
3692
3714
  });