stormcloud-video-player 0.8.59 → 0.8.61

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.
Files changed (82) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1369 -1369
  3. package/dist/stormcloud-vp.min.js +3 -1
  4. package/lib/Player.cjs +548 -0
  5. package/lib/Player.cjs.map +1 -0
  6. package/lib/Player.d.cts +146 -0
  7. package/lib/{index.js → StormcloudPlayer.cjs} +1193 -1908
  8. package/lib/StormcloudPlayer.cjs.map +1 -0
  9. package/lib/{index.d.ts → StormcloudPlayer.d.cts} +7 -400
  10. package/lib/index.cjs +1064 -280
  11. package/lib/index.cjs.map +1 -1
  12. package/lib/index.d.cts +18 -4032
  13. package/lib/patterns.cjs +111 -0
  14. package/lib/patterns.cjs.map +1 -0
  15. package/lib/patterns.d.cts +14 -0
  16. package/lib/player/AdBreakOrchestrator.cjs +51 -16
  17. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  18. package/lib/player/AdBreakOrchestrator.d.cts +3 -1
  19. package/lib/player/AdConfigManager.cjs +206 -26
  20. package/lib/player/AdConfigManager.cjs.map +1 -1
  21. package/lib/player/AdConfigManager.d.cts +1 -1
  22. package/lib/player/AdTimingService.cjs.map +1 -1
  23. package/lib/player/AdTimingService.d.cts +1 -1
  24. package/lib/player/HlsEngine.cjs.map +1 -1
  25. package/lib/player/HlsEngine.d.cts +1 -1
  26. package/lib/player/PlaceholderLayer.cjs.map +1 -1
  27. package/lib/player/PlayerControls.cjs.map +1 -1
  28. package/lib/player/PlayerControls.d.cts +1 -1
  29. package/lib/player/Scte35CueManager.cjs.map +1 -1
  30. package/lib/player/Scte35CueManager.d.cts +1 -1
  31. package/lib/player/Scte35Parser.cjs.map +1 -1
  32. package/lib/player/Scte35Parser.d.cts +1 -1
  33. package/lib/player/StormcloudVideoPlayer.cjs +1060 -278
  34. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  35. package/lib/player/StormcloudVideoPlayer.d.cts +1 -1
  36. package/lib/player/playerTypes.cjs.map +1 -1
  37. package/lib/player/playerTypes.d.cts +1 -1
  38. package/lib/players/FilePlayer.cjs.map +1 -1
  39. package/lib/players/HlsPlayer.cjs +1060 -278
  40. package/lib/players/HlsPlayer.cjs.map +1 -1
  41. package/lib/players/HlsPlayer.d.cts +1 -1
  42. package/lib/players/index.cjs +1060 -278
  43. package/lib/players/index.cjs.map +1 -1
  44. package/lib/props.cjs +186 -0
  45. package/lib/props.cjs.map +1 -0
  46. package/lib/props.d.cts +62 -0
  47. package/lib/sdk/hlsAdPlayer.cjs +884 -234
  48. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  49. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  50. package/lib/sdk/pal.cjs +9 -5
  51. package/lib/sdk/pal.cjs.map +1 -1
  52. package/lib/sdk/pal.d.cts +1 -0
  53. package/lib/types.cjs +49 -0
  54. package/lib/types.cjs.map +1 -0
  55. package/lib/{types-52ASml2N.d.cts → types.d.cts} +48 -1
  56. package/lib/ui/StormcloudVideoPlayer.cjs +1064 -280
  57. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  58. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  59. package/lib/utils/browserCompat.cjs.map +1 -1
  60. package/lib/utils/ctvVastSignals.cjs +178 -19
  61. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  62. package/lib/utils/devUrl.cjs.map +1 -1
  63. package/lib/utils/polyfills.cjs.map +1 -1
  64. package/lib/utils/tracking.cjs +45 -16
  65. package/lib/utils/tracking.cjs.map +1 -1
  66. package/lib/utils/tracking.d.cts +1 -1
  67. package/lib/utils/trackingIngest.cjs.map +1 -1
  68. package/lib/utils/vastEnvironmentSignals.cjs +192 -20
  69. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
  70. package/lib/utils/vastEnvironmentSignals.d.cts +13 -2
  71. package/lib/utils/vastMacros.cjs +50 -4
  72. package/lib/utils/vastMacros.cjs.map +1 -1
  73. package/lib/utils/vastMacros.d.cts +2 -0
  74. package/lib/utils/vastTrackingMacros.cjs +5 -0
  75. package/lib/utils/vastTrackingMacros.cjs.map +1 -1
  76. package/lib/utils/vastTrackingMacros.d.cts +2 -0
  77. package/lib/utils.cjs +292 -0
  78. package/lib/utils.cjs.map +1 -0
  79. package/lib/utils.d.cts +17 -0
  80. package/package.json +91 -91
  81. package/rollup.config.js +90 -90
  82. package/lib/index.js.map +0 -1
