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
@@ -612,6 +612,7 @@ var KNOWN_VAST_MACROS = /* @__PURE__ */ new Set([
612
612
  "PLAYERSIZE",
613
613
  "PLAYERSTATE",
614
614
  "PODSEQUENCE",
615
+ "REASON",
615
616
  "REGULATIONS",
616
617
  "SERVERSIDE",
617
618
  "SERVERUA",
@@ -670,6 +671,10 @@ function resolveMacroValues(ctx) {
670
671
  if (ctx.podSequence != null) {
671
672
  set("PODSEQUENCE", String(ctx.podSequence));
672
673
  }
674
+ set("ADSERVINGID", ctx.adServingId);
675
+ if (ctx.reason != null && ctx.reason !== "") {
676
+ set("REASON", String(ctx.reason));
677
+ }
673
678
  return values;
674
679
  }
675
680
  function substituteVastTrackingMacros(url) {
@@ -686,10 +691,72 @@ function substituteVastTrackingMacros(url) {
686
691
  });
687
692
  }
688
693
  // src/sdk/hlsAdPlayer.ts
694
+ var LINEAR_TRACKING_EVENTS = [
695
+ "creativeView",
696
+ "loaded",
697
+ "start",
698
+ "firstQuartile",
699
+ "midpoint",
700
+ "thirdQuartile",
701
+ "complete",
702
+ "mute",
703
+ "unmute",
704
+ "pause",
705
+ "resume",
706
+ "fullscreen",
707
+ "exitFullscreen",
708
+ "playerExpand",
709
+ "playerCollapse",
710
+ "notUsed"
711
+ ];
712
+ function textOf(el) {
713
+ var _el_textContent;
714
+ var value = el === null || el === void 0 ? void 0 : (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
715
+ return value ? value : void 0;
716
+ }
717
+ function parseVastTime(value) {
718
+ if (!value) return void 0;
719
+ var parts = value.trim().split(":");
720
+ if (parts.length !== 3) return void 0;
721
+ var _parts_map = _sliced_to_array(parts.map(function(p) {
722
+ return parseFloat(p);
723
+ }), 3), h = _parts_map[0], m = _parts_map[1], s = _parts_map[2];
724
+ if (![
725
+ h,
726
+ m,
727
+ s
728
+ ].every(function(n) {
729
+ return n !== void 0 && Number.isFinite(n);
730
+ })) {
731
+ return void 0;
732
+ }
733
+ return h * 3600 + m * 60 + s;
734
+ }
735
+ function parseProgressOffset(offset) {
736
+ if (!offset) return void 0;
737
+ var trimmed = offset.trim();
738
+ if (trimmed.endsWith("%")) {
739
+ var percent = parseFloat(trimmed);
740
+ return Number.isFinite(percent) ? {
741
+ offsetPercent: percent
742
+ } : void 0;
743
+ }
744
+ var seconds = parseVastTime(trimmed);
745
+ return seconds !== void 0 ? {
746
+ offsetSeconds: seconds
747
+ } : void 0;
748
+ }
689
749
  var MAX_VAST_WRAPPER_DEPTH = 5;
690
750
  var BEACON_TIMEOUT_MS = 3e4;
691
751
  var inFlightBeacons = /* @__PURE__ */ new Set();
692
752
  var VAST_ERROR_MEDIA_DISPLAY = 405;
753
+ var VAST_ERROR_WRAPPER_TIMEOUT = 301;
754
+ var VAST_ERROR_WRAPPER_LIMIT = 302;
755
+ var VAST_ERROR_WRAPPER_NO_ADS = 303;
756
+ var VAST_ERROR_NO_SUPPORTED_MEDIA = 403;
757
+ var VERIFICATION_NOT_SUPPORTED_REASON = 2;
758
+ var VIEWABLE_MIN_VISIBLE_RATIO = 0.5;
759
+ var VIEWABLE_MIN_CONTINUOUS_S = 2;
693
760
  function toVastMediaErrorCode(error) {
694
761
  switch(error === null || error === void 0 ? void 0 : error.code){
695
762
  case 1:
@@ -717,6 +784,7 @@ function createHlsAdPlayer(contentVideo, options) {
717
784
  var adHls;
718
785
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
719
786
  var adEventHandlers = [];
787
+ var containerHandlers = [];
720
788
  var currentAd;
721
789
  var currentAdMediaFile;
722
790
  var podAds = [];
@@ -734,14 +802,28 @@ function createHlsAdPlayer(contentVideo, options) {
734
802
  var sawDecodedVideoFrame = false;
735
803
  var videoFrameCallbackHandle;
736
804
  var pendingPlayPromise;
737
- var trackingFired = {
738
- impression: false,
739
- start: false,
740
- firstQuartile: false,
741
- midpoint: false,
742
- thirdQuartile: false,
743
- complete: false
744
- };
805
+ function createTrackingState() {
806
+ return {
807
+ impression: false,
808
+ loaded: false,
809
+ start: false,
810
+ firstQuartile: false,
811
+ midpoint: false,
812
+ thirdQuartile: false,
813
+ complete: false,
814
+ viewabilitySettled: false,
815
+ lastMuted: void 0,
816
+ progressFired: /* @__PURE__ */ new Set()
817
+ };
818
+ }
819
+ var trackingFired = createTrackingState();
820
+ var resolvedAds = /* @__PURE__ */ new Set();
821
+ var viewObserver;
822
+ var visibleRatio = 0;
823
+ var continuousVisibleS = 0;
824
+ var lastViewSampleTime;
825
+ var lastPlayerExpanded = false;
826
+ var documentHandlers = [];
745
827
  function emit(event, payload) {
746
828
  var set = listeners.get(event);
747
829
  if (!set) return;
@@ -770,7 +852,11 @@ function createHlsAdPlayer(contentVideo, options) {
770
852
  }
771
853
  }
772
854
  }
773
- function buildTrackingMacroContext(errorCode) {
855
+ function buildTrackingMacroContext() {
856
+ var options2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
857
+ var _options2_ad;
858
+ var errorCode = options2.errorCode, reason = options2.reason;
859
+ var ad = (_options2_ad = options2.ad) !== null && _options2_ad !== void 0 ? _options2_ad : currentAd;
774
860
  var context = {
775
861
  adPlayheadSeconds: adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.currentTime,
776
862
  contentPlayheadSeconds: contentVideo.currentTime,
@@ -791,11 +877,17 @@ function createHlsAdPlayer(contentVideo, options) {
791
877
  if (podAds.length > 0) {
792
878
  context.podSequence = podIndex + 1;
793
879
  }
880
+ if (ad === null || ad === void 0 ? void 0 : ad.adServingId) {
881
+ context.adServingId = ad.adServingId;
882
+ }
883
+ if (reason != null) {
884
+ context.reason = reason;
885
+ }
794
886
  return context;
795
887
  }
796
888
  function fireTrackingPixels(urls, options2) {
797
889
  if (!urls || urls.length === 0) return;
798
- var macroContext = buildTrackingMacroContext(options2 === null || options2 === void 0 ? void 0 : options2.errorCode);
890
+ var macroContext = buildTrackingMacroContext(options2);
799
891
  urls.forEach(function(url) {
800
892
  try {
801
893
  var trackingUrl = substituteVastTrackingMacros(url, macroContext);
@@ -906,8 +998,8 @@ function createHlsAdPlayer(contentVideo, options) {
906
998
  var url = (mediaFile.url.toLowerCase().split("?")[0] || "").trim();
907
999
  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");
908
1000
  }
909
- function collectVideoMediaFiles(scope, verbose) {
910
- var mediaFileElements = scope.querySelectorAll("MediaFile");
1001
+ function collectVideoMediaFiles(linear, verbose) {
1002
+ var mediaFileElements = linear.querySelectorAll(":scope > MediaFiles > MediaFile");
911
1003
  var mediaFiles = [];
912
1004
  if (verbose) {
913
1005
  console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
@@ -927,6 +1019,13 @@ function createHlsAdPlayer(contentVideo, options) {
927
1019
  }
928
1020
  return;
929
1021
  }
1022
+ var apiFramework = (mf.getAttribute("apiFramework") || "").toUpperCase();
1023
+ if (apiFramework === "VPAID") {
1024
+ if (verbose) {
1025
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, " ignored (VPAID creatives are not supported)"));
1026
+ }
1027
+ return;
1028
+ }
930
1029
  var bitrateAttr = mf.getAttribute("bitrate");
931
1030
  var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
932
1031
  var mediaFile = {
@@ -957,114 +1056,144 @@ function createHlsAdPlayer(contentVideo, options) {
957
1056
  return mediaFiles;
958
1057
  }
959
1058
  function createEmptyTrackingUrls() {
960
- return {
1059
+ var urls = {
961
1060
  impression: [],
962
- start: [],
963
- firstQuartile: [],
964
- midpoint: [],
965
- thirdQuartile: [],
966
- complete: [],
967
- mute: [],
968
- unmute: [],
969
- pause: [],
970
- resume: [],
971
- fullscreen: [],
972
- exitFullscreen: [],
973
- skip: [],
974
- error: []
1061
+ clickTracking: [],
1062
+ error: [],
1063
+ viewable: [],
1064
+ notViewable: [],
1065
+ viewUndetermined: [],
1066
+ verificationNotExecuted: [],
1067
+ progress: []
975
1068
  };
1069
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1070
+ try {
1071
+ for(var _iterator = LINEAR_TRACKING_EVENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1072
+ var event = _step.value;
1073
+ urls[event] = [];
1074
+ }
1075
+ } catch (err) {
1076
+ _didIteratorError = true;
1077
+ _iteratorError = err;
1078
+ } finally{
1079
+ try {
1080
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1081
+ _iterator.return();
1082
+ }
1083
+ } finally{
1084
+ if (_didIteratorError) {
1085
+ throw _iteratorError;
1086
+ }
1087
+ }
1088
+ }
1089
+ return urls;
976
1090
  }
977
- function extractTrackingUrls(scope) {
978
- var trackingUrls = createEmptyTrackingUrls();
979
- scope.querySelectorAll("Impression").forEach(function(el) {
980
- var _el_textContent;
981
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
982
- if (url) trackingUrls.impression.push(url);
1091
+ function pushUrls(target, elements) {
1092
+ elements.forEach(function(el) {
1093
+ var url = textOf(el);
1094
+ if (url) target.push(url);
983
1095
  });
984
- scope.querySelectorAll("Tracking").forEach(function(el) {
985
- var _el_textContent;
1096
+ }
1097
+ function collectLinearTracking(linear, into) {
1098
+ linear.querySelectorAll(":scope > TrackingEvents > Tracking").forEach(function(el) {
986
1099
  var event = el.getAttribute("event");
987
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
988
- if (event && url) {
989
- var eventKey = event;
990
- if (trackingUrls[eventKey]) {
991
- trackingUrls[eventKey].push(url);
992
- }
1100
+ var url = textOf(el);
1101
+ if (!event || !url) return;
1102
+ if (event === "progress") {
1103
+ var offset = parseProgressOffset(el.getAttribute("offset"));
1104
+ if (offset) into.progress.push(_object_spread({
1105
+ url: url
1106
+ }, offset));
1107
+ return;
1108
+ }
1109
+ if (LINEAR_TRACKING_EVENTS.indexOf(event) !== -1) {
1110
+ into[event].push(url);
993
1111
  }
994
1112
  });
995
- scope.querySelectorAll("Error").forEach(function(el) {
996
- var _el_textContent;
997
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
998
- if (url) trackingUrls.error.push(url);
1113
+ pushUrls(into.clickTracking, linear.querySelectorAll(":scope > VideoClicks > ClickTracking"));
1114
+ }
1115
+ function collectAdLevelTracking(adBody, into) {
1116
+ pushUrls(into.impression, adBody.querySelectorAll(":scope > Impression"));
1117
+ pushUrls(into.error, adBody.querySelectorAll(":scope > Error"));
1118
+ pushUrls(into.viewable, adBody.querySelectorAll(":scope > ViewableImpression > Viewable"));
1119
+ pushUrls(into.notViewable, adBody.querySelectorAll(":scope > ViewableImpression > NotViewable"));
1120
+ pushUrls(into.viewUndetermined, adBody.querySelectorAll(":scope > ViewableImpression > ViewUndetermined"));
1121
+ adBody.querySelectorAll(':scope > AdVerifications > Verification, :scope > Extensions > Extension[type="AdVerifications"] > AdVerifications > Verification').forEach(function(verification) {
1122
+ pushUrls(into.verificationNotExecuted, verification.querySelectorAll(':scope > TrackingEvents > Tracking[event="verificationNotExecuted"]'));
999
1123
  });
1000
- return trackingUrls;
1001
1124
  }
1002
1125
  function mergeTrackingUrls(target, source) {
1003
- Object.keys(target).forEach(function(key) {
1004
- if (source[key] && source[key].length > 0) {
1005
- target[key] = target[key].concat(source[key]);
1126
+ var targetLists = target;
1127
+ var sourceLists = source;
1128
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1129
+ try {
1130
+ for(var _iterator = Object.keys(targetLists)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1131
+ var key = _step.value;
1132
+ var incoming = sourceLists[key];
1133
+ if (incoming && incoming.length > 0) {
1134
+ targetLists[key] = targetLists[key].concat(incoming);
1135
+ }
1006
1136
  }
1007
- });
1137
+ } catch (err) {
1138
+ _didIteratorError = true;
1139
+ _iteratorError = err;
1140
+ } finally{
1141
+ try {
1142
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1143
+ _iterator.return();
1144
+ }
1145
+ } finally{
1146
+ if (_didIteratorError) {
1147
+ throw _iteratorError;
1148
+ }
1149
+ }
1150
+ }
1008
1151
  return target;
1009
1152
  }
1153
+ function parseXml(xmlString) {
1154
+ var xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
1155
+ var parserError = xmlDoc.querySelector("parsererror");
1156
+ if (parserError) {
1157
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1158
+ return null;
1159
+ }
1160
+ return xmlDoc;
1161
+ }
1162
+ function getAdSequence(adElement) {
1163
+ var sequence = parseInt(adElement.getAttribute("sequence") || "", 10);
1164
+ return Number.isFinite(sequence) ? sequence : void 0;
1165
+ }
1166
+ function emptyVastResult(root) {
1167
+ var errorUrls = [];
1168
+ pushUrls(errorUrls, root.querySelectorAll(":scope > Error"));
1169
+ return {
1170
+ type: "empty",
1171
+ errorUrls: errorUrls,
1172
+ errorCode: VAST_ERROR_WRAPPER_NO_ADS
1173
+ };
1174
+ }
1010
1175
  function parseVastXml(xmlString) {
1011
1176
  try {
1012
- var _xmlDoc_querySelector, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent1, _xmlDoc_querySelector2, _xmlDoc_querySelector3;
1013
- var parser = new DOMParser();
1014
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
1015
- var parserError = xmlDoc.querySelector("parsererror");
1016
- if (parserError) {
1017
- console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1018
- return {
1019
- type: "empty"
1020
- };
1021
- }
1022
- var adElement = xmlDoc.querySelector("Ad");
1177
+ var _adElements_find;
1178
+ var xmlDoc = parseXml(xmlString);
1179
+ if (!xmlDoc) return {
1180
+ type: "empty"
1181
+ };
1182
+ var root = xmlDoc.documentElement;
1183
+ var adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1184
+ var adElement = (_adElements_find = adElements.find(function(el) {
1185
+ return getAdSequence(el) === void 0;
1186
+ })) !== null && _adElements_find !== void 0 ? _adElements_find : adElements[0];
1023
1187
  if (!adElement) {
1024
- console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
1025
- return {
1026
- type: "empty"
1027
- };
1188
+ var _root_getAttribute;
1189
+ console.warn("[HlsAdPlayer] No Ad element found in VAST ".concat((_root_getAttribute = root.getAttribute("version")) !== null && _root_getAttribute !== void 0 ? _root_getAttribute : "", " response"));
1190
+ return emptyVastResult(root);
1028
1191
  }
1029
- var adId = adElement.getAttribute("id") || "unknown";
1030
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
1031
- 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();
1032
- 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();
1033
- if (wrapperUri) {
1034
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(wrapperUri));
1035
- return {
1036
- type: "wrapper",
1037
- vastAdTagUri: wrapperUri,
1038
- trackingUrls: extractTrackingUrls(xmlDoc),
1039
- clickThrough: clickThrough
1040
- };
1041
- }
1042
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
1043
- var durationText = ((_xmlDoc_querySelector3 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector3 === void 0 ? void 0 : _xmlDoc_querySelector3.textContent) || "00:00:30";
1044
- var durationParts = durationText.split(":");
1045
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
1046
- var mediaFiles = collectVideoMediaFiles(xmlDoc, true);
1047
- if (mediaFiles.length === 0) {
1048
- if (isNoAdAvailable) {
1049
- console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1050
- } else {
1051
- console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1052
- }
1053
- return {
1054
- type: "empty"
1055
- };
1192
+ var parsed = parseAdElement(adElement, true);
1193
+ if (parsed.type === "wrapper") {
1194
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
1056
1195
  }
1057
- return {
1058
- type: "inline",
1059
- ad: {
1060
- id: adId,
1061
- title: title,
1062
- duration: duration,
1063
- mediaFiles: mediaFiles,
1064
- trackingUrls: extractTrackingUrls(xmlDoc),
1065
- clickThrough: clickThrough
1066
- }
1067
- };
1196
+ return parsed;
1068
1197
  } catch (error) {
1069
1198
  console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
1070
1199
  return {
@@ -1073,48 +1202,101 @@ function createHlsAdPlayer(contentVideo, options) {
1073
1202
  }
1074
1203
  }
1075
1204
  function parseAdElement(adElement) {
1205
+ var verbose = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
1076
1206
  try {
1077
- var _adElement_querySelector, _adElement_querySelector_textContent, _adElement_querySelector1, _adElement_querySelector_textContent1, _adElement_querySelector2, _adElement_querySelector3;
1078
- var adId = adElement.getAttribute("id") || "unknown";
1079
- var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
1080
- 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();
1081
- 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();
1082
- if (wrapperUri) {
1207
+ var _parseVastTime;
1208
+ var wrapper = adElement.querySelector(":scope > Wrapper");
1209
+ if (wrapper) {
1210
+ var vastAdTagUri = textOf(wrapper.querySelector(":scope > VASTAdTagURI"));
1211
+ if (!vastAdTagUri) {
1212
+ console.warn("[HlsAdPlayer] <Wrapper> has no VASTAdTagURI");
1213
+ return {
1214
+ type: "empty"
1215
+ };
1216
+ }
1217
+ var trackingUrls2 = createEmptyTrackingUrls();
1218
+ collectAdLevelTracking(wrapper, trackingUrls2);
1219
+ wrapper.querySelectorAll(":scope > Creatives > Creative > Linear").forEach(function(linear2) {
1220
+ return collectLinearTracking(linear2, trackingUrls2);
1221
+ });
1083
1222
  return {
1084
1223
  type: "wrapper",
1085
- vastAdTagUri: wrapperUri,
1086
- trackingUrls: extractTrackingUrls(adElement),
1087
- clickThrough: clickThrough
1224
+ vastAdTagUri: vastAdTagUri,
1225
+ trackingUrls: trackingUrls2,
1226
+ rules: {
1227
+ followAdditionalWrappers: wrapper.getAttribute("followAdditionalWrappers") !== "false"
1228
+ }
1088
1229
  };
1089
1230
  }
1090
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
1091
- var durationText = ((_adElement_querySelector3 = adElement.querySelector("Duration")) === null || _adElement_querySelector3 === void 0 ? void 0 : _adElement_querySelector3.textContent) || "00:00:30";
1092
- var durationParts = durationText.split(":");
1093
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
1094
- var mediaFiles = collectVideoMediaFiles(adElement, false);
1095
- if (mediaFiles.length === 0) {
1096
- if (isNoAdAvailable) {
1097
- console.warn("[HlsAdPlayer] Pod <Ad> indicates no ad available");
1098
- } else {
1099
- console.warn("[HlsAdPlayer] No supported media files in pod <Ad>");
1100
- }
1231
+ var inLine = adElement.querySelector(":scope > InLine");
1232
+ if (!inLine) {
1233
+ console.warn("[HlsAdPlayer] <Ad> has neither <InLine> nor <Wrapper>");
1101
1234
  return {
1102
1235
  type: "empty"
1103
1236
  };
1104
1237
  }
1238
+ var errorUrls = [];
1239
+ pushUrls(errorUrls, inLine.querySelectorAll(":scope > Error"));
1240
+ if (adElement.getAttribute("conditionalAd") === "true") {
1241
+ console.warn("[HlsAdPlayer] Skipping conditional <Ad> (VPAID-only)");
1242
+ return {
1243
+ type: "empty",
1244
+ errorUrls: errorUrls,
1245
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1246
+ };
1247
+ }
1248
+ var linear;
1249
+ var mediaFiles = [];
1250
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1251
+ try {
1252
+ for(var _iterator = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear"))[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1253
+ var candidate = _step.value;
1254
+ var files = collectVideoMediaFiles(candidate, verbose);
1255
+ if (files.length > 0) {
1256
+ linear = candidate;
1257
+ mediaFiles = files;
1258
+ break;
1259
+ }
1260
+ }
1261
+ } catch (err) {
1262
+ _didIteratorError = true;
1263
+ _iteratorError = err;
1264
+ } finally{
1265
+ try {
1266
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1267
+ _iterator.return();
1268
+ }
1269
+ } finally{
1270
+ if (_didIteratorError) {
1271
+ throw _iteratorError;
1272
+ }
1273
+ }
1274
+ }
1275
+ if (!linear) {
1276
+ console.warn("[HlsAdPlayer] No supported linear media files in <Ad>");
1277
+ return {
1278
+ type: "empty",
1279
+ errorUrls: errorUrls,
1280
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1281
+ };
1282
+ }
1283
+ var trackingUrls = createEmptyTrackingUrls();
1284
+ collectAdLevelTracking(inLine, trackingUrls);
1285
+ collectLinearTracking(linear, trackingUrls);
1105
1286
  return {
1106
1287
  type: "inline",
1107
1288
  ad: {
1108
- id: adId,
1109
- title: title,
1110
- duration: duration,
1289
+ id: adElement.getAttribute("id") || "unknown",
1290
+ title: textOf(inLine.querySelector(":scope > AdTitle")) || "Ad",
1291
+ duration: (_parseVastTime = parseVastTime(textOf(linear.querySelector(":scope > Duration")))) !== null && _parseVastTime !== void 0 ? _parseVastTime : 30,
1111
1292
  mediaFiles: mediaFiles,
1112
- trackingUrls: extractTrackingUrls(adElement),
1113
- clickThrough: clickThrough
1293
+ trackingUrls: trackingUrls,
1294
+ clickThrough: textOf(linear.querySelector(":scope > VideoClicks > ClickThrough")),
1295
+ adServingId: textOf(inLine.querySelector(":scope > AdServingId"))
1114
1296
  }
1115
1297
  };
1116
1298
  } catch (error) {
1117
- console.error("[HlsAdPlayer] Error parsing pod <Ad> element:", error);
1299
+ console.error("[HlsAdPlayer] Error parsing <Ad> element:", error);
1118
1300
  return {
1119
1301
  type: "empty"
1120
1302
  };
@@ -1193,30 +1375,63 @@ function createHlsAdPlayer(contentVideo, options) {
1193
1375
  }
1194
1376
  function fetchAndParseVastAd(_0) {
1195
1377
  return _async_to_generator(function(vastTagUrl) {
1196
- var depth, accumulatedTracking, vastXml, parsed;
1378
+ var depth, accumulatedTracking, rules, vastXml, error, parsed, _parsed_errorUrls, _parsed_errorCode;
1197
1379
  var _arguments = arguments;
1198
1380
  return _ts_generator(this, function(_state) {
1199
1381
  switch(_state.label){
1200
1382
  case 0:
1201
- depth = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : 0, accumulatedTracking = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : createEmptyTrackingUrls();
1383
+ 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] : {
1384
+ followAdditionalWrappers: true
1385
+ };
1386
+ _state.label = 1;
1387
+ case 1:
1388
+ _state.trys.push([
1389
+ 1,
1390
+ 3,
1391
+ ,
1392
+ 4
1393
+ ]);
1202
1394
  return [
1203
1395
  4,
1204
1396
  fetchVastXml(vastTagUrl, depth === 0 ? "include" : "omit")
1205
1397
  ];
1206
- case 1:
1398
+ case 2:
1207
1399
  vastXml = _state.sent();
1400
+ return [
1401
+ 3,
1402
+ 4
1403
+ ];
1404
+ case 3:
1405
+ error = _state.sent();
1406
+ if (depth === 0) throw error;
1407
+ console.warn("[HlsAdPlayer] Wrapped VAST request failed:", error);
1408
+ fireTrackingPixels(accumulatedTracking.error, {
1409
+ errorCode: VAST_ERROR_WRAPPER_TIMEOUT
1410
+ });
1411
+ return [
1412
+ 2,
1413
+ null
1414
+ ];
1415
+ case 4:
1208
1416
  console.log("[HlsAdPlayer] VAST XML received");
1209
1417
  console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1210
1418
  parsed = parseVastXml(vastXml);
1211
1419
  if (parsed.type === "empty") {
1420
+ ;
1421
+ fireTrackingPixels(((_parsed_errorUrls = parsed.errorUrls) !== null && _parsed_errorUrls !== void 0 ? _parsed_errorUrls : []).concat(accumulatedTracking.error), {
1422
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1423
+ });
1212
1424
  return [
1213
1425
  2,
1214
1426
  null
1215
1427
  ];
1216
1428
  }
1217
1429
  if (parsed.type === "wrapper") {
1218
- if (depth >= MAX_VAST_WRAPPER_DEPTH) {
1219
- console.warn("[HlsAdPlayer] VAST wrapper depth limit (".concat(MAX_VAST_WRAPPER_DEPTH, ") reached, aborting redirect chain"));
1430
+ if (depth >= MAX_VAST_WRAPPER_DEPTH || !rules.followAdditionalWrappers) {
1431
+ 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');
1432
+ fireTrackingPixels(accumulatedTracking.error.concat(parsed.trackingUrls.error), {
1433
+ errorCode: VAST_ERROR_WRAPPER_LIMIT
1434
+ });
1220
1435
  return [
1221
1436
  2,
1222
1437
  null
@@ -1225,7 +1440,7 @@ function createHlsAdPlayer(contentVideo, options) {
1225
1440
  mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);
1226
1441
  return [
1227
1442
  2,
1228
- fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking)
1443
+ fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking, parsed.rules)
1229
1444
  ];
1230
1445
  }
1231
1446
  mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);
@@ -1239,7 +1454,7 @@ function createHlsAdPlayer(contentVideo, options) {
1239
1454
  }
1240
1455
  function fetchAndParsePod(vastTagUrl) {
1241
1456
  return _async_to_generator(function() {
1242
- var vastXml, trimmedXml, parser, xmlDoc, adElements, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, adElement, parsed, resolved, error, err;
1457
+ 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;
1243
1458
  return _ts_generator(this, function(_state) {
1244
1459
  switch(_state.label){
1245
1460
  case 0:
@@ -1258,125 +1473,212 @@ function createHlsAdPlayer(contentVideo, options) {
1258
1473
  []
1259
1474
  ];
1260
1475
  }
1261
- parser = new DOMParser();
1262
- xmlDoc = parser.parseFromString(vastXml, "text/xml");
1263
- if (xmlDoc.querySelector("parsererror")) {
1264
- console.error("[HlsAdPlayer] Pod VAST XML parsing error (malformed). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1476
+ xmlDoc = parseXml(vastXml);
1477
+ if (!xmlDoc) {
1478
+ console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1265
1479
  return [
1266
1480
  2,
1267
1481
  []
1268
1482
  ];
1269
1483
  }
1270
- adElements = Array.from(xmlDoc.querySelectorAll("Ad"));
1484
+ root = xmlDoc.documentElement;
1485
+ adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1271
1486
  if (adElements.length === 0) {
1272
- console.warn("[HlsAdPlayer] No <Ad> elements found in pod VAST response (no fill). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1487
+ ;
1488
+ ;
1489
+ 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)"));
1490
+ empty = emptyVastResult(root);
1491
+ if (empty.type === "empty" && ((_empty_errorUrls = empty.errorUrls) === null || _empty_errorUrls === void 0 ? void 0 : _empty_errorUrls.length)) {
1492
+ ;
1493
+ fireTrackingPixels(empty.errorUrls, {
1494
+ errorCode: (_empty_errorCode = empty.errorCode) !== null && _empty_errorCode !== void 0 ? _empty_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1495
+ });
1496
+ }
1273
1497
  return [
1274
1498
  2,
1275
1499
  []
1276
1500
  ];
1277
1501
  }
1278
- adElements.sort(function(a, b) {
1279
- var aSeq = parseInt(a.getAttribute("sequence") || "", 10);
1280
- var bSeq = parseInt(b.getAttribute("sequence") || "", 10);
1281
- var aVal = Number.isFinite(aSeq) ? aSeq : Number.MAX_SAFE_INTEGER;
1282
- var bVal = Number.isFinite(bSeq) ? bSeq : Number.MAX_SAFE_INTEGER;
1283
- return aVal - bVal;
1502
+ resolveAd = function resolveAd(adElement) {
1503
+ return _async_to_generator(function() {
1504
+ var _parsed_errorUrls, parsed, _parsed_errorCode;
1505
+ return _ts_generator(this, function(_state) {
1506
+ parsed = parseAdElement(adElement);
1507
+ if (parsed.type === "inline") return [
1508
+ 2,
1509
+ parsed.ad
1510
+ ];
1511
+ if (parsed.type === "wrapper") {
1512
+ return [
1513
+ 2,
1514
+ fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls, parsed.rules)
1515
+ ];
1516
+ }
1517
+ if ((_parsed_errorUrls = parsed.errorUrls) === null || _parsed_errorUrls === void 0 ? void 0 : _parsed_errorUrls.length) {
1518
+ ;
1519
+ fireTrackingPixels(parsed.errorUrls, {
1520
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_NO_SUPPORTED_MEDIA
1521
+ });
1522
+ }
1523
+ return [
1524
+ 2,
1525
+ null
1526
+ ];
1527
+ });
1528
+ })();
1529
+ };
1530
+ podElements = adElements.filter(function(el) {
1531
+ return getAdSequence(el) !== void 0;
1532
+ }).sort(function(a, b) {
1533
+ return getAdSequence(a) - getAdSequence(b);
1534
+ });
1535
+ buffet = adElements.filter(function(el) {
1536
+ return getAdSequence(el) === void 0;
1284
1537
  });
1285
1538
  ads = [];
1539
+ if (!(podElements.length === 0)) return [
1540
+ 3,
1541
+ 10
1542
+ ];
1286
1543
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1287
1544
  _state.label = 2;
1288
1545
  case 2:
1289
1546
  _state.trys.push([
1290
1547
  2,
1291
- 10,
1292
- 11,
1293
- 12
1548
+ 7,
1549
+ 8,
1550
+ 9
1294
1551
  ]);
1295
- _iterator = adElements[Symbol.iterator]();
1552
+ _iterator = buffet[Symbol.iterator]();
1296
1553
  _state.label = 3;
1297
1554
  case 3:
1298
1555
  if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
1299
1556
  3,
1300
- 9
1557
+ 6
1301
1558
  ];
1302
1559
  adElement = _step.value;
1303
- parsed = parseAdElement(adElement);
1304
- if (!(parsed.type === "inline")) return [
1305
- 3,
1306
- 4
1307
- ];
1308
- ads.push(parsed.ad);
1309
1560
  return [
1310
- 3,
1311
- 8
1561
+ 4,
1562
+ resolveAd(adElement)
1312
1563
  ];
1313
1564
  case 4:
1314
- if (!(parsed.type === "wrapper")) return [
1315
- 3,
1316
- 8
1317
- ];
1565
+ ad = _state.sent();
1566
+ if (ad) ads.push(ad);
1318
1567
  _state.label = 5;
1319
1568
  case 5:
1320
- _state.trys.push([
1321
- 5,
1322
- 7,
1323
- ,
1324
- 8
1325
- ]);
1569
+ _iteratorNormalCompletion = true;
1326
1570
  return [
1327
- 4,
1328
- fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls)
1571
+ 3,
1572
+ 3
1329
1573
  ];
1330
1574
  case 6:
1331
- resolved = _state.sent();
1332
- if (resolved) {
1333
- ads.push(resolved);
1334
- }
1335
1575
  return [
1336
1576
  3,
1337
- 8
1577
+ 9
1338
1578
  ];
1339
1579
  case 7:
1340
- error = _state.sent();
1341
- console.warn("[HlsAdPlayer] Failed to resolve wrapper <Ad> in pod:", error);
1580
+ err = _state.sent();
1581
+ _didIteratorError = true;
1582
+ _iteratorError = err;
1342
1583
  return [
1343
1584
  3,
1344
- 8
1585
+ 9
1345
1586
  ];
1346
1587
  case 8:
1347
- _iteratorNormalCompletion = true;
1588
+ try {
1589
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1590
+ _iterator.return();
1591
+ }
1592
+ } finally{
1593
+ if (_didIteratorError) {
1594
+ throw _iteratorError;
1595
+ }
1596
+ }
1348
1597
  return [
1349
- 3,
1350
- 3
1598
+ 7
1351
1599
  ];
1352
1600
  case 9:
1353
1601
  return [
1354
1602
  3,
1355
- 12
1603
+ 21
1356
1604
  ];
1357
1605
  case 10:
1358
- err = _state.sent();
1359
- _didIteratorError = true;
1360
- _iteratorError = err;
1606
+ _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
1607
+ _state.label = 11;
1608
+ case 11:
1609
+ _state.trys.push([
1610
+ 11,
1611
+ 19,
1612
+ 20,
1613
+ 21
1614
+ ]);
1615
+ _iterator1 = podElements[Symbol.iterator]();
1616
+ _state.label = 12;
1617
+ case 12:
1618
+ if (!!(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done)) return [
1619
+ 3,
1620
+ 18
1621
+ ];
1622
+ adElement1 = _step1.value;
1623
+ return [
1624
+ 4,
1625
+ resolveAd(adElement1)
1626
+ ];
1627
+ case 13:
1628
+ ad1 = _state.sent();
1629
+ _state.label = 14;
1630
+ case 14:
1631
+ if (!(!ad1 && buffet.length > 0)) return [
1632
+ 3,
1633
+ 16
1634
+ ];
1635
+ return [
1636
+ 4,
1637
+ resolveAd(buffet.shift())
1638
+ ];
1639
+ case 15:
1640
+ ad1 = _state.sent();
1641
+ return [
1642
+ 3,
1643
+ 14
1644
+ ];
1645
+ case 16:
1646
+ if (ad1) ads.push(ad1);
1647
+ _state.label = 17;
1648
+ case 17:
1649
+ _iteratorNormalCompletion1 = true;
1361
1650
  return [
1362
1651
  3,
1363
1652
  12
1364
1653
  ];
1365
- case 11:
1654
+ case 18:
1655
+ return [
1656
+ 3,
1657
+ 21
1658
+ ];
1659
+ case 19:
1660
+ err = _state.sent();
1661
+ _didIteratorError1 = true;
1662
+ _iteratorError1 = err;
1663
+ return [
1664
+ 3,
1665
+ 21
1666
+ ];
1667
+ case 20:
1366
1668
  try {
1367
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1368
- _iterator.return();
1669
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1670
+ _iterator1.return();
1369
1671
  }
1370
1672
  } finally{
1371
- if (_didIteratorError) {
1372
- throw _iteratorError;
1673
+ if (_didIteratorError1) {
1674
+ throw _iteratorError1;
1373
1675
  }
1374
1676
  }
1375
1677
  return [
1376
1678
  7
1377
1679
  ];
1378
- case 12:
1379
- console.log("[HlsAdPlayer] Parsed ".concat(ads.length, " ad(s) from pod VAST response"));
1680
+ case 21:
1681
+ 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"));
1380
1682
  return [
1381
1683
  2,
1382
1684
  ads
@@ -1406,7 +1708,40 @@ function createHlsAdPlayer(contentVideo, options) {
1406
1708
  var onTimeUpdate = function onTimeUpdate() {
1407
1709
  if (!currentAd || !adVideoElement) return;
1408
1710
  noteAdProgress();
1409
- var progress = adVideoElement.currentTime / currentAd.duration;
1711
+ sampleViewability();
1712
+ var currentTime = adVideoElement.currentTime;
1713
+ if (trackingFired.start) {
1714
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1715
+ try {
1716
+ for(var _iterator = currentAd.trackingUrls.progress[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1717
+ var event = _step.value;
1718
+ var _event_offsetSeconds, _event_offsetPercent;
1719
+ if (trackingFired.progressFired.has(event)) continue;
1720
+ 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;
1721
+ if (currentTime >= threshold) {
1722
+ trackingFired.progressFired.add(event);
1723
+ fireTrackingPixels([
1724
+ event.url
1725
+ ]);
1726
+ }
1727
+ }
1728
+ } catch (err) {
1729
+ _didIteratorError = true;
1730
+ _iteratorError = err;
1731
+ } finally{
1732
+ try {
1733
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1734
+ _iterator.return();
1735
+ }
1736
+ } finally{
1737
+ if (_didIteratorError) {
1738
+ throw _iteratorError;
1739
+ }
1740
+ }
1741
+ }
1742
+ }
1743
+ if (!(currentAd.duration > 0)) return;
1744
+ var progress = currentTime / currentAd.duration;
1410
1745
  if (progress >= 0.25 && !trackingFired.firstQuartile) {
1411
1746
  trackingFired.firstQuartile = true;
1412
1747
  fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
@@ -1428,15 +1763,38 @@ function createHlsAdPlayer(contentVideo, options) {
1428
1763
  handleVideoDecodeFailure();
1429
1764
  }
1430
1765
  };
1766
+ var onCanPlay = function onCanPlay() {
1767
+ if (!currentAd || trackingFired.loaded) return;
1768
+ trackingFired.loaded = true;
1769
+ fireTrackingPixels(currentAd.trackingUrls.loaded);
1770
+ };
1431
1771
  var onPlaying = function onPlaying() {
1432
1772
  startStallWatchdog();
1433
- if (!currentAd || trackingFired.start) return;
1773
+ if (!currentAd || !adVideoElement) return;
1774
+ if (!trackingFired.impression) {
1775
+ trackingFired.impression = true;
1776
+ resolvedAds.add(currentAd);
1777
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1778
+ fireTrackingPixels(currentAd.trackingUrls.creativeView);
1779
+ fireTrackingPixels(currentAd.trackingUrls.verificationNotExecuted, {
1780
+ reason: VERIFICATION_NOT_SUPPORTED_REASON
1781
+ });
1782
+ emit("ad_impression", {
1783
+ adId: currentAd.id,
1784
+ index: podIndex,
1785
+ total: podAds.length || 1
1786
+ });
1787
+ }
1788
+ if (trackingFired.start) return;
1434
1789
  trackingFired.start = true;
1790
+ trackingFired.lastMuted = adVideoElement.muted || adVideoElement.volume === 0;
1435
1791
  fireTrackingPixels(currentAd.trackingUrls.start);
1436
1792
  console.log("[HlsAdPlayer] Ad started playing");
1437
1793
  };
1438
1794
  var onEnded = function onEnded() {
1439
1795
  if (!currentAd || trackingFired.complete) return;
1796
+ sampleViewability();
1797
+ settleViewability();
1440
1798
  trackingFired.complete = true;
1441
1799
  fireTrackingPixels(currentAd.trackingUrls.complete);
1442
1800
  console.log("[HlsAdPlayer] Ad completed");
@@ -1448,11 +1806,7 @@ function createHlsAdPlayer(contentVideo, options) {
1448
1806
  var onError = function onError(e) {
1449
1807
  if (!adPlaying) return;
1450
1808
  console.error("[HlsAdPlayer] Ad video error:", e);
1451
- if (currentAd) {
1452
- fireTrackingPixels(currentAd.trackingUrls.error, {
1453
- errorCode: toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error)
1454
- });
1455
- }
1809
+ reportCurrentAdError(toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error));
1456
1810
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1457
1811
  return;
1458
1812
  }
@@ -1460,19 +1814,26 @@ function createHlsAdPlayer(contentVideo, options) {
1460
1814
  };
1461
1815
  var onVolumeChange = function onVolumeChange() {
1462
1816
  if (!currentAd || !adVideoElement) return;
1463
- if (adVideoElement.muted) {
1464
- fireTrackingPixels(currentAd.trackingUrls.mute);
1465
- } else {
1466
- fireTrackingPixels(currentAd.trackingUrls.unmute);
1817
+ var muted = adVideoElement.muted || adVideoElement.volume === 0;
1818
+ if (!trackingFired.start) {
1819
+ trackingFired.lastMuted = muted;
1820
+ return;
1467
1821
  }
1822
+ if (muted === trackingFired.lastMuted) return;
1823
+ trackingFired.lastMuted = muted;
1824
+ fireTrackingPixels(muted ? currentAd.trackingUrls.mute : currentAd.trackingUrls.unmute);
1825
+ };
1826
+ var isTrackablePlayback = function isTrackablePlayback() {
1827
+ return adPlaying && !!currentAd && !!adVideoElement && trackingFired.start && !trackingFired.complete && !adVideoElement.ended;
1468
1828
  };
1469
1829
  var onPause = function onPause() {
1470
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1830
+ continuousVisibleS = 0;
1831
+ if (isTrackablePlayback()) {
1471
1832
  fireTrackingPixels(currentAd.trackingUrls.pause);
1472
1833
  }
1473
1834
  };
1474
1835
  var onPlay = function onPlay() {
1475
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1836
+ if (isTrackablePlayback()) {
1476
1837
  fireTrackingPixels(currentAd.trackingUrls.resume);
1477
1838
  }
1478
1839
  };
@@ -1485,6 +1846,10 @@ function createHlsAdPlayer(contentVideo, options) {
1485
1846
  type: "loadedmetadata",
1486
1847
  handler: onLoadedMetadata
1487
1848
  },
1849
+ {
1850
+ type: "canplay",
1851
+ handler: onCanPlay
1852
+ },
1488
1853
  {
1489
1854
  type: "playing",
1490
1855
  handler: onPlaying
@@ -1556,6 +1921,229 @@ function createHlsAdPlayer(contentVideo, options) {
1556
1921
  }
1557
1922
  adEventHandlers = [];
1558
1923
  }
1924
+ function handleAdClick() {
1925
+ if (!adPlaying || !currentAd) return;
1926
+ fireTrackingPixels(currentAd.trackingUrls.clickTracking);
1927
+ emit("ad_click", {
1928
+ adId: currentAd.id,
1929
+ clickThrough: currentAd.clickThrough
1930
+ });
1931
+ if (currentAd.clickThrough) {
1932
+ try {
1933
+ window.open(currentAd.clickThrough, "_blank", "noopener");
1934
+ } catch (error) {
1935
+ console.warn("[HlsAdPlayer] Failed to open ClickThrough URL:", error);
1936
+ }
1937
+ }
1938
+ }
1939
+ function reportCurrentAdError(errorCode) {
1940
+ if (!currentAd) return;
1941
+ resolvedAds.add(currentAd);
1942
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1943
+ errorCode: errorCode
1944
+ });
1945
+ }
1946
+ function fireNotUsedForUnplayedAds() {
1947
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1948
+ try {
1949
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1950
+ var ad = _step.value;
1951
+ if (resolvedAds.has(ad)) continue;
1952
+ resolvedAds.add(ad);
1953
+ fireTrackingPixels(ad.trackingUrls.notUsed, {
1954
+ ad: ad
1955
+ });
1956
+ }
1957
+ } catch (err) {
1958
+ _didIteratorError = true;
1959
+ _iteratorError = err;
1960
+ } finally{
1961
+ try {
1962
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1963
+ _iterator.return();
1964
+ }
1965
+ } finally{
1966
+ if (_didIteratorError) {
1967
+ throw _iteratorError;
1968
+ }
1969
+ }
1970
+ }
1971
+ }
1972
+ function sampleViewability() {
1973
+ if (!currentAd || !adVideoElement || !viewObserver || !trackingFired.impression || trackingFired.viewabilitySettled) {
1974
+ return;
1975
+ }
1976
+ var now = adVideoElement.currentTime;
1977
+ var inView = visibleRatio >= VIEWABLE_MIN_VISIBLE_RATIO && document.visibilityState === "visible" && !adVideoElement.paused;
1978
+ if (!inView) {
1979
+ continuousVisibleS = 0;
1980
+ } else if (lastViewSampleTime !== void 0 && now >= lastViewSampleTime) {
1981
+ continuousVisibleS += now - lastViewSampleTime;
1982
+ }
1983
+ lastViewSampleTime = now;
1984
+ if (continuousVisibleS >= VIEWABLE_MIN_CONTINUOUS_S) {
1985
+ trackingFired.viewabilitySettled = true;
1986
+ fireTrackingPixels(currentAd.trackingUrls.viewable);
1987
+ }
1988
+ }
1989
+ function settleViewability() {
1990
+ if (!currentAd || !trackingFired.impression || trackingFired.viewabilitySettled) {
1991
+ return;
1992
+ }
1993
+ trackingFired.viewabilitySettled = true;
1994
+ fireTrackingPixels(viewObserver ? currentAd.trackingUrls.notViewable : currentAd.trackingUrls.viewUndetermined);
1995
+ }
1996
+ function handleFullscreenChange() {
1997
+ var _document_fullscreenElement;
1998
+ if (!adPlaying || !currentAd || !adContainerEl || !trackingFired.start) return;
1999
+ var fullscreenEl = (_document_fullscreenElement = document.fullscreenElement) !== null && _document_fullscreenElement !== void 0 ? _document_fullscreenElement : document.webkitFullscreenElement;
2000
+ var expanded = !!fullscreenEl && fullscreenEl.contains(adContainerEl);
2001
+ if (expanded === lastPlayerExpanded) return;
2002
+ lastPlayerExpanded = expanded;
2003
+ var urls = currentAd.trackingUrls;
2004
+ fireTrackingPixels(expanded ? urls.fullscreen.concat(urls.playerExpand) : urls.exitFullscreen.concat(urls.playerCollapse));
2005
+ }
2006
+ function attachContainerHandlers() {
2007
+ if (!adContainerEl || containerHandlers.length > 0) return;
2008
+ var onClick = function onClick() {
2009
+ return handleAdClick();
2010
+ };
2011
+ var onInteraction = function onInteraction(event) {
2012
+ if (adPlaying) emit("ad_interaction", event);
2013
+ };
2014
+ containerHandlers = [
2015
+ {
2016
+ type: "click",
2017
+ handler: onClick
2018
+ },
2019
+ {
2020
+ type: "mousedown",
2021
+ handler: onInteraction
2022
+ },
2023
+ {
2024
+ type: "touchstart",
2025
+ handler: onInteraction
2026
+ }
2027
+ ];
2028
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2029
+ try {
2030
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2031
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
2032
+ adContainerEl.addEventListener(type, handler);
2033
+ }
2034
+ } catch (err) {
2035
+ _didIteratorError = true;
2036
+ _iteratorError = err;
2037
+ } finally{
2038
+ try {
2039
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2040
+ _iterator.return();
2041
+ }
2042
+ } finally{
2043
+ if (_didIteratorError) {
2044
+ throw _iteratorError;
2045
+ }
2046
+ }
2047
+ }
2048
+ var onFullscreenChange = function onFullscreenChange() {
2049
+ return handleFullscreenChange();
2050
+ };
2051
+ documentHandlers = [
2052
+ {
2053
+ type: "fullscreenchange",
2054
+ handler: onFullscreenChange
2055
+ },
2056
+ {
2057
+ type: "webkitfullscreenchange",
2058
+ handler: onFullscreenChange
2059
+ }
2060
+ ];
2061
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2062
+ try {
2063
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2064
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
2065
+ document.addEventListener(type1, handler1);
2066
+ }
2067
+ } catch (err) {
2068
+ _didIteratorError1 = true;
2069
+ _iteratorError1 = err;
2070
+ } finally{
2071
+ try {
2072
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2073
+ _iterator1.return();
2074
+ }
2075
+ } finally{
2076
+ if (_didIteratorError1) {
2077
+ throw _iteratorError1;
2078
+ }
2079
+ }
2080
+ }
2081
+ if (typeof IntersectionObserver !== "undefined") {
2082
+ viewObserver = new IntersectionObserver(function(entries) {
2083
+ var entry = entries[entries.length - 1];
2084
+ if (entry) {
2085
+ visibleRatio = entry.isIntersecting ? entry.intersectionRatio : 0;
2086
+ }
2087
+ }, {
2088
+ threshold: [
2089
+ 0,
2090
+ 0.25,
2091
+ 0.5,
2092
+ 0.75,
2093
+ 1
2094
+ ]
2095
+ });
2096
+ viewObserver.observe(adContainerEl);
2097
+ }
2098
+ }
2099
+ function detachContainerHandlers() {
2100
+ if (adContainerEl) {
2101
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2102
+ try {
2103
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2104
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
2105
+ adContainerEl.removeEventListener(type, handler);
2106
+ }
2107
+ } catch (err) {
2108
+ _didIteratorError = true;
2109
+ _iteratorError = err;
2110
+ } finally{
2111
+ try {
2112
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2113
+ _iterator.return();
2114
+ }
2115
+ } finally{
2116
+ if (_didIteratorError) {
2117
+ throw _iteratorError;
2118
+ }
2119
+ }
2120
+ }
2121
+ }
2122
+ containerHandlers = [];
2123
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2124
+ try {
2125
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2126
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
2127
+ document.removeEventListener(type1, handler1);
2128
+ }
2129
+ } catch (err) {
2130
+ _didIteratorError1 = true;
2131
+ _iteratorError1 = err;
2132
+ } finally{
2133
+ try {
2134
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2135
+ _iterator1.return();
2136
+ }
2137
+ } finally{
2138
+ if (_didIteratorError1) {
2139
+ throw _iteratorError1;
2140
+ }
2141
+ }
2142
+ }
2143
+ documentHandlers = [];
2144
+ viewObserver === null || viewObserver === void 0 ? void 0 : viewObserver.disconnect();
2145
+ viewObserver = void 0;
2146
+ }
1559
2147
  function setAdPlayingFlag(isPlaying) {
1560
2148
  if (isPlaying) {
1561
2149
  contentVideo.dataset.stormcloudAdPlaying = "true";
@@ -1563,15 +2151,10 @@ function createHlsAdPlayer(contentVideo, options) {
1563
2151
  delete contentVideo.dataset.stormcloudAdPlaying;
1564
2152
  }
1565
2153
  }
1566
- function resetQuartileTracking(preserveImpression) {
1567
- trackingFired = {
1568
- impression: preserveImpression ? trackingFired.impression : false,
1569
- start: false,
1570
- firstQuartile: false,
1571
- midpoint: false,
1572
- thirdQuartile: false,
1573
- complete: false
1574
- };
2154
+ function resetAdTracking() {
2155
+ trackingFired = createTrackingState();
2156
+ continuousVisibleS = 0;
2157
+ lastViewSampleTime = void 0;
1575
2158
  }
1576
2159
  function isRvfcSupported(video) {
1577
2160
  return typeof video.requestVideoFrameCallback === "function";
@@ -1677,13 +2260,12 @@ function createHlsAdPlayer(contentVideo, options) {
1677
2260
  if (podIndex >= podAds.length - 1) {
1678
2261
  return false;
1679
2262
  }
2263
+ settleViewability();
1680
2264
  podIndex++;
1681
2265
  currentAd = podAds[podIndex];
1682
2266
  currentAdMediaFile = void 0;
1683
- resetQuartileTracking(false);
2267
+ resetAdTracking();
1684
2268
  if (currentAd) {
1685
- fireTrackingPixels(currentAd.trackingUrls.impression);
1686
- trackingFired.impression = true;
1687
2269
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1688
2270
  }
1689
2271
  clearStallWatchdog();
@@ -1721,11 +2303,7 @@ function createHlsAdPlayer(contentVideo, options) {
1721
2303
  function handleAdStall() {
1722
2304
  console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
1723
2305
  clearStallWatchdog();
1724
- if (currentAd) {
1725
- fireTrackingPixels(currentAd.trackingUrls.error, {
1726
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1727
- });
1728
- }
2306
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1729
2307
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1730
2308
  return;
1731
2309
  }
@@ -1791,11 +2369,7 @@ function createHlsAdPlayer(contentVideo, options) {
1791
2369
  function handleVideoDecodeFailure() {
1792
2370
  console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1793
2371
  clearStallWatchdog();
1794
- if (currentAd) {
1795
- fireTrackingPixels(currentAd.trackingUrls.error, {
1796
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1797
- });
1798
- }
2372
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1799
2373
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1800
2374
  return;
1801
2375
  }
@@ -1850,6 +2424,7 @@ function createHlsAdPlayer(contentVideo, options) {
1850
2424
  }
1851
2425
  function handleAdComplete() {
1852
2426
  console.log("[HlsAdPlayer] Handling ad completion");
2427
+ settleViewability();
1853
2428
  clearStallWatchdog();
1854
2429
  adPlaying = false;
1855
2430
  setAdPlayingFlag(false);
@@ -1873,6 +2448,7 @@ function createHlsAdPlayer(contentVideo, options) {
1873
2448
  }
1874
2449
  function handleAdError() {
1875
2450
  console.log("[HlsAdPlayer] Handling ad error");
2451
+ settleViewability();
1876
2452
  clearStallWatchdog();
1877
2453
  adPlaying = false;
1878
2454
  setAdPlayingFlag(false);
@@ -1905,6 +2481,7 @@ function createHlsAdPlayer(contentVideo, options) {
1905
2481
  adContainerEl = container;
1906
2482
  }
1907
2483
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
2484
+ attachContainerHandlers();
1908
2485
  },
1909
2486
  requestAds: function requestAds(vastTagUrl) {
1910
2487
  return _async_to_generator(function() {
@@ -1967,10 +2544,6 @@ function createHlsAdPlayer(contentVideo, options) {
1967
2544
  currentAd = ads[0];
1968
2545
  currentAdMediaFile = void 0;
1969
2546
  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"));
1970
- if (currentAd) {
1971
- fireTrackingPixels(currentAd.trackingUrls.impression);
1972
- trackingFired.impression = true;
1973
- }
1974
2547
  return [
1975
2548
  2,
1976
2549
  Promise.resolve()
@@ -2010,7 +2583,7 @@ function createHlsAdPlayer(contentVideo, options) {
2010
2583
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
2011
2584
  }
2012
2585
  setupAdEventListeners();
2013
- resetQuartileTracking(true);
2586
+ resetAdTracking();
2014
2587
  contentVolume = contentVideo.volume;
2015
2588
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
2016
2589
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -2081,6 +2654,8 @@ function createHlsAdPlayer(contentVideo, options) {
2081
2654
  var previousMutedState;
2082
2655
  return _ts_generator(this, function(_state) {
2083
2656
  console.log("[HlsAdPlayer] Stopping ad");
2657
+ settleViewability();
2658
+ fireNotUsedForUnplayedAds();
2084
2659
  clearStallWatchdog();
2085
2660
  adPlaying = false;
2086
2661
  setAdPlayingFlag(false);
@@ -2111,6 +2686,8 @@ function createHlsAdPlayer(contentVideo, options) {
2111
2686
  },
2112
2687
  destroy: function destroy() {
2113
2688
  console.log("[HlsAdPlayer] Destroying");
2689
+ settleViewability();
2690
+ fireNotUsedForUnplayedAds();
2114
2691
  destroyed = true;
2115
2692
  clearStallWatchdog();
2116
2693
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2139,6 +2716,7 @@ function createHlsAdPlayer(contentVideo, options) {
2139
2716
  contentVideo.muted = originalMutedState;
2140
2717
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
2141
2718
  teardownAdEventListeners();
2719
+ detachContainerHandlers();
2142
2720
  releaseAdDecoder();
2143
2721
  currentAd = void 0;
2144
2722
  currentAdMediaFile = void 0;
@@ -2284,6 +2862,7 @@ function toDevSafeUrl(rawUrl) {
2284
2862
  // src/sdk/pal.ts
2285
2863
  var PAL_SDK_URL = "https://imasdk.googleapis.com/pal/sdkloader/pal.js";
2286
2864
  var _nonceLoader;
2865
+ var _nonceLoaderAllowStorage;
2287
2866
  var _palLoadPromise;
2288
2867
  function loadPalSdk() {
2289
2868
  var _window_goog;
@@ -2326,12 +2905,15 @@ function loadPalSdk() {
2326
2905
  });
2327
2906
  return _palLoadPromise;
2328
2907
  }
2329
- function getOrCreateNonceLoader() {
2330
- if (_nonceLoader) return _nonceLoader;
2908
+ function getOrCreateNonceLoader(allowStorage) {
2909
+ if (_nonceLoader && _nonceLoaderAllowStorage === allowStorage) {
2910
+ return _nonceLoader;
2911
+ }
2331
2912
  var goog = window.goog;
2332
2913
  var consentSettings = new goog.pal.ConsentSettings();
2333
- consentSettings.allowStorage = true;
2914
+ consentSettings.allowStorage = allowStorage;
2334
2915
  _nonceLoader = new goog.pal.NonceLoader(consentSettings);
2916
+ _nonceLoaderAllowStorage = allowStorage;
2335
2917
  return _nonceLoader;
2336
2918
  }
2337
2919
  function createPalNonceManager() {
@@ -2340,7 +2922,7 @@ function createPalNonceManager() {
2340
2922
  return {
2341
2923
  generateNonce: function generateNonce() {
2342
2924
  return _async_to_generator(function() {
2343
- var options, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
2925
+ var options, _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
2344
2926
  var _arguments = arguments;
2345
2927
  return _ts_generator(this, function(_state) {
2346
2928
  switch(_state.label){
@@ -2360,7 +2942,7 @@ function createPalNonceManager() {
2360
2942
  ];
2361
2943
  case 2:
2362
2944
  _state.sent();
2363
- loader = getOrCreateNonceLoader();
2945
+ loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
2364
2946
  goog = window.goog;
2365
2947
  request = new goog.pal.NonceRequest();
2366
2948
  request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
@@ -2545,6 +3127,8 @@ function ingestPlayerTracking(licenseKey, channel, body) {
2545
3127
  }
2546
3128
  // src/utils/vastEnvironmentSignals.ts
2547
3129
  var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3130
+ var WEB_SESSION_STORAGE_KEY = "stormcloud.web.sid";
3131
+ var inMemoryWebSessionId;
2548
3132
  var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
2549
3133
  var DEVICE_ID_STORAGE_KEYS = [
2550
3134
  "rdid",
@@ -2566,7 +3150,7 @@ function resolveVastEnvironmentSignals(isCtv) {
2566
3150
  var _ref;
2567
3151
  var bridgeSignals = readNativeBridgeSignals();
2568
3152
  var platformDevice = readPlatformNativeDeviceId();
2569
- var realDeviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
3153
+ var realDeviceId = bridgeSignals.deviceId || (isCtv ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
2570
3154
  var deviceId = realDeviceId;
2571
3155
  var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
2572
3156
  var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
@@ -2580,6 +3164,7 @@ function resolveVastEnvironmentSignals(isCtv) {
2580
3164
  limitAdTracking = (_ref1 = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref1 !== void 0 ? _ref1 : false;
2581
3165
  }
2582
3166
  }
3167
+ var deviceTypeHint = resolveDeviceTypeHint(isCtv);
2583
3168
  if (isCtv) {
2584
3169
  return _object_spread_props(_object_spread({
2585
3170
  isCtv: true,
@@ -2591,18 +3176,157 @@ function resolveVastEnvironmentSignals(isCtv) {
2591
3176
  } : {}, deviceId && limitAdTracking != null ? {
2592
3177
  limitAdTracking: limitAdTracking
2593
3178
  } : {}), {
2594
- deviceTypeHint: 5
3179
+ deviceTypeHint: deviceTypeHint
2595
3180
  });
2596
3181
  }
2597
- return _object_spread({
3182
+ var webSessionId = getOrCreateWebSessionId();
3183
+ return _object_spread_props(_object_spread({
2598
3184
  isCtv: false
2599
- }, deviceId ? {
3185
+ }, webSessionId ? {
3186
+ sessionId: webSessionId
3187
+ } : {}, deviceId ? {
2600
3188
  deviceId: deviceId
2601
3189
  } : {}, deviceId && deviceIdType ? {
2602
3190
  deviceIdType: deviceIdType
2603
3191
  } : {}, deviceId && limitAdTracking != null ? {
2604
3192
  limitAdTracking: limitAdTracking
2605
- } : {});
3193
+ } : {}), {
3194
+ deviceTypeHint: deviceTypeHint
3195
+ });
3196
+ }
3197
+ var DEVICE_TYPE_HINT = {
3198
+ FEATURE_PHONE: 1,
3199
+ SMARTPHONE: 2,
3200
+ DESKTOP: 3,
3201
+ TABLET: 4,
3202
+ CONNECTED_TV: 5,
3203
+ GAME_CONSOLE: 6,
3204
+ SET_TOP_BOX: 7
3205
+ };
3206
+ var DEVICE_TYPE_HINT_ALIASES = {
3207
+ featurephone: DEVICE_TYPE_HINT.FEATURE_PHONE,
3208
+ smartphone: DEVICE_TYPE_HINT.SMARTPHONE,
3209
+ mobile: DEVICE_TYPE_HINT.SMARTPHONE,
3210
+ phone: DEVICE_TYPE_HINT.SMARTPHONE,
3211
+ desktop: DEVICE_TYPE_HINT.DESKTOP,
3212
+ pc: DEVICE_TYPE_HINT.DESKTOP,
3213
+ tablet: DEVICE_TYPE_HINT.TABLET,
3214
+ ctv: DEVICE_TYPE_HINT.CONNECTED_TV,
3215
+ tv: DEVICE_TYPE_HINT.CONNECTED_TV,
3216
+ connectedtv: DEVICE_TYPE_HINT.CONNECTED_TV,
3217
+ smarttv: DEVICE_TYPE_HINT.CONNECTED_TV,
3218
+ console: DEVICE_TYPE_HINT.GAME_CONSOLE,
3219
+ gameconsole: DEVICE_TYPE_HINT.GAME_CONSOLE,
3220
+ stb: DEVICE_TYPE_HINT.SET_TOP_BOX,
3221
+ settopbox: DEVICE_TYPE_HINT.SET_TOP_BOX
3222
+ };
3223
+ 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;
3224
+ var GAME_CONSOLE_UA = /PlayStation|Xbox|Nintendo/i;
3225
+ 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;
3226
+ var FEATURE_PHONE_UA = /KAIOS|MIDP|J2ME|Series40|Opera Mini/i;
3227
+ function resolveDeviceTypeHint(isCtv) {
3228
+ var override = readDeviceTypeHintOverride(isCtv);
3229
+ if (override != null) return override;
3230
+ return inferDeviceTypeHint(isCtv);
3231
+ }
3232
+ function inferDeviceTypeHint(isCtv) {
3233
+ var fallback = isCtv ? DEVICE_TYPE_HINT.CONNECTED_TV : DEVICE_TYPE_HINT.DESKTOP;
3234
+ if (typeof navigator === "undefined") return fallback;
3235
+ var ua = navigator.userAgent || "";
3236
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
3237
+ if (SET_TOP_BOX_UA.test(ua)) return DEVICE_TYPE_HINT.SET_TOP_BOX;
3238
+ if (GAME_CONSOLE_UA.test(ua)) return DEVICE_TYPE_HINT.GAME_CONSOLE;
3239
+ if (CONNECTED_TV_UA.test(ua) && !/Mobile/i.test(ua)) {
3240
+ return DEVICE_TYPE_HINT.CONNECTED_TV;
3241
+ }
3242
+ if (FEATURE_PHONE_UA.test(ua)) return DEVICE_TYPE_HINT.FEATURE_PHONE;
3243
+ if (/iPad/i.test(ua) || /Macintosh/i.test(ua) && maxTouchPoints > 1) {
3244
+ return DEVICE_TYPE_HINT.TABLET;
3245
+ }
3246
+ if (/iPhone|iPod/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3247
+ if (/Android/i.test(ua)) {
3248
+ if (/Mobile/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3249
+ if (maxTouchPoints === 0) return DEVICE_TYPE_HINT.SET_TOP_BOX;
3250
+ return DEVICE_TYPE_HINT.TABLET;
3251
+ }
3252
+ if (/Mobile|Windows Phone|BlackBerry/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3253
+ return fallback;
3254
+ }
3255
+ function readDeviceTypeHintOverride(isCtv) {
3256
+ if (typeof window === "undefined") return void 0;
3257
+ var keys = [
3258
+ "dth",
3259
+ "deviceTypeHint"
3260
+ ];
3261
+ var fromGlobal = normalizeDeviceTypeHint(window.__STORMCLOUD_DTH__);
3262
+ if (fromGlobal != null) return fromGlobal;
3263
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3264
+ try {
3265
+ for(var _iterator = getNativeBridgeSources()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3266
+ var source = _step.value;
3267
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
3268
+ try {
3269
+ for(var _iterator1 = keys[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
3270
+ var key = _step1.value;
3271
+ var value = source === null || source === void 0 ? void 0 : source[key];
3272
+ var normalized = normalizeDeviceTypeHint(typeof value === "function" ? safeCall(value, source) : value);
3273
+ if (normalized != null) return normalized;
3274
+ }
3275
+ } catch (err) {
3276
+ _didIteratorError1 = true;
3277
+ _iteratorError1 = err;
3278
+ } finally{
3279
+ try {
3280
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
3281
+ _iterator1.return();
3282
+ }
3283
+ } finally{
3284
+ if (_didIteratorError1) {
3285
+ throw _iteratorError1;
3286
+ }
3287
+ }
3288
+ }
3289
+ }
3290
+ } catch (err) {
3291
+ _didIteratorError = true;
3292
+ _iteratorError = err;
3293
+ } finally{
3294
+ try {
3295
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3296
+ _iterator.return();
3297
+ }
3298
+ } finally{
3299
+ if (_didIteratorError) {
3300
+ throw _iteratorError;
3301
+ }
3302
+ }
3303
+ }
3304
+ if (!isCtv) return void 0;
3305
+ for(var _i = 0, _iter = [
3306
+ "stormcloud.dth",
3307
+ "dth"
3308
+ ]; _i < _iter.length; _i++){
3309
+ var key1 = _iter[_i];
3310
+ var normalized1 = normalizeDeviceTypeHint(readStoredString(key1));
3311
+ if (normalized1 != null) return normalized1;
3312
+ }
3313
+ return void 0;
3314
+ }
3315
+ function normalizeDeviceTypeHint(value) {
3316
+ if (typeof value === "number") {
3317
+ return Number.isInteger(value) && value >= 1 && value <= 7 ? value : void 0;
3318
+ }
3319
+ if (typeof value !== "string") return void 0;
3320
+ var trimmed = value.trim();
3321
+ if (/^[1-7]$/.test(trimmed)) return parseInt(trimmed, 10);
3322
+ return DEVICE_TYPE_HINT_ALIASES[trimmed.toLowerCase().replace(/[\s_-]/g, "")];
3323
+ }
3324
+ function safeCall(fn, thisArg) {
3325
+ try {
3326
+ return fn.call(thisArg);
3327
+ } catch (unused) {
3328
+ return void 0;
3329
+ }
2606
3330
  }
2607
3331
  function inferDeviceIdType() {
2608
3332
  if (typeof navigator === "undefined") {
@@ -2626,9 +3350,10 @@ function isEquivalentDeviceIdType(tagType, runtimeType) {
2626
3350
  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2627
3351
  }
2628
3352
  function resolveNativeDeviceId() {
3353
+ var includeStored = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
2629
3354
  var bridgeSignals = readNativeBridgeSignals();
2630
3355
  var platformDevice = readPlatformNativeDeviceId();
2631
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
3356
+ var deviceId = bridgeSignals.deviceId || (includeStored ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
2632
3357
  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {
2633
3358
  return void 0;
2634
3359
  }
@@ -2657,6 +3382,21 @@ function getOrCreateCtvSessionId() {
2657
3382
  writePersistentId(CTV_SESSION_STORAGE_KEY, sessionId);
2658
3383
  return sessionId;
2659
3384
  }
3385
+ function getOrCreateWebSessionId() {
3386
+ if (typeof window === "undefined") return void 0;
3387
+ try {
3388
+ var _window_sessionStorage;
3389
+ var existing = (_window_sessionStorage = window.sessionStorage) === null || _window_sessionStorage === void 0 ? void 0 : _window_sessionStorage.getItem(WEB_SESSION_STORAGE_KEY);
3390
+ if (existing && !isMacroPlaceholder(existing)) return existing;
3391
+ } catch (unused) {}
3392
+ var sessionId = inMemoryWebSessionId || createUuid();
3393
+ inMemoryWebSessionId = sessionId;
3394
+ try {
3395
+ var _window_sessionStorage1;
3396
+ (_window_sessionStorage1 = window.sessionStorage) === null || _window_sessionStorage1 === void 0 ? void 0 : _window_sessionStorage1.setItem(WEB_SESSION_STORAGE_KEY, sessionId);
3397
+ } catch (unused) {}
3398
+ return sessionId;
3399
+ }
2660
3400
  function readPersistentId(storageKey) {
2661
3401
  return readStoredString(storageKey) || readCookie(storageKey);
2662
3402
  }
@@ -2808,22 +3548,9 @@ function isZeroedAdId(value) {
2808
3548
  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
2809
3549
  }
2810
3550
  function readNativeBridgeSignals() {
2811
- if (typeof window === "undefined") {
2812
- return {};
2813
- }
2814
- var candidates = [
2815
- window.__STORMCLOUD_CTV_AD_INFO__,
2816
- window.__STORMCLOUD_CTV__,
2817
- window.stormcloudCtv,
2818
- window.AiryTV,
2819
- window.Android,
2820
- window.webOS,
2821
- window.tizen,
2822
- window.amazon
2823
- ].filter(Boolean);
2824
3551
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2825
3552
  try {
2826
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3553
+ for(var _iterator = getNativeBridgeSources()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2827
3554
  var source = _step.value;
2828
3555
  var contentUrl = readBridgeValue(source, [
2829
3556
  "contentUrl",
@@ -2898,6 +3625,21 @@ function readNativeBridgeSignals() {
2898
3625
  }
2899
3626
  return {};
2900
3627
  }
3628
+ function getNativeBridgeSources() {
3629
+ if (typeof window === "undefined") {
3630
+ return [];
3631
+ }
3632
+ return [
3633
+ window.__STORMCLOUD_CTV_AD_INFO__,
3634
+ window.__STORMCLOUD_CTV__,
3635
+ window.stormcloudCtv,
3636
+ window.AiryTV,
3637
+ window.Android,
3638
+ window.webOS,
3639
+ window.tizen,
3640
+ window.amazon
3641
+ ].filter(Boolean);
3642
+ }
2901
3643
  function readBridgeValue(source, keys) {
2902
3644
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2903
3645
  try {
@@ -3256,7 +3998,7 @@ function sha256Hex(input) {
3256
3998
  })();
3257
3999
  }
3258
4000
  function resolvePlayerIdentitySeed(clientInfo) {
3259
- var nativeDeviceId = resolveNativeDeviceId();
4001
+ var nativeDeviceId = resolveNativeDeviceId(clientInfo.isSmartTV);
3260
4002
  if (nativeDeviceId) {
3261
4003
  return "device:".concat(nativeDeviceId);
3262
4004
  }
@@ -4025,6 +4767,12 @@ function applyDeviceIdentityParams(params, ctx) {
4025
4767
  params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
4026
4768
  return;
4027
4769
  }
4770
+ if (!ctx.isCtv) {
4771
+ params.delete("rdid");
4772
+ params.delete("idtype");
4773
+ params.delete("is_lat");
4774
+ return;
4775
+ }
4028
4776
  var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
4029
4777
  var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
4030
4778
  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
@@ -4179,15 +4927,24 @@ function applyVastMacros(baseUrl, ctx) {
4179
4927
  if (ctx.podMaxAds != null) {
4180
4928
  params.set("pmad", String(Math.max(1, Math.round(ctx.podMaxAds))));
4181
4929
  }
4182
- if (!ctx.isCtv && ctx.pageUrl) {
4183
- params.set("url", ctx.pageUrl);
4184
- params.set("description_url", ctx.pageUrl);
4185
- }
4186
4930
  var existingUrl = params.get("url") || "";
4187
4931
  if (EXAMPLE_COM_URL.test(existingUrl)) {
4188
4932
  params.delete("url");
4189
4933
  params.delete("description_url");
4190
4934
  }
4935
+ if (!ctx.isCtv && ctx.pageUrl) {
4936
+ if (isMacroPlaceholder2(params.get("url"))) {
4937
+ params.set("url", ctx.pageUrl);
4938
+ }
4939
+ if (isMacroPlaceholder2(params.get("description_url"))) {
4940
+ params.set("description_url", params.get("url") || ctx.pageUrl);
4941
+ }
4942
+ }
4943
+ if (!ctx.isCtv) {
4944
+ params.delete("an");
4945
+ params.delete("msid");
4946
+ params.delete("sid");
4947
+ }
4191
4948
  if (ctx.adWillPlayMuted != null) {
4192
4949
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
4193
4950
  }
@@ -4221,6 +4978,9 @@ function applyVastMacros(baseUrl, ctx) {
4221
4978
  if (ctx.programTitle) {
4222
4979
  params.set("ct_ti", ctx.programTitle);
4223
4980
  }
4981
+ if (ctx.channelName) {
4982
+ params.set("ct_ch", ctx.channelName);
4983
+ }
4224
4984
  var staleKeys = [];
4225
4985
  params.forEach(function(value, key) {
4226
4986
  if (isMacroPlaceholder2(value)) {
@@ -4273,8 +5033,10 @@ function fetchConsentSignals() {
4273
5033
  tcfApi("addEventListener", 2, function(tcData, success) {
4274
5034
  if (settled) return;
4275
5035
  if (success && tcData && (tcData.eventStatus === "tcloaded" || tcData.eventStatus === "useractioncomplete")) {
5036
+ var _tcData_purpose_consents, _tcData_purpose;
4276
5037
  settled = true;
4277
5038
  signals.gdpr = tcData.gdprApplies ? "1" : "0";
5039
+ 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;
4278
5040
  if (typeof tcData.tcString === "string" && tcData.tcString) {
4279
5041
  signals.gdprConsent = tcData.tcString;
4280
5042
  }
@@ -5807,7 +6569,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
5807
6569
  pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
5808
6570
  adWillPlayMuted: adWillPlayMuted,
5809
6571
  adWillAutoPlay: !!this.config.autoplay,
5810
- sessionId: envSignals.sessionId,
6572
+ sessionId: envSignals.isCtv || this.consentSignals.storageAllowed !== false ? envSignals.sessionId : void 0,
5811
6573
  deviceId: envSignals.deviceId,
5812
6574
  deviceIdType: envSignals.deviceIdType,
5813
6575
  limitAdTracking: envSignals.limitAdTracking,
@@ -5815,6 +6577,8 @@ var AdConfigManager = /*#__PURE__*/ function() {
5815
6577
  adTest: this.config.adTest
5816
6578
  }, this.config.programTitle ? {
5817
6579
  programTitle: this.config.programTitle
6580
+ } : {}, this.config.channelName ? {
6581
+ channelName: this.config.channelName
5818
6582
  } : {}), {
5819
6583
  consent: this.consentSignals
5820
6584
  }));
@@ -7354,6 +8118,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7354
8118
  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 : "?"));
7355
8119
  }
7356
8120
  });
8121
+ adPlayer.on("ad_click", function() {
8122
+ _this.host.onAdClick();
8123
+ });
8124
+ adPlayer.on("ad_interaction", function(event) {
8125
+ if (event) _this.host.onAdInteraction(event);
8126
+ });
7357
8127
  adPlayer.on("all_ads_completed", function() {
7358
8128
  sendAdImpressionTracking(_this.host.config.licenseKey, {
7359
8129
  source: "hls",
@@ -8883,6 +9653,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8883
9653
  },
8884
9654
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8885
9655
  return _this.generatePodVastUrl(base, breakDurationMs);
9656
+ },
9657
+ onAdClick: function onAdClick() {
9658
+ return _this.palNonce.sendAdClick();
9659
+ },
9660
+ onAdInteraction: function onAdInteraction(event) {
9661
+ return _this.palNonce.sendAdTouch(event);
8886
9662
  }
8887
9663
  }, this.timing, this.adConfig, this.cueManager, this.placeholder);
8888
9664
  }
@@ -8923,7 +9699,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8923
9699
  // ───────────────────────────────────────────────────────────────
8924
9700
  function load() {
8925
9701
  return _async_to_generator(function() {
8926
- var _this, _this_config_lowLatencyMode, error, palDescriptionUrl, continueLiveStreamDuringAds;
9702
+ var _this, error, palDescriptionUrl, continueLiveStreamDuringAds;
8927
9703
  return _ts_generator(this, function(_state) {
8928
9704
  switch(_state.label){
8929
9705
  case 0:
@@ -8959,19 +9735,25 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8959
9735
  4
8960
9736
  ];
8961
9737
  case 4:
8962
- palDescriptionUrl = this.adConfig.getPalDescriptionUrl();
8963
- this.palNonce.generateNonce(_object_spread({
8964
- videoWidth: this.video.offsetWidth || this.video.clientWidth || 640,
8965
- videoHeight: this.video.offsetHeight || this.video.clientHeight || 480,
8966
- adWillAutoPlay: !!this.config.autoplay,
8967
- adWillPlayMuted: true,
8968
- playerVolume: 0,
8969
- continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
8970
- }, palDescriptionUrl ? {
8971
- descriptionUrl: palDescriptionUrl
8972
- } : {})).catch(function() {});
8973
- fetchConsentSignals().then(function(signals) {
9738
+ palDescriptionUrl = this.config.ctvAdRequest ? this.adConfig.getPalDescriptionUrl() : void 0;
9739
+ fetchConsentSignals().catch(function() {
9740
+ return {};
9741
+ }).then(function(signals) {
9742
+ var _this_config_lowLatencyMode;
8974
9743
  _this.adConfig.consentSignals = signals;
9744
+ var muted = _this.video.muted;
9745
+ return _this.palNonce.generateNonce(_object_spread({
9746
+ videoWidth: _this.video.offsetWidth || _this.video.clientWidth || 640,
9747
+ videoHeight: _this.video.offsetHeight || _this.video.clientHeight || 480,
9748
+ adWillAutoPlay: !!_this.config.autoplay,
9749
+ adWillPlayMuted: muted,
9750
+ playerVolume: muted ? 0 : _this.video.volume,
9751
+ continuousPlayback: (_this_config_lowLatencyMode = _this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
9752
+ }, palDescriptionUrl ? {
9753
+ descriptionUrl: palDescriptionUrl
9754
+ } : {}, signals.storageAllowed != null ? {
9755
+ allowStorage: signals.storageAllowed
9756
+ } : {}));
8975
9757
  }).catch(function() {});
8976
9758
  this.adConfig.initializeTracking();
8977
9759
  if (!this.hlsEngine.shouldUseNativeHls(function() {