@@ -602,6 +602,7 @@ var KNOWN_VAST_MACROS = /* @__PURE__ */ new Set([
602
602
  "PLAYERSIZE",
603
603
  "PLAYERSTATE",
604
604
  "PODSEQUENCE",
605
+ "REASON",
605
606
  "REGULATIONS",
606
607
  "SERVERSIDE",
607
608
  "SERVERUA",
@@ -660,6 +661,10 @@ function resolveMacroValues(ctx) {
660
661
  if (ctx.podSequence != null) {
661
662
  set("PODSEQUENCE", String(ctx.podSequence));
662
663
  }
664
+ set("ADSERVINGID", ctx.adServingId);
665
+ if (ctx.reason != null && ctx.reason !== "") {
666
+ set("REASON", String(ctx.reason));
667
+ }
663
668
  return values;
664
669
  }
665
670
  function substituteVastTrackingMacros(url) {
@@ -676,10 +681,72 @@ function substituteVastTrackingMacros(url) {
676
681
  });
677
682
  }
678
683
  // src/sdk/hlsAdPlayer.ts
684
+ var LINEAR_TRACKING_EVENTS = [
685
+ "creativeView",
686
+ "loaded",
687
+ "start",
688
+ "firstQuartile",
689
+ "midpoint",
690
+ "thirdQuartile",
691
+ "complete",
692
+ "mute",
693
+ "unmute",
694
+ "pause",
695
+ "resume",
696
+ "fullscreen",
697
+ "exitFullscreen",
698
+ "playerExpand",
699
+ "playerCollapse",
700
+ "notUsed"
701
+ ];
702
+ function textOf(el) {
703
+ var _el_textContent;
704
+ var value = el === null || el === void 0 ? void 0 : (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
705
+ return value ? value : void 0;
706
+ }
707
+ function parseVastTime(value) {
708
+ if (!value) return void 0;
709
+ var parts = value.trim().split(":");
710
+ if (parts.length !== 3) return void 0;
711
+ var _parts_map = _sliced_to_array(parts.map(function(p) {
712
+ return parseFloat(p);
713
+ }), 3), h = _parts_map[0], m = _parts_map[1], s = _parts_map[2];
714
+ if (![
715
+ h,
716
+ m,
717
+ s
718
+ ].every(function(n) {
719
+ return n !== void 0 && Number.isFinite(n);
720
+ })) {
721
+ return void 0;
722
+ }
723
+ return h * 3600 + m * 60 + s;
724
+ }
725
+ function parseProgressOffset(offset) {
726
+ if (!offset) return void 0;
727
+ var trimmed = offset.trim();
728
+ if (trimmed.endsWith("%")) {
729
+ var percent = parseFloat(trimmed);
730
+ return Number.isFinite(percent) ? {
731
+ offsetPercent: percent
732
+ } : void 0;
733
+ }
734
+ var seconds = parseVastTime(trimmed);
735
+ return seconds !== void 0 ? {
736
+ offsetSeconds: seconds
737
+ } : void 0;
738
+ }
679
739
  var MAX_VAST_WRAPPER_DEPTH = 5;
680
740
  var BEACON_TIMEOUT_MS = 3e4;
681
741
  var inFlightBeacons = /* @__PURE__ */ new Set();
682
742
  var VAST_ERROR_MEDIA_DISPLAY = 405;
743
+ var VAST_ERROR_WRAPPER_TIMEOUT = 301;
744
+ var VAST_ERROR_WRAPPER_LIMIT = 302;
745
+ var VAST_ERROR_WRAPPER_NO_ADS = 303;
746
+ var VAST_ERROR_NO_SUPPORTED_MEDIA = 403;
747
+ var VERIFICATION_NOT_SUPPORTED_REASON = 2;
748
+ var VIEWABLE_MIN_VISIBLE_RATIO = 0.5;
749
+ var VIEWABLE_MIN_CONTINUOUS_S = 2;
683
750
  function toVastMediaErrorCode(error) {
684
751
  switch(error === null || error === void 0 ? void 0 : error.code){
685
752
  case 1:
@@ -707,6 +774,7 @@ function createHlsAdPlayer(contentVideo, options) {
707
774
  var adHls;
708
775
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
709
776
  var adEventHandlers = [];
777
+ var containerHandlers = [];
710
778
  var currentAd;
711
779
  var currentAdMediaFile;
712
780
  var podAds = [];
@@ -724,14 +792,28 @@ function createHlsAdPlayer(contentVideo, options) {
724
792
  var sawDecodedVideoFrame = false;
725
793
  var videoFrameCallbackHandle;
726
794
  var pendingPlayPromise;
727
- var trackingFired = {
728
- impression: false,
729
- start: false,
730
- firstQuartile: false,
731
- midpoint: false,
732
- thirdQuartile: false,
733
- complete: false
734
- };
795
+ function createTrackingState() {
796
+ return {
797
+ impression: false,
798
+ loaded: false,
799
+ start: false,
800
+ firstQuartile: false,
801
+ midpoint: false,
802
+ thirdQuartile: false,
803
+ complete: false,
804
+ viewabilitySettled: false,
805
+ lastMuted: void 0,
806
+ progressFired: /* @__PURE__ */ new Set()
807
+ };
808
+ }
809
+ var trackingFired = createTrackingState();
810
+ var resolvedAds = /* @__PURE__ */ new Set();
811
+ var viewObserver;
812
+ var visibleRatio = 0;
813
+ var continuousVisibleS = 0;
814
+ var lastViewSampleTime;
815
+ var lastPlayerExpanded = false;
816
+ var documentHandlers = [];
735
817
  function emit(event, payload) {
736
818
  var set = listeners.get(event);
737
819
  if (!set) return;
@@ -760,7 +842,11 @@ function createHlsAdPlayer(contentVideo, options) {
760
842
  }
761
843
  }
762
844
  }
763
- function buildTrackingMacroContext(errorCode) {
845
+ function buildTrackingMacroContext() {
846
+ var options2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
847
+ var _options2_ad;
848
+ var errorCode = options2.errorCode, reason = options2.reason;
849
+ var ad = (_options2_ad = options2.ad) !== null && _options2_ad !== void 0 ? _options2_ad : currentAd;
764
850
  var context = {
765
851
  adPlayheadSeconds: adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.currentTime,
766
852
  contentPlayheadSeconds: contentVideo.currentTime,
@@ -781,11 +867,17 @@ function createHlsAdPlayer(contentVideo, options) {
781
867
  if (podAds.length > 0) {
782
868
  context.podSequence = podIndex + 1;
783
869
  }
870
+ if (ad === null || ad === void 0 ? void 0 : ad.adServingId) {
871
+ context.adServingId = ad.adServingId;
872
+ }
873
+ if (reason != null) {
874
+ context.reason = reason;
875
+ }
784
876
  return context;
785
877
  }
786
878
  function fireTrackingPixels(urls, options2) {
787
879
  if (!urls || urls.length === 0) return;
788
- var macroContext = buildTrackingMacroContext(options2 === null || options2 === void 0 ? void 0 : options2.errorCode);
880
+ var macroContext = buildTrackingMacroContext(options2);
789
881
  urls.forEach(function(url) {
790
882
  try {
791
883
  var trackingUrl = substituteVastTrackingMacros(url, macroContext);
@@ -896,8 +988,8 @@ function createHlsAdPlayer(contentVideo, options) {
896
988
  var url = (mediaFile.url.toLowerCase().split("?")[0] || "").trim();
897
989
  return type.startsWith("audio/") || url.endsWith(".mp3") || url.endsWith(".aac") || url.endsWith(".m4a") || url.endsWith(".ogg") || url.endsWith(".oga") || url.endsWith(".opus") || url.endsWith(".wav") || url.endsWith(".weba");
898
990
  }
899
- function collectVideoMediaFiles(scope, verbose) {
900
- var mediaFileElements = scope.querySelectorAll("MediaFile");
991
+ function collectVideoMediaFiles(linear, verbose) {
992
+ var mediaFileElements = linear.querySelectorAll(":scope > MediaFiles > MediaFile");
901
993
  var mediaFiles = [];
902
994
  if (verbose) {
903
995
  console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
@@ -917,6 +1009,13 @@ function createHlsAdPlayer(contentVideo, options) {
917
1009
  }
918
1010
  return;
919
1011
  }
1012
+ var apiFramework = (mf.getAttribute("apiFramework") || "").toUpperCase();
1013
+ if (apiFramework === "VPAID") {
1014
+ if (verbose) {
1015
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, " ignored (VPAID creatives are not supported)"));
1016
+ }
1017
+ return;
1018
+ }
920
1019
  var bitrateAttr = mf.getAttribute("bitrate");
921
1020
  var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
922
1021
  var mediaFile = {
@@ -947,114 +1046,144 @@ function createHlsAdPlayer(contentVideo, options) {
947
1046
  return mediaFiles;
948
1047
  }
949
1048
  function createEmptyTrackingUrls() {
950
- return {
1049
+ var urls = {
951
1050
  impression: [],
952
- start: [],
953
- firstQuartile: [],
954
- midpoint: [],
955
- thirdQuartile: [],
956
- complete: [],
957
- mute: [],
958
- unmute: [],
959
- pause: [],
960
- resume: [],
961
- fullscreen: [],
962
- exitFullscreen: [],
963
- skip: [],
964
- error: []
1051
+ clickTracking: [],
1052
+ error: [],
1053
+ viewable: [],
1054
+ notViewable: [],
1055
+ viewUndetermined: [],
1056
+ verificationNotExecuted: [],
1057
+ progress: []
965
1058
  };
1059
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1060
+ try {
1061
+ for(var _iterator = LINEAR_TRACKING_EVENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1062
+ var event = _step.value;
1063
+ urls[event] = [];
1064
+ }
1065
+ } catch (err) {
1066
+ _didIteratorError = true;
1067
+ _iteratorError = err;
1068
+ } finally{
1069
+ try {
1070
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1071
+ _iterator.return();
1072
+ }
1073
+ } finally{
1074
+ if (_didIteratorError) {
1075
+ throw _iteratorError;
1076
+ }
1077
+ }
1078
+ }
1079
+ return urls;
966
1080
  }
967
- function extractTrackingUrls(scope) {
968
- var trackingUrls = createEmptyTrackingUrls();
969
- scope.querySelectorAll("Impression").forEach(function(el) {
970
- var _el_textContent;
971
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
972
- if (url) trackingUrls.impression.push(url);
1081
+ function pushUrls(target, elements) {
1082
+ elements.forEach(function(el) {
1083
+ var url = textOf(el);
1084
+ if (url) target.push(url);
973
1085
  });
974
- scope.querySelectorAll("Tracking").forEach(function(el) {
975
- var _el_textContent;
1086
+ }
1087
+ function collectLinearTracking(linear, into) {
1088
+ linear.querySelectorAll(":scope > TrackingEvents > Tracking").forEach(function(el) {
976
1089
  var event = el.getAttribute("event");
977
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
978
- if (event && url) {
979
- var eventKey = event;
980
- if (trackingUrls[eventKey]) {
981
- trackingUrls[eventKey].push(url);
982
- }
1090
+ var url = textOf(el);
1091
+ if (!event || !url) return;
1092
+ if (event === "progress") {
1093
+ var offset = parseProgressOffset(el.getAttribute("offset"));
1094
+ if (offset) into.progress.push(_object_spread({
1095
+ url: url
1096
+ }, offset));
1097
+ return;
1098
+ }
1099
+ if (LINEAR_TRACKING_EVENTS.indexOf(event) !== -1) {
1100
+ into[event].push(url);
983
1101
  }
984
1102
  });
985
- scope.querySelectorAll("Error").forEach(function(el) {
986
- var _el_textContent;
987
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
988
- if (url) trackingUrls.error.push(url);
1103
+ pushUrls(into.clickTracking, linear.querySelectorAll(":scope > VideoClicks > ClickTracking"));
1104
+ }
1105
+ function collectAdLevelTracking(adBody, into) {
1106
+ pushUrls(into.impression, adBody.querySelectorAll(":scope > Impression"));
1107
+ pushUrls(into.error, adBody.querySelectorAll(":scope > Error"));
1108
+ pushUrls(into.viewable, adBody.querySelectorAll(":scope > ViewableImpression > Viewable"));
1109
+ pushUrls(into.notViewable, adBody.querySelectorAll(":scope > ViewableImpression > NotViewable"));
1110
+ pushUrls(into.viewUndetermined, adBody.querySelectorAll(":scope > ViewableImpression > ViewUndetermined"));
1111
+ adBody.querySelectorAll(':scope > AdVerifications > Verification, :scope > Extensions > Extension[type="AdVerifications"] > AdVerifications > Verification').forEach(function(verification) {
1112
+ pushUrls(into.verificationNotExecuted, verification.querySelectorAll(':scope > TrackingEvents > Tracking[event="verificationNotExecuted"]'));
989
1113
  });
990
- return trackingUrls;
991
1114
  }
992
1115
  function mergeTrackingUrls(target, source) {
993
- Object.keys(target).forEach(function(key) {
994
- if (source[key] && source[key].length > 0) {
995
- target[key] = target[key].concat(source[key]);
1116
+ var targetLists = target;
1117
+ var sourceLists = source;
1118
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1119
+ try {
1120
+ for(var _iterator = Object.keys(targetLists)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1121
+ var key = _step.value;
1122
+ var incoming = sourceLists[key];
1123
+ if (incoming && incoming.length > 0) {
1124
+ targetLists[key] = targetLists[key].concat(incoming);
1125
+ }
996
1126
  }
997
- });
1127
+ } catch (err) {
1128
+ _didIteratorError = true;
1129
+ _iteratorError = err;
1130
+ } finally{
1131
+ try {
1132
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1133
+ _iterator.return();
1134
+ }
1135
+ } finally{
1136
+ if (_didIteratorError) {
1137
+ throw _iteratorError;
1138
+ }
1139
+ }
1140
+ }
998
1141
  return target;
999
1142
  }
1143
+ function parseXml(xmlString) {
1144
+ var xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
1145
+ var parserError = xmlDoc.querySelector("parsererror");
1146
+ if (parserError) {
1147
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1148
+ return null;
1149
+ }
1150
+ return xmlDoc;
1151
+ }
1152
+ function getAdSequence(adElement) {
1153
+ var sequence = parseInt(adElement.getAttribute("sequence") || "", 10);
1154
+ return Number.isFinite(sequence) ? sequence : void 0;
1155
+ }
1156
+ function emptyVastResult(root) {
1157
+ var errorUrls = [];
1158
+ pushUrls(errorUrls, root.querySelectorAll(":scope > Error"));
1159
+ return {
1160
+ type: "empty",
1161
+ errorUrls: errorUrls,
1162
+ errorCode: VAST_ERROR_WRAPPER_NO_ADS
1163
+ };
1164
+ }
1000
1165
  function parseVastXml(xmlString) {
1001
1166
  try {
1002
- var _xmlDoc_querySelector, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent1, _xmlDoc_querySelector2, _xmlDoc_querySelector3;
1003
- var parser = new DOMParser();
1004
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
1005
- var parserError = xmlDoc.querySelector("parsererror");
1006
- if (parserError) {
1007
- console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1008
- return {
1009
- type: "empty"
1010
- };
1011
- }
1012
- var adElement = xmlDoc.querySelector("Ad");
1167
+ var _adElements_find;
1168
+ var xmlDoc = parseXml(xmlString);
1169
+ if (!xmlDoc) return {
1170
+ type: "empty"
1171
+ };
1172
+ var root = xmlDoc.documentElement;
1173
+ var adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1174
+ var adElement = (_adElements_find = adElements.find(function(el) {
1175
+ return getAdSequence(el) === void 0;
1176
+ })) !== null && _adElements_find !== void 0 ? _adElements_find : adElements[0];
1013
1177
  if (!adElement) {
1014
- console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
1015
- return {
1016
- type: "empty"
1017
- };
1178
+ var _root_getAttribute;
1179
+ console.warn("[HlsAdPlayer] No Ad element found in VAST ".concat((_root_getAttribute = root.getAttribute("version")) !== null && _root_getAttribute !== void 0 ? _root_getAttribute : "", " response"));
1180
+ return emptyVastResult(root);
1018
1181
  }
1019
- var adId = adElement.getAttribute("id") || "unknown";
1020
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
1021
- var clickThrough = (_xmlDoc_querySelector1 = xmlDoc.querySelector("ClickThrough")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : (_xmlDoc_querySelector_textContent = _xmlDoc_querySelector1.textContent) === null || _xmlDoc_querySelector_textContent === void 0 ? void 0 : _xmlDoc_querySelector_textContent.trim();
1022
- var wrapperUri = (_xmlDoc_querySelector2 = xmlDoc.querySelector("VASTAdTagURI")) === null || _xmlDoc_querySelector2 === void 0 ? void 0 : (_xmlDoc_querySelector_textContent1 = _xmlDoc_querySelector2.textContent) === null || _xmlDoc_querySelector_textContent1 === void 0 ? void 0 : _xmlDoc_querySelector_textContent1.trim();
1023
- if (wrapperUri) {
1024
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(wrapperUri));
1025
- return {
1026
- type: "wrapper",
1027
- vastAdTagUri: wrapperUri,
1028
- trackingUrls: extractTrackingUrls(xmlDoc),
1029
- clickThrough: clickThrough
1030
- };
1031
- }
1032
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
1033
- var durationText = ((_xmlDoc_querySelector3 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector3 === void 0 ? void 0 : _xmlDoc_querySelector3.textContent) || "00:00:30";
1034
- var durationParts = durationText.split(":");
1035
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
1036
- var mediaFiles = collectVideoMediaFiles(xmlDoc, true);
1037
- if (mediaFiles.length === 0) {
1038
- if (isNoAdAvailable) {
1039
- console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1040
- } else {
1041
- console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1042
- }
1043
- return {
1044
- type: "empty"
1045
- };
1182
+ var parsed = parseAdElement(adElement, true);
1183
+ if (parsed.type === "wrapper") {
1184
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
1046
1185
  }
1047
- return {
1048
- type: "inline",
1049
- ad: {
1050
- id: adId,
1051
- title: title,
1052
- duration: duration,
1053
- mediaFiles: mediaFiles,
1054
- trackingUrls: extractTrackingUrls(xmlDoc),
1055
- clickThrough: clickThrough
1056
- }
1057
- };
1186
+ return parsed;
1058
1187
  } catch (error) {
1059
1188
  console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
1060
1189
  return {
@@ -1063,48 +1192,101 @@ function createHlsAdPlayer(contentVideo, options) {
1063
1192
  }
1064
1193
  }
1065
1194
  function parseAdElement(adElement) {
1195
+ var verbose = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
1066
1196
  try {
1067
- var _adElement_querySelector, _adElement_querySelector_textContent, _adElement_querySelector1, _adElement_querySelector_textContent1, _adElement_querySelector2, _adElement_querySelector3;
1068
- var adId = adElement.getAttribute("id") || "unknown";
1069
- var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
1070
- var clickThrough = (_adElement_querySelector1 = adElement.querySelector("ClickThrough")) === null || _adElement_querySelector1 === void 0 ? void 0 : (_adElement_querySelector_textContent = _adElement_querySelector1.textContent) === null || _adElement_querySelector_textContent === void 0 ? void 0 : _adElement_querySelector_textContent.trim();
1071
- var wrapperUri = (_adElement_querySelector2 = adElement.querySelector("VASTAdTagURI")) === null || _adElement_querySelector2 === void 0 ? void 0 : (_adElement_querySelector_textContent1 = _adElement_querySelector2.textContent) === null || _adElement_querySelector_textContent1 === void 0 ? void 0 : _adElement_querySelector_textContent1.trim();
1072
- if (wrapperUri) {
1197
+ var _parseVastTime;
1198
+ var wrapper = adElement.querySelector(":scope > Wrapper");
1199
+ if (wrapper) {
1200
+ var vastAdTagUri = textOf(wrapper.querySelector(":scope > VASTAdTagURI"));
1201
+ if (!vastAdTagUri) {
1202
+ console.warn("[HlsAdPlayer] <Wrapper> has no VASTAdTagURI");
1203
+ return {
1204
+ type: "empty"
1205
+ };
1206
+ }
1207
+ var trackingUrls2 = createEmptyTrackingUrls();
1208
+ collectAdLevelTracking(wrapper, trackingUrls2);
1209
+ wrapper.querySelectorAll(":scope > Creatives > Creative > Linear").forEach(function(linear2) {
1210
+ return collectLinearTracking(linear2, trackingUrls2);
1211
+ });
1073
1212
  return {
1074
1213
  type: "wrapper",
1075
- vastAdTagUri: wrapperUri,
1076
- trackingUrls: extractTrackingUrls(adElement),
1077
- clickThrough: clickThrough
1214
+ vastAdTagUri: vastAdTagUri,
1215
+ trackingUrls: trackingUrls2,
1216
+ rules: {
1217
+ followAdditionalWrappers: wrapper.getAttribute("followAdditionalWrappers") !== "false"
1218
+ }
1078
1219
  };
1079
1220
  }
1080
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
1081
- var durationText = ((_adElement_querySelector3 = adElement.querySelector("Duration")) === null || _adElement_querySelector3 === void 0 ? void 0 : _adElement_querySelector3.textContent) || "00:00:30";
1082
- var durationParts = durationText.split(":");
1083
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
1084
- var mediaFiles = collectVideoMediaFiles(adElement, false);
1085
- if (mediaFiles.length === 0) {
1086
- if (isNoAdAvailable) {
1087
- console.warn("[HlsAdPlayer] Pod <Ad> indicates no ad available");
1088
- } else {
1089
- console.warn("[HlsAdPlayer] No supported media files in pod <Ad>");
1090
- }
1221
+ var inLine = adElement.querySelector(":scope > InLine");
1222
+ if (!inLine) {
1223
+ console.warn("[HlsAdPlayer] <Ad> has neither <InLine> nor <Wrapper>");
1091
1224
  return {
1092
1225
  type: "empty"
1093
1226
  };
1094
1227
  }
1228
+ var errorUrls = [];
1229
+ pushUrls(errorUrls, inLine.querySelectorAll(":scope > Error"));
1230
+ if (adElement.getAttribute("conditionalAd") === "true") {
1231
+ console.warn("[HlsAdPlayer] Skipping conditional <Ad> (VPAID-only)");
1232
+ return {
1233
+ type: "empty",
1234
+ errorUrls: errorUrls,
1235
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1236
+ };
1237
+ }
1238
+ var linear;
1239
+ var mediaFiles = [];
1240
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1241
+ try {
1242
+ for(var _iterator = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear"))[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1243
+ var candidate = _step.value;
1244
+ var files = collectVideoMediaFiles(candidate, verbose);
1245
+ if (files.length > 0) {
1246
+ linear = candidate;
1247
+ mediaFiles = files;
1248
+ break;
1249
+ }
1250
+ }
1251
+ } catch (err) {
1252
+ _didIteratorError = true;
1253
+ _iteratorError = err;
1254
+ } finally{
1255
+ try {
1256
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1257
+ _iterator.return();
1258
+ }
1259
+ } finally{
1260
+ if (_didIteratorError) {
1261
+ throw _iteratorError;
1262
+ }
1263
+ }
1264
+ }
1265
+ if (!linear) {
1266
+ console.warn("[HlsAdPlayer] No supported linear media files in <Ad>");
1267
+ return {
1268
+ type: "empty",
1269
+ errorUrls: errorUrls,
1270
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1271
+ };
1272
+ }
1273
+ var trackingUrls = createEmptyTrackingUrls();
1274
+ collectAdLevelTracking(inLine, trackingUrls);
1275
+ collectLinearTracking(linear, trackingUrls);
1095
1276
  return {
1096
1277
  type: "inline",
1097
1278
  ad: {
1098
- id: adId,
1099
- title: title,
1100
- duration: duration,
1279
+ id: adElement.getAttribute("id") || "unknown",
1280
+ title: textOf(inLine.querySelector(":scope > AdTitle")) || "Ad",
1281
+ duration: (_parseVastTime = parseVastTime(textOf(linear.querySelector(":scope > Duration")))) !== null && _parseVastTime !== void 0 ? _parseVastTime : 30,
1101
1282
  mediaFiles: mediaFiles,
1102
- trackingUrls: extractTrackingUrls(adElement),
1103
- clickThrough: clickThrough
1283
+ trackingUrls: trackingUrls,
1284
+ clickThrough: textOf(linear.querySelector(":scope > VideoClicks > ClickThrough")),
1285
+ adServingId: textOf(inLine.querySelector(":scope > AdServingId"))
1104
1286
  }
1105
1287
  };
1106
1288
  } catch (error) {
1107
- console.error("[HlsAdPlayer] Error parsing pod <Ad> element:", error);
1289
+ console.error("[HlsAdPlayer] Error parsing <Ad> element:", error);
1108
1290
  return {
1109
1291
  type: "empty"
1110
1292
  };
@@ -1183,30 +1365,63 @@ function createHlsAdPlayer(contentVideo, options) {
1183
1365
  }
1184
1366
  function fetchAndParseVastAd(_0) {
1185
1367
  return _async_to_generator(function(vastTagUrl) {
1186
- var depth, accumulatedTracking, vastXml, parsed;
1368
+ var depth, accumulatedTracking, rules, vastXml, error, parsed, _parsed_errorUrls, _parsed_errorCode;
1187
1369
  var _arguments = arguments;
1188
1370
  return _ts_generator(this, function(_state) {
1189
1371
  switch(_state.label){
1190
1372
  case 0:
1191
- depth = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : 0, accumulatedTracking = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : createEmptyTrackingUrls();
1373
+ depth = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : 0, accumulatedTracking = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : createEmptyTrackingUrls(), rules = _arguments.length > 3 && _arguments[3] !== void 0 ? _arguments[3] : {
1374
+ followAdditionalWrappers: true
1375
+ };
1376
+ _state.label = 1;
1377
+ case 1:
1378
+ _state.trys.push([
1379
+ 1,
1380
+ 3,
1381
+ ,
1382
+ 4
1383
+ ]);
1192
1384
  return [
1193
1385
  4,
1194
1386
  fetchVastXml(vastTagUrl, depth === 0 ? "include" : "omit")
1195
1387
  ];
1196
- case 1:
1388
+ case 2:
1197
1389
  vastXml = _state.sent();
1390
+ return [
1391
+ 3,
1392
+ 4
1393
+ ];
1394
+ case 3:
1395
+ error = _state.sent();
1396
+ if (depth === 0) throw error;
1397
+ console.warn("[HlsAdPlayer] Wrapped VAST request failed:", error);
1398
+ fireTrackingPixels(accumulatedTracking.error, {
1399
+ errorCode: VAST_ERROR_WRAPPER_TIMEOUT
1400
+ });
1401
+ return [
1402
+ 2,
1403
+ null
1404
+ ];
1405
+ case 4:
1198
1406
  console.log("[HlsAdPlayer] VAST XML received");
1199
1407
  console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1200
1408
  parsed = parseVastXml(vastXml);
1201
1409
  if (parsed.type === "empty") {
1410
+ ;
1411
+ fireTrackingPixels(((_parsed_errorUrls = parsed.errorUrls) !== null && _parsed_errorUrls !== void 0 ? _parsed_errorUrls : []).concat(accumulatedTracking.error), {
1412
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1413
+ });
1202
1414
  return [
1203
1415
  2,
1204
1416
  null
1205
1417
  ];
1206
1418
  }
1207
1419
  if (parsed.type === "wrapper") {
1208
- if (depth >= MAX_VAST_WRAPPER_DEPTH) {
1209
- console.warn("[HlsAdPlayer] VAST wrapper depth limit (".concat(MAX_VAST_WRAPPER_DEPTH, ") reached, aborting redirect chain"));
1420
+ if (depth >= MAX_VAST_WRAPPER_DEPTH || !rules.followAdditionalWrappers) {
1421
+ console.warn(rules.followAdditionalWrappers ? "[HlsAdPlayer] VAST wrapper depth limit (".concat(MAX_VAST_WRAPPER_DEPTH, ") reached, aborting redirect chain") : '[HlsAdPlayer] Parent wrapper set followAdditionalWrappers="false"; rejecting nested wrapper');
1422
+ fireTrackingPixels(accumulatedTracking.error.concat(parsed.trackingUrls.error), {
1423
+ errorCode: VAST_ERROR_WRAPPER_LIMIT
1424
+ });
1210
1425
  return [
1211
1426
  2,
1212
1427
  null
@@ -1215,7 +1430,7 @@ function createHlsAdPlayer(contentVideo, options) {
1215
1430
  mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);
1216
1431
  return [
1217
1432
  2,
1218
- fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking)
1433
+ fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking, parsed.rules)
1219
1434
  ];
1220
1435
  }
1221
1436
  mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);
@@ -1229,7 +1444,7 @@ function createHlsAdPlayer(contentVideo, options) {
1229
1444
  }
1230
1445
  function fetchAndParsePod(vastTagUrl) {
1231
1446
  return _async_to_generator(function() {
1232
- var vastXml, trimmedXml, parser, xmlDoc, adElements, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, adElement, parsed, resolved, error, err;
1447
+ var _root_getAttribute, vastXml, trimmedXml, xmlDoc, root, adElements, _root_getAttribute1, _empty_errorUrls, empty, _empty_errorCode, resolveAd, podElements, buffet, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, adElement, ad, err, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, adElement1, ad1, err;
1233
1448
  return _ts_generator(this, function(_state) {
1234
1449
  switch(_state.label){
1235
1450
  case 0:
@@ -1248,125 +1463,212 @@ function createHlsAdPlayer(contentVideo, options) {
1248
1463
  []
1249
1464
  ];
1250
1465
  }
1251
- parser = new DOMParser();
1252
- xmlDoc = parser.parseFromString(vastXml, "text/xml");
1253
- if (xmlDoc.querySelector("parsererror")) {
1254
- console.error("[HlsAdPlayer] Pod VAST XML parsing error (malformed). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1466
+ xmlDoc = parseXml(vastXml);
1467
+ if (!xmlDoc) {
1468
+ console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1255
1469
  return [
1256
1470
  2,
1257
1471
  []
1258
1472
  ];
1259
1473
  }
1260
- adElements = Array.from(xmlDoc.querySelectorAll("Ad"));
1474
+ root = xmlDoc.documentElement;
1475
+ adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1261
1476
  if (adElements.length === 0) {
1262
- console.warn("[HlsAdPlayer] No <Ad> elements found in pod VAST response (no fill). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1477
+ ;
1478
+ ;
1479
+ console.warn("[HlsAdPlayer] No <Ad> elements in VAST ".concat((_root_getAttribute1 = root.getAttribute("version")) !== null && _root_getAttribute1 !== void 0 ? _root_getAttribute1 : "", " pod response (no fill)"));
1480
+ empty = emptyVastResult(root);
1481
+ if (empty.type === "empty" && ((_empty_errorUrls = empty.errorUrls) === null || _empty_errorUrls === void 0 ? void 0 : _empty_errorUrls.length)) {
1482
+ ;
1483
+ fireTrackingPixels(empty.errorUrls, {
1484
+ errorCode: (_empty_errorCode = empty.errorCode) !== null && _empty_errorCode !== void 0 ? _empty_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1485
+ });
1486
+ }
1263
1487
  return [
1264
1488
  2,
1265
1489
  []
1266
1490
  ];
1267
1491
  }
1268
- adElements.sort(function(a, b) {
1269
- var aSeq = parseInt(a.getAttribute("sequence") || "", 10);
1270
- var bSeq = parseInt(b.getAttribute("sequence") || "", 10);
1271
- var aVal = Number.isFinite(aSeq) ? aSeq : Number.MAX_SAFE_INTEGER;
1272
- var bVal = Number.isFinite(bSeq) ? bSeq : Number.MAX_SAFE_INTEGER;
1273
- return aVal - bVal;
1492
+ resolveAd = function resolveAd(adElement) {
1493
+ return _async_to_generator(function() {
1494
+ var _parsed_errorUrls, parsed, _parsed_errorCode;
1495
+ return _ts_generator(this, function(_state) {
1496
+ parsed = parseAdElement(adElement);
1497
+ if (parsed.type === "inline") return [
1498
+ 2,
1499
+ parsed.ad
1500
+ ];
1501
+ if (parsed.type === "wrapper") {
1502
+ return [
1503
+ 2,
1504
+ fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls, parsed.rules)
1505
+ ];
1506
+ }
1507
+ if ((_parsed_errorUrls = parsed.errorUrls) === null || _parsed_errorUrls === void 0 ? void 0 : _parsed_errorUrls.length) {
1508
+ ;
1509
+ fireTrackingPixels(parsed.errorUrls, {
1510
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_NO_SUPPORTED_MEDIA
1511
+ });
1512
+ }
1513
+ return [
1514
+ 2,
1515
+ null
1516
+ ];
1517
+ });
1518
+ })();
1519
+ };
1520
+ podElements = adElements.filter(function(el) {
1521
+ return getAdSequence(el) !== void 0;
1522
+ }).sort(function(a, b) {
1523
+ return getAdSequence(a) - getAdSequence(b);
1524
+ });
1525
+ buffet = adElements.filter(function(el) {
1526
+ return getAdSequence(el) === void 0;
1274
1527
  });
1275
1528
  ads = [];
1529
+ if (!(podElements.length === 0)) return [
1530
+ 3,
1531
+ 10
1532
+ ];
1276
1533
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1277
1534
  _state.label = 2;
1278
1535
  case 2:
1279
1536
  _state.trys.push([
1280
1537
  2,
1281
- 10,
1282
- 11,
1283
- 12
1538
+ 7,
1539
+ 8,
1540
+ 9
1284
1541
  ]);
1285
- _iterator = adElements[Symbol.iterator]();
1542
+ _iterator = buffet[Symbol.iterator]();
1286
1543
  _state.label = 3;
1287
1544
  case 3:
1288
1545
  if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
1289
1546
  3,
1290
- 9
1547
+ 6
1291
1548
  ];
1292
1549
  adElement = _step.value;
1293
- parsed = parseAdElement(adElement);
1294
- if (!(parsed.type === "inline")) return [
1295
- 3,
1296
- 4
1297
- ];
1298
- ads.push(parsed.ad);
1299
1550
  return [
1300
- 3,
1301
- 8
1551
+ 4,
1552
+ resolveAd(adElement)
1302
1553
  ];
1303
1554
  case 4:
1304
- if (!(parsed.type === "wrapper")) return [
1305
- 3,
1306
- 8
1307
- ];
1555
+ ad = _state.sent();
1556
+ if (ad) ads.push(ad);
1308
1557
  _state.label = 5;
1309
1558
  case 5:
1310
- _state.trys.push([
1311
- 5,
1312
- 7,
1313
- ,
1314
- 8
1315
- ]);
1559
+ _iteratorNormalCompletion = true;
1316
1560
  return [
1317
- 4,
1318
- fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls)
1561
+ 3,
1562
+ 3
1319
1563
  ];
1320
1564
  case 6:
1321
- resolved = _state.sent();
1322
- if (resolved) {
1323
- ads.push(resolved);
1324
- }
1325
1565
  return [
1326
1566
  3,
1327
- 8
1567
+ 9
1328
1568
  ];
1329
1569
  case 7:
1330
- error = _state.sent();
1331
- console.warn("[HlsAdPlayer] Failed to resolve wrapper <Ad> in pod:", error);
1570
+ err = _state.sent();
1571
+ _didIteratorError = true;
1572
+ _iteratorError = err;
1332
1573
  return [
1333
1574
  3,
1334
- 8
1575
+ 9
1335
1576
  ];
1336
1577
  case 8:
1337
- _iteratorNormalCompletion = true;
1578
+ try {
1579
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1580
+ _iterator.return();
1581
+ }
1582
+ } finally{
1583
+ if (_didIteratorError) {
1584
+ throw _iteratorError;
1585
+ }
1586
+ }
1338
1587
  return [
1339
- 3,
1340
- 3
1588
+ 7
1341
1589
  ];
1342
1590
  case 9:
1343
1591
  return [
1344
1592
  3,
1345
- 12
1593
+ 21
1346
1594
  ];
1347
1595
  case 10:
1348
- err = _state.sent();
1349
- _didIteratorError = true;
1350
- _iteratorError = err;
1596
+ _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
1597
+ _state.label = 11;
1598
+ case 11:
1599
+ _state.trys.push([
1600
+ 11,
1601
+ 19,
1602
+ 20,
1603
+ 21
1604
+ ]);
1605
+ _iterator1 = podElements[Symbol.iterator]();
1606
+ _state.label = 12;
1607
+ case 12:
1608
+ if (!!(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done)) return [
1609
+ 3,
1610
+ 18
1611
+ ];
1612
+ adElement1 = _step1.value;
1613
+ return [
1614
+ 4,
1615
+ resolveAd(adElement1)
1616
+ ];
1617
+ case 13:
1618
+ ad1 = _state.sent();
1619
+ _state.label = 14;
1620
+ case 14:
1621
+ if (!(!ad1 && buffet.length > 0)) return [
1622
+ 3,
1623
+ 16
1624
+ ];
1625
+ return [
1626
+ 4,
1627
+ resolveAd(buffet.shift())
1628
+ ];
1629
+ case 15:
1630
+ ad1 = _state.sent();
1631
+ return [
1632
+ 3,
1633
+ 14
1634
+ ];
1635
+ case 16:
1636
+ if (ad1) ads.push(ad1);
1637
+ _state.label = 17;
1638
+ case 17:
1639
+ _iteratorNormalCompletion1 = true;
1351
1640
  return [
1352
1641
  3,
1353
1642
  12
1354
1643
  ];
1355
- case 11:
1644
+ case 18:
1645
+ return [
1646
+ 3,
1647
+ 21
1648
+ ];
1649
+ case 19:
1650
+ err = _state.sent();
1651
+ _didIteratorError1 = true;
1652
+ _iteratorError1 = err;
1653
+ return [
1654
+ 3,
1655
+ 21
1656
+ ];
1657
+ case 20:
1356
1658
  try {
1357
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1358
- _iterator.return();
1659
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1660
+ _iterator1.return();
1359
1661
  }
1360
1662
  } finally{
1361
- if (_didIteratorError) {
1362
- throw _iteratorError;
1663
+ if (_didIteratorError1) {
1664
+ throw _iteratorError1;
1363
1665
  }
1364
1666
  }
1365
1667
  return [
1366
1668
  7
1367
1669
  ];
1368
- case 12:
1369
- console.log("[HlsAdPlayer] Parsed ".concat(ads.length, " ad(s) from pod VAST response"));
1670
+ case 21:
1671
+ console.log("[HlsAdPlayer] Parsed ".concat(ads.length, " ad(s) from VAST ").concat((_root_getAttribute = root.getAttribute("version")) !== null && _root_getAttribute !== void 0 ? _root_getAttribute : "", " pod response"));
1370
1672
  return [
1371
1673
  2,
1372
1674
  ads
@@ -1396,7 +1698,40 @@ function createHlsAdPlayer(contentVideo, options) {
1396
1698
  var onTimeUpdate = function onTimeUpdate() {
1397
1699
  if (!currentAd || !adVideoElement) return;
1398
1700
  noteAdProgress();
1399
- var progress = adVideoElement.currentTime / currentAd.duration;
1701
+ sampleViewability();
1702
+ var currentTime = adVideoElement.currentTime;
1703
+ if (trackingFired.start) {
1704
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1705
+ try {
1706
+ for(var _iterator = currentAd.trackingUrls.progress[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1707
+ var event = _step.value;
1708
+ var _event_offsetSeconds, _event_offsetPercent;
1709
+ if (trackingFired.progressFired.has(event)) continue;
1710
+ var threshold = (_event_offsetSeconds = event.offsetSeconds) !== null && _event_offsetSeconds !== void 0 ? _event_offsetSeconds : ((_event_offsetPercent = event.offsetPercent) !== null && _event_offsetPercent !== void 0 ? _event_offsetPercent : 0) / 100 * currentAd.duration;
1711
+ if (currentTime >= threshold) {
1712
+ trackingFired.progressFired.add(event);
1713
+ fireTrackingPixels([
1714
+ event.url
1715
+ ]);
1716
+ }
1717
+ }
1718
+ } catch (err) {
1719
+ _didIteratorError = true;
1720
+ _iteratorError = err;
1721
+ } finally{
1722
+ try {
1723
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1724
+ _iterator.return();
1725
+ }
1726
+ } finally{
1727
+ if (_didIteratorError) {
1728
+ throw _iteratorError;
1729
+ }
1730
+ }
1731
+ }
1732
+ }
1733
+ if (!(currentAd.duration > 0)) return;
1734
+ var progress = currentTime / currentAd.duration;
1400
1735
  if (progress >= 0.25 && !trackingFired.firstQuartile) {
1401
1736
  trackingFired.firstQuartile = true;
1402
1737
  fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
@@ -1418,15 +1753,38 @@ function createHlsAdPlayer(contentVideo, options) {
1418
1753
  handleVideoDecodeFailure();
1419
1754
  }
1420
1755
  };
1756
+ var onCanPlay = function onCanPlay() {
1757
+ if (!currentAd || trackingFired.loaded) return;
1758
+ trackingFired.loaded = true;
1759
+ fireTrackingPixels(currentAd.trackingUrls.loaded);
1760
+ };
1421
1761
  var onPlaying = function onPlaying() {
1422
1762
  startStallWatchdog();
1423
- if (!currentAd || trackingFired.start) return;
1763
+ if (!currentAd || !adVideoElement) return;
1764
+ if (!trackingFired.impression) {
1765
+ trackingFired.impression = true;
1766
+ resolvedAds.add(currentAd);
1767
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1768
+ fireTrackingPixels(currentAd.trackingUrls.creativeView);
1769
+ fireTrackingPixels(currentAd.trackingUrls.verificationNotExecuted, {
1770
+ reason: VERIFICATION_NOT_SUPPORTED_REASON
1771
+ });
1772
+ emit("ad_impression", {
1773
+ adId: currentAd.id,
1774
+ index: podIndex,
1775
+ total: podAds.length || 1
1776
+ });
1777
+ }
1778
+ if (trackingFired.start) return;
1424
1779
  trackingFired.start = true;
1780
+ trackingFired.lastMuted = adVideoElement.muted || adVideoElement.volume === 0;
1425
1781
  fireTrackingPixels(currentAd.trackingUrls.start);
1426
1782
  console.log("[HlsAdPlayer] Ad started playing");
1427
1783
  };
1428
1784
  var onEnded = function onEnded() {
1429
1785
  if (!currentAd || trackingFired.complete) return;
1786
+ sampleViewability();
1787
+ settleViewability();
1430
1788
  trackingFired.complete = true;
1431
1789
  fireTrackingPixels(currentAd.trackingUrls.complete);
1432
1790
  console.log("[HlsAdPlayer] Ad completed");
@@ -1438,11 +1796,7 @@ function createHlsAdPlayer(contentVideo, options) {
1438
1796
  var onError = function onError(e) {
1439
1797
  if (!adPlaying) return;
1440
1798
  console.error("[HlsAdPlayer] Ad video error:", e);
1441
- if (currentAd) {
1442
- fireTrackingPixels(currentAd.trackingUrls.error, {
1443
- errorCode: toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error)
1444
- });
1445
- }
1799
+ reportCurrentAdError(toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error));
1446
1800
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1447
1801
  return;
1448
1802
  }
@@ -1450,19 +1804,26 @@ function createHlsAdPlayer(contentVideo, options) {
1450
1804
  };
1451
1805
  var onVolumeChange = function onVolumeChange() {
1452
1806
  if (!currentAd || !adVideoElement) return;
1453
- if (adVideoElement.muted) {
1454
- fireTrackingPixels(currentAd.trackingUrls.mute);
1455
- } else {
1456
- fireTrackingPixels(currentAd.trackingUrls.unmute);
1807
+ var muted = adVideoElement.muted || adVideoElement.volume === 0;
1808
+ if (!trackingFired.start) {
1809
+ trackingFired.lastMuted = muted;
1810
+ return;
1457
1811
  }
1812
+ if (muted === trackingFired.lastMuted) return;
1813
+ trackingFired.lastMuted = muted;
1814
+ fireTrackingPixels(muted ? currentAd.trackingUrls.mute : currentAd.trackingUrls.unmute);
1815
+ };
1816
+ var isTrackablePlayback = function isTrackablePlayback() {
1817
+ return adPlaying && !!currentAd && !!adVideoElement && trackingFired.start && !trackingFired.complete && !adVideoElement.ended;
1458
1818
  };
1459
1819
  var onPause = function onPause() {
1460
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1820
+ continuousVisibleS = 0;
1821
+ if (isTrackablePlayback()) {
1461
1822
  fireTrackingPixels(currentAd.trackingUrls.pause);
1462
1823
  }
1463
1824
  };
1464
1825
  var onPlay = function onPlay() {
1465
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1826
+ if (isTrackablePlayback()) {
1466
1827
  fireTrackingPixels(currentAd.trackingUrls.resume);
1467
1828
  }
1468
1829
  };
@@ -1475,6 +1836,10 @@ function createHlsAdPlayer(contentVideo, options) {
1475
1836
  type: "loadedmetadata",
1476
1837
  handler: onLoadedMetadata
1477
1838
  },
1839
+ {
1840
+ type: "canplay",
1841
+ handler: onCanPlay
1842
+ },
1478
1843
  {
1479
1844
  type: "playing",
1480
1845
  handler: onPlaying
@@ -1546,6 +1911,229 @@ function createHlsAdPlayer(contentVideo, options) {
1546
1911
  }
1547
1912
  adEventHandlers = [];
1548
1913
  }
1914
+ function handleAdClick() {
1915
+ if (!adPlaying || !currentAd) return;
1916
+ fireTrackingPixels(currentAd.trackingUrls.clickTracking);
1917
+ emit("ad_click", {
1918
+ adId: currentAd.id,
1919
+ clickThrough: currentAd.clickThrough
1920
+ });
1921
+ if (currentAd.clickThrough) {
1922
+ try {
1923
+ window.open(currentAd.clickThrough, "_blank", "noopener");
1924
+ } catch (error) {
1925
+ console.warn("[HlsAdPlayer] Failed to open ClickThrough URL:", error);
1926
+ }
1927
+ }
1928
+ }
1929
+ function reportCurrentAdError(errorCode) {
1930
+ if (!currentAd) return;
1931
+ resolvedAds.add(currentAd);
1932
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1933
+ errorCode: errorCode
1934
+ });
1935
+ }
1936
+ function fireNotUsedForUnplayedAds() {
1937
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1938
+ try {
1939
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1940
+ var ad = _step.value;
1941
+ if (resolvedAds.has(ad)) continue;
1942
+ resolvedAds.add(ad);
1943
+ fireTrackingPixels(ad.trackingUrls.notUsed, {
1944
+ ad: ad
1945
+ });
1946
+ }
1947
+ } catch (err) {
1948
+ _didIteratorError = true;
1949
+ _iteratorError = err;
1950
+ } finally{
1951
+ try {
1952
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1953
+ _iterator.return();
1954
+ }
1955
+ } finally{
1956
+ if (_didIteratorError) {
1957
+ throw _iteratorError;
1958
+ }
1959
+ }
1960
+ }
1961
+ }
1962
+ function sampleViewability() {
1963
+ if (!currentAd || !adVideoElement || !viewObserver || !trackingFired.impression || trackingFired.viewabilitySettled) {
1964
+ return;
1965
+ }
1966
+ var now = adVideoElement.currentTime;
1967
+ var inView = visibleRatio >= VIEWABLE_MIN_VISIBLE_RATIO && document.visibilityState === "visible" && !adVideoElement.paused;
1968
+ if (!inView) {
1969
+ continuousVisibleS = 0;
1970
+ } else if (lastViewSampleTime !== void 0 && now >= lastViewSampleTime) {
1971
+ continuousVisibleS += now - lastViewSampleTime;
1972
+ }
1973
+ lastViewSampleTime = now;
1974
+ if (continuousVisibleS >= VIEWABLE_MIN_CONTINUOUS_S) {
1975
+ trackingFired.viewabilitySettled = true;
1976
+ fireTrackingPixels(currentAd.trackingUrls.viewable);
1977
+ }
1978
+ }
1979
+ function settleViewability() {
1980
+ if (!currentAd || !trackingFired.impression || trackingFired.viewabilitySettled) {
1981
+ return;
1982
+ }
1983
+ trackingFired.viewabilitySettled = true;
1984
+ fireTrackingPixels(viewObserver ? currentAd.trackingUrls.notViewable : currentAd.trackingUrls.viewUndetermined);
1985
+ }
1986
+ function handleFullscreenChange() {
1987
+ var _document_fullscreenElement;
1988
+ if (!adPlaying || !currentAd || !adContainerEl || !trackingFired.start) return;
1989
+ var fullscreenEl = (_document_fullscreenElement = document.fullscreenElement) !== null && _document_fullscreenElement !== void 0 ? _document_fullscreenElement : document.webkitFullscreenElement;
1990
+ var expanded = !!fullscreenEl && fullscreenEl.contains(adContainerEl);
1991
+ if (expanded === lastPlayerExpanded) return;
1992
+ lastPlayerExpanded = expanded;
1993
+ var urls = currentAd.trackingUrls;
1994
+ fireTrackingPixels(expanded ? urls.fullscreen.concat(urls.playerExpand) : urls.exitFullscreen.concat(urls.playerCollapse));
1995
+ }
1996
+ function attachContainerHandlers() {
1997
+ if (!adContainerEl || containerHandlers.length > 0) return;
1998
+ var onClick = function onClick() {
1999
+ return handleAdClick();
2000
+ };
2001
+ var onInteraction = function onInteraction(event) {
2002
+ if (adPlaying) emit("ad_interaction", event);
2003
+ };
2004
+ containerHandlers = [
2005
+ {
2006
+ type: "click",
2007
+ handler: onClick
2008
+ },
2009
+ {
2010
+ type: "mousedown",
2011
+ handler: onInteraction
2012
+ },
2013
+ {
2014
+ type: "touchstart",
2015
+ handler: onInteraction
2016
+ }
2017
+ ];
2018
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2019
+ try {
2020
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2021
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
2022
+ adContainerEl.addEventListener(type, handler);
2023
+ }
2024
+ } catch (err) {
2025
+ _didIteratorError = true;
2026
+ _iteratorError = err;
2027
+ } finally{
2028
+ try {
2029
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2030
+ _iterator.return();
2031
+ }
2032
+ } finally{
2033
+ if (_didIteratorError) {
2034
+ throw _iteratorError;
2035
+ }
2036
+ }
2037
+ }
2038
+ var onFullscreenChange = function onFullscreenChange() {
2039
+ return handleFullscreenChange();
2040
+ };
2041
+ documentHandlers = [
2042
+ {
2043
+ type: "fullscreenchange",
2044
+ handler: onFullscreenChange
2045
+ },
2046
+ {
2047
+ type: "webkitfullscreenchange",
2048
+ handler: onFullscreenChange
2049
+ }
2050
+ ];
2051
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2052
+ try {
2053
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2054
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
2055
+ document.addEventListener(type1, handler1);
2056
+ }
2057
+ } catch (err) {
2058
+ _didIteratorError1 = true;
2059
+ _iteratorError1 = err;
2060
+ } finally{
2061
+ try {
2062
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2063
+ _iterator1.return();
2064
+ }
2065
+ } finally{
2066
+ if (_didIteratorError1) {
2067
+ throw _iteratorError1;
2068
+ }
2069
+ }
2070
+ }
2071
+ if (typeof IntersectionObserver !== "undefined") {
2072
+ viewObserver = new IntersectionObserver(function(entries) {
2073
+ var entry = entries[entries.length - 1];
2074
+ if (entry) {
2075
+ visibleRatio = entry.isIntersecting ? entry.intersectionRatio : 0;
2076
+ }
2077
+ }, {
2078
+ threshold: [
2079
+ 0,
2080
+ 0.25,
2081
+ 0.5,
2082
+ 0.75,
2083
+ 1
2084
+ ]
2085
+ });
2086
+ viewObserver.observe(adContainerEl);
2087
+ }
2088
+ }
2089
+ function detachContainerHandlers() {
2090
+ if (adContainerEl) {
2091
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2092
+ try {
2093
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2094
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
2095
+ adContainerEl.removeEventListener(type, handler);
2096
+ }
2097
+ } catch (err) {
2098
+ _didIteratorError = true;
2099
+ _iteratorError = err;
2100
+ } finally{
2101
+ try {
2102
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2103
+ _iterator.return();
2104
+ }
2105
+ } finally{
2106
+ if (_didIteratorError) {
2107
+ throw _iteratorError;
2108
+ }
2109
+ }
2110
+ }
2111
+ }
2112
+ containerHandlers = [];
2113
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2114
+ try {
2115
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2116
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
2117
+ document.removeEventListener(type1, handler1);
2118
+ }
2119
+ } catch (err) {
2120
+ _didIteratorError1 = true;
2121
+ _iteratorError1 = err;
2122
+ } finally{
2123
+ try {
2124
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2125
+ _iterator1.return();
2126
+ }
2127
+ } finally{
2128
+ if (_didIteratorError1) {
2129
+ throw _iteratorError1;
2130
+ }
2131
+ }
2132
+ }
2133
+ documentHandlers = [];
2134
+ viewObserver === null || viewObserver === void 0 ? void 0 : viewObserver.disconnect();
2135
+ viewObserver = void 0;
2136
+ }
1549
2137
  function setAdPlayingFlag(isPlaying) {
1550
2138
  if (isPlaying) {
1551
2139
  contentVideo.dataset.stormcloudAdPlaying = "true";
@@ -1553,15 +2141,10 @@ function createHlsAdPlayer(contentVideo, options) {
1553
2141
  delete contentVideo.dataset.stormcloudAdPlaying;
1554
2142
  }
1555
2143
  }
1556
- function resetQuartileTracking(preserveImpression) {
1557
- trackingFired = {
1558
- impression: preserveImpression ? trackingFired.impression : false,
1559
- start: false,
1560
- firstQuartile: false,
1561
- midpoint: false,
1562
- thirdQuartile: false,
1563
- complete: false
1564
- };
2144
+ function resetAdTracking() {
2145
+ trackingFired = createTrackingState();
2146
+ continuousVisibleS = 0;
2147
+ lastViewSampleTime = void 0;
1565
2148
  }
1566
2149
  function isRvfcSupported(video) {
1567
2150
  return typeof video.requestVideoFrameCallback === "function";
@@ -1667,13 +2250,12 @@ function createHlsAdPlayer(contentVideo, options) {
1667
2250
  if (podIndex >= podAds.length - 1) {
1668
2251
  return false;
1669
2252
  }
2253
+ settleViewability();
1670
2254
  podIndex++;
1671
2255
  currentAd = podAds[podIndex];
1672
2256
  currentAdMediaFile = void 0;
1673
- resetQuartileTracking(false);
2257
+ resetAdTracking();
1674
2258
  if (currentAd) {
1675
- fireTrackingPixels(currentAd.trackingUrls.impression);
1676
- trackingFired.impression = true;
1677
2259
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1678
2260
  }
1679
2261
  clearStallWatchdog();
@@ -1711,11 +2293,7 @@ function createHlsAdPlayer(contentVideo, options) {
1711
2293
  function handleAdStall() {
1712
2294
  console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
1713
2295
  clearStallWatchdog();
1714
- if (currentAd) {
1715
- fireTrackingPixels(currentAd.trackingUrls.error, {
1716
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1717
- });
1718
- }
2296
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1719
2297
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1720
2298
  return;
1721
2299
  }
@@ -1781,11 +2359,7 @@ function createHlsAdPlayer(contentVideo, options) {
1781
2359
  function handleVideoDecodeFailure() {
1782
2360
  console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1783
2361
  clearStallWatchdog();
1784
- if (currentAd) {
1785
- fireTrackingPixels(currentAd.trackingUrls.error, {
1786
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1787
- });
1788
- }
2362
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1789
2363
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1790
2364
  return;
1791
2365
  }
@@ -1840,6 +2414,7 @@ function createHlsAdPlayer(contentVideo, options) {
1840
2414
  }
1841
2415
  function handleAdComplete() {
1842
2416
  console.log("[HlsAdPlayer] Handling ad completion");
2417
+ settleViewability();
1843
2418
  clearStallWatchdog();
1844
2419
  adPlaying = false;
1845
2420
  setAdPlayingFlag(false);
@@ -1863,6 +2438,7 @@ function createHlsAdPlayer(contentVideo, options) {
1863
2438
  }
1864
2439
  function handleAdError() {
1865
2440
  console.log("[HlsAdPlayer] Handling ad error");
2441
+ settleViewability();
1866
2442
  clearStallWatchdog();
1867
2443
  adPlaying = false;
1868
2444
  setAdPlayingFlag(false);
@@ -1895,6 +2471,7 @@ function createHlsAdPlayer(contentVideo, options) {
1895
2471
  adContainerEl = container;
1896
2472
  }
1897
2473
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
2474
+ attachContainerHandlers();
1898
2475
  },
1899
2476
  requestAds: function requestAds(vastTagUrl) {
1900
2477
  return _async_to_generator(function() {
@@ -1957,10 +2534,6 @@ function createHlsAdPlayer(contentVideo, options) {
1957
2534
  currentAd = ads[0];
1958
2535
  currentAdMediaFile = void 0;
1959
2536
  console.log("[HlsAdPlayer] Pod parsed: ".concat(ads.length, ' ad(s), first="').concat(currentAd === null || currentAd === void 0 ? void 0 : currentAd.title, '", duration=').concat(currentAd === null || currentAd === void 0 ? void 0 : currentAd.duration, "s"));
1960
- if (currentAd) {
1961
- fireTrackingPixels(currentAd.trackingUrls.impression);
1962
- trackingFired.impression = true;
1963
- }
1964
2537
  return [
1965
2538
  2,
1966
2539
  Promise.resolve()
@@ -2000,7 +2573,7 @@ function createHlsAdPlayer(contentVideo, options) {
2000
2573
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
2001
2574
  }
2002
2575
  setupAdEventListeners();
2003
- resetQuartileTracking(true);
2576
+ resetAdTracking();
2004
2577
  contentVolume = contentVideo.volume;
2005
2578
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
2006
2579
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -2071,6 +2644,8 @@ function createHlsAdPlayer(contentVideo, options) {
2071
2644
  var previousMutedState;
2072
2645
  return _ts_generator(this, function(_state) {
2073
2646
  console.log("[HlsAdPlayer] Stopping ad");
2647
+ settleViewability();
2648
+ fireNotUsedForUnplayedAds();
2074
2649
  clearStallWatchdog();
2075
2650
  adPlaying = false;
2076
2651
  setAdPlayingFlag(false);
@@ -2101,6 +2676,8 @@ function createHlsAdPlayer(contentVideo, options) {
2101
2676
  },
2102
2677
  destroy: function destroy() {
2103
2678
  console.log("[HlsAdPlayer] Destroying");
2679
+ settleViewability();
2680
+ fireNotUsedForUnplayedAds();
2104
2681
  destroyed = true;
2105
2682
  clearStallWatchdog();
2106
2683
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2129,6 +2706,7 @@ function createHlsAdPlayer(contentVideo, options) {
2129
2706
  contentVideo.muted = originalMutedState;
2130
2707
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
2131
2708
  teardownAdEventListeners();
2709
+ detachContainerHandlers();
2132
2710
  releaseAdDecoder();
2133
2711
  currentAd = void 0;
2134
2712
  currentAdMediaFile = void 0;
@@ -2274,6 +2852,7 @@ function toDevSafeUrl(rawUrl) {
2274
2852
  // src/sdk/pal.ts
2275
2853
  var PAL_SDK_URL = "https://imasdk.googleapis.com/pal/sdkloader/pal.js";
2276
2854
  var _nonceLoader;
2855
+ var _nonceLoaderAllowStorage;
2277
2856
  var _palLoadPromise;
2278
2857
  function loadPalSdk() {
2279
2858
  var _window_goog;
@@ -2316,12 +2895,15 @@ function loadPalSdk() {
2316
2895
  });
2317
2896
  return _palLoadPromise;
2318
2897
  }
2319
- function getOrCreateNonceLoader() {
2320
- if (_nonceLoader) return _nonceLoader;
2898
+ function getOrCreateNonceLoader(allowStorage) {
2899
+ if (_nonceLoader && _nonceLoaderAllowStorage === allowStorage) {
2900
+ return _nonceLoader;
2901
+ }
2321
2902
  var goog = window.goog;
2322
2903
  var consentSettings = new goog.pal.ConsentSettings();
2323
- consentSettings.allowStorage = true;
2904
+ consentSettings.allowStorage = allowStorage;
2324
2905
  _nonceLoader = new goog.pal.NonceLoader(consentSettings);
2906
+ _nonceLoaderAllowStorage = allowStorage;
2325
2907
  return _nonceLoader;
2326
2908
  }
2327
2909
  function createPalNonceManager() {
@@ -2330,7 +2912,7 @@ function createPalNonceManager() {
2330
2912
  return {
2331
2913
  generateNonce: function generateNonce() {
2332
2914
  return _async_to_generator(function() {
2333
- var options, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
2915
+ var options, _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
2334
2916
  var _arguments = arguments;
2335
2917
  return _ts_generator(this, function(_state) {
2336
2918
  switch(_state.label){
@@ -2350,7 +2932,7 @@ function createPalNonceManager() {
2350
2932
  ];
2351
2933
  case 2:
2352
2934
  _state.sent();
2353
- loader = getOrCreateNonceLoader();
2935
+ loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
2354
2936
  goog = window.goog;
2355
2937
  request = new goog.pal.NonceRequest();
2356
2938
  request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
@@ -2535,6 +3117,8 @@ function ingestPlayerTracking(licenseKey, channel, body) {
2535
3117
  }
2536
3118
  // src/utils/vastEnvironmentSignals.ts
2537
3119
  var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3120
+ var WEB_SESSION_STORAGE_KEY = "stormcloud.web.sid";
3121
+ var inMemoryWebSessionId;
2538
3122
  var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
2539
3123
  var DEVICE_ID_STORAGE_KEYS = [
2540
3124
  "rdid",
@@ -2556,7 +3140,7 @@ function resolveVastEnvironmentSignals(isCtv) {
2556
3140
  var _ref;
2557
3141
  var bridgeSignals = readNativeBridgeSignals();
2558
3142
  var platformDevice = readPlatformNativeDeviceId();
2559
- var realDeviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
3143
+ var realDeviceId = bridgeSignals.deviceId || (isCtv ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
2560
3144
  var deviceId = realDeviceId;
2561
3145
  var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
2562
3146
  var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
@@ -2570,6 +3154,7 @@ function resolveVastEnvironmentSignals(isCtv) {
2570
3154
  limitAdTracking = (_ref1 = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref1 !== void 0 ? _ref1 : false;
2571
3155
  }
2572
3156
  }
3157
+ var deviceTypeHint = resolveDeviceTypeHint(isCtv);
2573
3158
  if (isCtv) {
2574
3159
  return _object_spread_props(_object_spread({
2575
3160
  isCtv: true,
@@ -2581,18 +3166,157 @@ function resolveVastEnvironmentSignals(isCtv) {
2581
3166
  } : {}, deviceId && limitAdTracking != null ? {
2582
3167
  limitAdTracking: limitAdTracking
2583
3168
  } : {}), {
2584
- deviceTypeHint: 5
3169
+ deviceTypeHint: deviceTypeHint
2585
3170
  });
2586
3171
  }
2587
- return _object_spread({
3172
+ var webSessionId = getOrCreateWebSessionId();
3173
+ return _object_spread_props(_object_spread({
2588
3174
  isCtv: false
2589
- }, deviceId ? {
3175
+ }, webSessionId ? {
3176
+ sessionId: webSessionId
3177
+ } : {}, deviceId ? {
2590
3178
  deviceId: deviceId
2591
3179
  } : {}, deviceId && deviceIdType ? {
2592
3180
  deviceIdType: deviceIdType
2593
3181
  } : {}, deviceId && limitAdTracking != null ? {
2594
3182
  limitAdTracking: limitAdTracking
2595
- } : {});
3183
+ } : {}), {
3184
+ deviceTypeHint: deviceTypeHint
3185
+ });
3186
+ }
3187
+ var DEVICE_TYPE_HINT = {
3188
+ FEATURE_PHONE: 1,
3189
+ SMARTPHONE: 2,
3190
+ DESKTOP: 3,
3191
+ TABLET: 4,
3192
+ CONNECTED_TV: 5,
3193
+ GAME_CONSOLE: 6,
3194
+ SET_TOP_BOX: 7
3195
+ };
3196
+ var DEVICE_TYPE_HINT_ALIASES = {
3197
+ featurephone: DEVICE_TYPE_HINT.FEATURE_PHONE,
3198
+ smartphone: DEVICE_TYPE_HINT.SMARTPHONE,
3199
+ mobile: DEVICE_TYPE_HINT.SMARTPHONE,
3200
+ phone: DEVICE_TYPE_HINT.SMARTPHONE,
3201
+ desktop: DEVICE_TYPE_HINT.DESKTOP,
3202
+ pc: DEVICE_TYPE_HINT.DESKTOP,
3203
+ tablet: DEVICE_TYPE_HINT.TABLET,
3204
+ ctv: DEVICE_TYPE_HINT.CONNECTED_TV,
3205
+ tv: DEVICE_TYPE_HINT.CONNECTED_TV,
3206
+ connectedtv: DEVICE_TYPE_HINT.CONNECTED_TV,
3207
+ smarttv: DEVICE_TYPE_HINT.CONNECTED_TV,
3208
+ console: DEVICE_TYPE_HINT.GAME_CONSOLE,
3209
+ gameconsole: DEVICE_TYPE_HINT.GAME_CONSOLE,
3210
+ stb: DEVICE_TYPE_HINT.SET_TOP_BOX,
3211
+ settopbox: DEVICE_TYPE_HINT.SET_TOP_BOX
3212
+ };
3213
+ var SET_TOP_BOX_UA = /LGSTB|\bSTB\b|STB\d|Set-?Top|SetTopBox|TV ?Box|Kaon|Humax|Arris|Technicolor|Sagemcom|Infomir|MAG\d{3}|KreaTV|Amino|Formuler|Dune ?HD|TiVo|MiBOX|Mi Box|SHIELD Android TV|\bAFT[A-Z]|Roku|AppleTV|Apple TV|CrKey/i;
3214
+ var GAME_CONSOLE_UA = /PlayStation|Xbox|Nintendo/i;
3215
+ var CONNECTED_TV_UA = /Web0S|webOS|Tizen|SMART-TV|SmartTV|NetCast|BRAVIA|HbbTV|VIDAA|Hisense|Philips|Viera|AQUOS|Android TV|Google TV|\bTV\b/i;
3216
+ var FEATURE_PHONE_UA = /KAIOS|MIDP|J2ME|Series40|Opera Mini/i;
3217
+ function resolveDeviceTypeHint(isCtv) {
3218
+ var override = readDeviceTypeHintOverride(isCtv);
3219
+ if (override != null) return override;
3220
+ return inferDeviceTypeHint(isCtv);
3221
+ }
3222
+ function inferDeviceTypeHint(isCtv) {
3223
+ var fallback = isCtv ? DEVICE_TYPE_HINT.CONNECTED_TV : DEVICE_TYPE_HINT.DESKTOP;
3224
+ if (typeof navigator === "undefined") return fallback;
3225
+ var ua = navigator.userAgent || "";
3226
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
3227
+ if (SET_TOP_BOX_UA.test(ua)) return DEVICE_TYPE_HINT.SET_TOP_BOX;
3228
+ if (GAME_CONSOLE_UA.test(ua)) return DEVICE_TYPE_HINT.GAME_CONSOLE;
3229
+ if (CONNECTED_TV_UA.test(ua) && !/Mobile/i.test(ua)) {
3230
+ return DEVICE_TYPE_HINT.CONNECTED_TV;
3231
+ }
3232
+ if (FEATURE_PHONE_UA.test(ua)) return DEVICE_TYPE_HINT.FEATURE_PHONE;
3233
+ if (/iPad/i.test(ua) || /Macintosh/i.test(ua) && maxTouchPoints > 1) {
3234
+ return DEVICE_TYPE_HINT.TABLET;
3235
+ }
3236
+ if (/iPhone|iPod/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3237
+ if (/Android/i.test(ua)) {
3238
+ if (/Mobile/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3239
+ if (maxTouchPoints === 0) return DEVICE_TYPE_HINT.SET_TOP_BOX;
3240
+ return DEVICE_TYPE_HINT.TABLET;
3241
+ }
3242
+ if (/Mobile|Windows Phone|BlackBerry/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3243
+ return fallback;
3244
+ }
3245
+ function readDeviceTypeHintOverride(isCtv) {
3246
+ if (typeof window === "undefined") return void 0;
3247
+ var keys = [
3248
+ "dth",
3249
+ "deviceTypeHint"
3250
+ ];
3251
+ var fromGlobal = normalizeDeviceTypeHint(window.__STORMCLOUD_DTH__);
3252
+ if (fromGlobal != null) return fromGlobal;
3253
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3254
+ try {
3255
+ for(var _iterator = getNativeBridgeSources()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3256
+ var source = _step.value;
3257
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
3258
+ try {
3259
+ for(var _iterator1 = keys[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
3260
+ var key = _step1.value;
3261
+ var value = source === null || source === void 0 ? void 0 : source[key];
3262
+ var normalized = normalizeDeviceTypeHint(typeof value === "function" ? safeCall(value, source) : value);
3263
+ if (normalized != null) return normalized;
3264
+ }
3265
+ } catch (err) {
3266
+ _didIteratorError1 = true;
3267
+ _iteratorError1 = err;
3268
+ } finally{
3269
+ try {
3270
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
3271
+ _iterator1.return();
3272
+ }
3273
+ } finally{
3274
+ if (_didIteratorError1) {
3275
+ throw _iteratorError1;
3276
+ }
3277
+ }
3278
+ }
3279
+ }
3280
+ } catch (err) {
3281
+ _didIteratorError = true;
3282
+ _iteratorError = err;
3283
+ } finally{
3284
+ try {
3285
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3286
+ _iterator.return();
3287
+ }
3288
+ } finally{
3289
+ if (_didIteratorError) {
3290
+ throw _iteratorError;
3291
+ }
3292
+ }
3293
+ }
3294
+ if (!isCtv) return void 0;
3295
+ for(var _i = 0, _iter = [
3296
+ "stormcloud.dth",
3297
+ "dth"
3298
+ ]; _i < _iter.length; _i++){
3299
+ var key1 = _iter[_i];
3300
+ var normalized1 = normalizeDeviceTypeHint(readStoredString(key1));
3301
+ if (normalized1 != null) return normalized1;
3302
+ }
3303
+ return void 0;
3304
+ }
3305
+ function normalizeDeviceTypeHint(value) {
3306
+ if (typeof value === "number") {
3307
+ return Number.isInteger(value) && value >= 1 && value <= 7 ? value : void 0;
3308
+ }
3309
+ if (typeof value !== "string") return void 0;
3310
+ var trimmed = value.trim();
3311
+ if (/^[1-7]$/.test(trimmed)) return parseInt(trimmed, 10);
3312
+ return DEVICE_TYPE_HINT_ALIASES[trimmed.toLowerCase().replace(/[\s_-]/g, "")];
3313
+ }
3314
+ function safeCall(fn, thisArg) {
3315
+ try {
3316
+ return fn.call(thisArg);
3317
+ } catch (unused) {
3318
+ return void 0;
3319
+ }
2596
3320
  }
2597
3321
  function inferDeviceIdType() {
2598
3322
  if (typeof navigator === "undefined") {
@@ -2616,9 +3340,10 @@ function isEquivalentDeviceIdType(tagType, runtimeType) {
2616
3340
  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2617
3341
  }
2618
3342
  function resolveNativeDeviceId() {
3343
+ var includeStored = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
2619
3344
  var bridgeSignals = readNativeBridgeSignals();
2620
3345
  var platformDevice = readPlatformNativeDeviceId();
2621
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
3346
+ var deviceId = bridgeSignals.deviceId || (includeStored ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
2622
3347
  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {
2623
3348
  return void 0;
2624
3349
  }
@@ -2647,6 +3372,21 @@ function getOrCreateCtvSessionId() {
2647
3372
  writePersistentId(CTV_SESSION_STORAGE_KEY, sessionId);
2648
3373
  return sessionId;
2649
3374
  }
3375
+ function getOrCreateWebSessionId() {
3376
+ if (typeof window === "undefined") return void 0;
3377
+ try {
3378
+ var _window_sessionStorage;
3379
+ var existing = (_window_sessionStorage = window.sessionStorage) === null || _window_sessionStorage === void 0 ? void 0 : _window_sessionStorage.getItem(WEB_SESSION_STORAGE_KEY);
3380
+ if (existing && !isMacroPlaceholder(existing)) return existing;
3381
+ } catch (unused) {}
3382
+ var sessionId = inMemoryWebSessionId || createUuid();
3383
+ inMemoryWebSessionId = sessionId;
3384
+ try {
3385
+ var _window_sessionStorage1;
3386
+ (_window_sessionStorage1 = window.sessionStorage) === null || _window_sessionStorage1 === void 0 ? void 0 : _window_sessionStorage1.setItem(WEB_SESSION_STORAGE_KEY, sessionId);
3387
+ } catch (unused) {}
3388
+ return sessionId;
3389
+ }
2650
3390
  function readPersistentId(storageKey) {
2651
3391
  return readStoredString(storageKey) || readCookie(storageKey);
2652
3392
  }
@@ -2798,22 +3538,9 @@ function isZeroedAdId(value) {
2798
3538
  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
2799
3539
  }
2800
3540
  function readNativeBridgeSignals() {
2801
- if (typeof window === "undefined") {
2802
- return {};
2803
- }
2804
- var candidates = [
2805
- window.__STORMCLOUD_CTV_AD_INFO__,
2806
- window.__STORMCLOUD_CTV__,
2807
- window.stormcloudCtv,
2808
- window.AiryTV,
2809
- window.Android,
2810
- window.webOS,
2811
- window.tizen,
2812
- window.amazon
2813
- ].filter(Boolean);
2814
3541
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2815
3542
  try {
2816
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3543
+ for(var _iterator = getNativeBridgeSources()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2817
3544
  var source = _step.value;
2818
3545
  var contentUrl = readBridgeValue(source, [
2819
3546
  "contentUrl",
@@ -2888,6 +3615,21 @@ function readNativeBridgeSignals() {
2888
3615
  }
2889
3616
  return {};
2890
3617
  }
3618
+ function getNativeBridgeSources() {
3619
+ if (typeof window === "undefined") {
3620
+ return [];
3621
+ }
3622
+ return [
3623
+ window.__STORMCLOUD_CTV_AD_INFO__,
3624
+ window.__STORMCLOUD_CTV__,
3625
+ window.stormcloudCtv,
3626
+ window.AiryTV,
3627
+ window.Android,
3628
+ window.webOS,
3629
+ window.tizen,
3630
+ window.amazon
3631
+ ].filter(Boolean);
3632
+ }
2891
3633
  function readBridgeValue(source, keys) {
2892
3634
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2893
3635
  try {
@@ -3246,7 +3988,7 @@ function sha256Hex(input) {
3246
3988
  })();
3247
3989
  }
3248
3990
  function resolvePlayerIdentitySeed(clientInfo) {
3249
- var nativeDeviceId = resolveNativeDeviceId();
3991
+ var nativeDeviceId = resolveNativeDeviceId(clientInfo.isSmartTV);
3250
3992
  if (nativeDeviceId) {
3251
3993
  return "device:".concat(nativeDeviceId);
3252
3994
  }
@@ -4015,6 +4757,12 @@ function applyDeviceIdentityParams(params, ctx) {
4015
4757
  params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
4016
4758
  return;
4017
4759
  }
4760
+ if (!ctx.isCtv) {
4761
+ params.delete("rdid");
4762
+ params.delete("idtype");
4763
+ params.delete("is_lat");
4764
+ return;
4765
+ }
4018
4766
  var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
4019
4767
  var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
4020
4768
  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
@@ -4169,15 +4917,24 @@ function applyVastMacros(baseUrl, ctx) {
4169
4917
  if (ctx.podMaxAds != null) {
4170
4918
  params.set("pmad", String(Math.max(1, Math.round(ctx.podMaxAds))));
4171
4919
  }
4172
- if (!ctx.isCtv && ctx.pageUrl) {
4173
- params.set("url", ctx.pageUrl);
4174
- params.set("description_url", ctx.pageUrl);
4175
- }
4176
4920
  var existingUrl = params.get("url") || "";
4177
4921
  if (EXAMPLE_COM_URL.test(existingUrl)) {
4178
4922
  params.delete("url");
4179
4923
  params.delete("description_url");
4180
4924
  }
4925
+ if (!ctx.isCtv && ctx.pageUrl) {
4926
+ if (isMacroPlaceholder2(params.get("url"))) {
4927
+ params.set("url", ctx.pageUrl);
4928
+ }
4929
+ if (isMacroPlaceholder2(params.get("description_url"))) {
4930
+ params.set("description_url", params.get("url") || ctx.pageUrl);
4931
+ }
4932
+ }
4933
+ if (!ctx.isCtv) {
4934
+ params.delete("an");
4935
+ params.delete("msid");
4936
+ params.delete("sid");
4937
+ }
4181
4938
  if (ctx.adWillPlayMuted != null) {
4182
4939
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
4183
4940
  }
@@ -4211,6 +4968,9 @@ function applyVastMacros(baseUrl, ctx) {
4211
4968
  if (ctx.programTitle) {
4212
4969
  params.set("ct_ti", ctx.programTitle);
4213
4970
  }
4971
+ if (ctx.channelName) {
4972
+ params.set("ct_ch", ctx.channelName);
4973
+ }
4214
4974
  var staleKeys = [];
4215
4975
  params.forEach(function(value, key) {
4216
4976
  if (isMacroPlaceholder2(value)) {
@@ -4263,8 +5023,10 @@ function fetchConsentSignals() {
4263
5023
  tcfApi("addEventListener", 2, function(tcData, success) {
4264
5024
  if (settled) return;
4265
5025
  if (success && tcData && (tcData.eventStatus === "tcloaded" || tcData.eventStatus === "useractioncomplete")) {
5026
+ var _tcData_purpose_consents, _tcData_purpose;
4266
5027
  settled = true;
4267
5028
  signals.gdpr = tcData.gdprApplies ? "1" : "0";
5029
+ signals.storageAllowed = tcData.gdprApplies ? ((_tcData_purpose = tcData.purpose) === null || _tcData_purpose === void 0 ? void 0 : (_tcData_purpose_consents = _tcData_purpose.consents) === null || _tcData_purpose_consents === void 0 ? void 0 : _tcData_purpose_consents[1]) === true : true;
4268
5030
  if (typeof tcData.tcString === "string" && tcData.tcString) {
4269
5031
  signals.gdprConsent = tcData.tcString;
4270
5032
  }
@@ -5797,7 +6559,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
5797
6559
  pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
5798
6560
  adWillPlayMuted: adWillPlayMuted,
5799
6561
  adWillAutoPlay: !!this.config.autoplay,
5800
- sessionId: envSignals.sessionId,
6562
+ sessionId: envSignals.isCtv || this.consentSignals.storageAllowed !== false ? envSignals.sessionId : void 0,
5801
6563
  deviceId: envSignals.deviceId,
5802
6564
  deviceIdType: envSignals.deviceIdType,
5803
6565
  limitAdTracking: envSignals.limitAdTracking,
@@ -5805,6 +6567,8 @@ var AdConfigManager = /*#__PURE__*/ function() {
5805
6567
  adTest: this.config.adTest
5806
6568
  }, this.config.programTitle ? {
5807
6569
  programTitle: this.config.programTitle
6570
+ } : {}, this.config.channelName ? {
6571
+ channelName: this.config.channelName
5808
6572
  } : {}), {
5809
6573
  consent: this.consentSignals
5810
6574
  }));
@@ -7344,6 +8108,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7344
8108
  console.log("[POD] Playing pod ad ".concat((payload === null || payload === void 0 ? void 0 : payload.index) != null ? payload.index + 1 : "?", "/").concat((_ref = payload === null || payload === void 0 ? void 0 : payload.total) !== null && _ref !== void 0 ? _ref : "?"));
7345
8109
  }
7346
8110
  });
8111
+ adPlayer.on("ad_click", function() {
8112
+ _this.host.onAdClick();
8113
+ });
8114
+ adPlayer.on("ad_interaction", function(event) {
8115
+ if (event) _this.host.onAdInteraction(event);
8116
+ });
7347
8117
  adPlayer.on("all_ads_completed", function() {
7348
8118
  sendAdImpressionTracking(_this.host.config.licenseKey, {
7349
8119
  source: "hls",
@@ -8873,6 +9643,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8873
9643
  },
8874
9644
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8875
9645
  return _this.generatePodVastUrl(base, breakDurationMs);
9646
+ },
9647
+ onAdClick: function onAdClick() {
9648
+ return _this.palNonce.sendAdClick();
9649
+ },
9650
+ onAdInteraction: function onAdInteraction(event) {
9651
+ return _this.palNonce.sendAdTouch(event);
8876
9652
  }
8877
9653
  }, this.timing, this.adConfig, this.cueManager, this.placeholder);
8878
9654
  }
@@ -8913,7 +9689,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8913
9689
  // ───────────────────────────────────────────────────────────────
8914
9690
  function load() {
8915
9691
  return _async_to_generator(function() {
8916
- var _this, _this_config_lowLatencyMode, error, palDescriptionUrl, continueLiveStreamDuringAds;
9692
+ var _this, error, palDescriptionUrl, continueLiveStreamDuringAds;
8917
9693
  return _ts_generator(this, function(_state) {
8918
9694
  switch(_state.label){
8919
9695
  case 0:
@@ -8949,19 +9725,25 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8949
9725
  4
8950
9726
  ];
8951
9727
  case 4:
8952
- palDescriptionUrl = this.adConfig.getPalDescriptionUrl();
8953
- this.palNonce.generateNonce(_object_spread({
8954
- videoWidth: this.video.offsetWidth || this.video.clientWidth || 640,
8955
- videoHeight: this.video.offsetHeight || this.video.clientHeight || 480,
8956
- adWillAutoPlay: !!this.config.autoplay,
8957
- adWillPlayMuted: true,
8958
- playerVolume: 0,
8959
- continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
8960
- }, palDescriptionUrl ? {
8961
- descriptionUrl: palDescriptionUrl
8962
- } : {})).catch(function() {});
8963
- fetchConsentSignals().then(function(signals) {
9728
+ palDescriptionUrl = this.config.ctvAdRequest ? this.adConfig.getPalDescriptionUrl() : void 0;
9729
+ fetchConsentSignals().catch(function() {
9730
+ return {};
9731
+ }).then(function(signals) {
9732
+ var _this_config_lowLatencyMode;
8964
9733
  _this.adConfig.consentSignals = signals;
9734
+ var muted = _this.video.muted;
9735
+ return _this.palNonce.generateNonce(_object_spread({
9736
+ videoWidth: _this.video.offsetWidth || _this.video.clientWidth || 640,
9737
+ videoHeight: _this.video.offsetHeight || _this.video.clientHeight || 480,
9738
+ adWillAutoPlay: !!_this.config.autoplay,
9739
+ adWillPlayMuted: muted,
9740
+ playerVolume: muted ? 0 : _this.video.volume,
9741
+ continuousPlayback: (_this_config_lowLatencyMode = _this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
9742
+ }, palDescriptionUrl ? {
9743
+ descriptionUrl: palDescriptionUrl
9744
+ } : {}, signals.storageAllowed != null ? {
9745
+ allowStorage: signals.storageAllowed
9746
+ } : {}));
8965
9747
  }).catch(function() {});
8966
9748
  this.adConfig.initializeTracking();
8967
9749
  if (!this.hlsEngine.shouldUseNativeHls(function() {
@@ -9683,7 +10465,7 @@ var CRITICAL_PROPS = [
9683
10465
  var CONTROLS_HIDE_DELAY = 3e3;
9684
10466
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
9685
10467
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9686
- var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, ctvAdRequest = props.ctvAdRequest, programTitle = props.programTitle, restVideoAttrs = _object_without_properties(props, [
10468
+ var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, ctvAdRequest = props.ctvAdRequest, programTitle = props.programTitle, channelName = props.channelName, restVideoAttrs = _object_without_properties(props, [
9687
10469
  "src",
9688
10470
  "autoplay",
9689
10471
  "muted",
@@ -9715,7 +10497,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9715
10497
  "vmapUrl",
9716
10498
  "minSegmentsBeforePlay",
9717
10499
  "ctvAdRequest",
9718
- "programTitle"
10500
+ "programTitle",
10501
+ "channelName"
9719
10502
  ]);
9720
10503
  var videoRef = (0, import_react.useRef)(null);
9721
10504
  var playerRef = (0, import_react.useRef)(null);
@@ -9907,6 +10690,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9907
10690
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
9908
10691
  if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;
9909
10692
  if (programTitle !== void 0) cfg.programTitle = programTitle;
10693
+ if (channelName !== void 0) cfg.channelName = channelName;
9910
10694
  var player = new StormcloudVideoPlayer(cfg);
9911
10695
  playerRef.current = player;
9912
10696
  player.load().then(function() {