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
package/lib/index.cjs CHANGED
@@ -798,6 +798,7 @@ var KNOWN_VAST_MACROS = /* @__PURE__ */ new Set([
798
798
  "PLAYERSIZE",
799
799
  "PLAYERSTATE",
800
800
  "PODSEQUENCE",
801
+ "REASON",
801
802
  "REGULATIONS",
802
803
  "SERVERSIDE",
803
804
  "SERVERUA",
@@ -856,6 +857,10 @@ function resolveMacroValues(ctx) {
856
857
  if (ctx.podSequence != null) {
857
858
  set("PODSEQUENCE", String(ctx.podSequence));
858
859
  }
860
+ set("ADSERVINGID", ctx.adServingId);
861
+ if (ctx.reason != null && ctx.reason !== "") {
862
+ set("REASON", String(ctx.reason));
863
+ }
859
864
  return values;
860
865
  }
861
866
  function substituteVastTrackingMacros(url) {
@@ -872,10 +877,72 @@ function substituteVastTrackingMacros(url) {
872
877
  });
873
878
  }
874
879
  // src/sdk/hlsAdPlayer.ts
880
+ var LINEAR_TRACKING_EVENTS = [
881
+ "creativeView",
882
+ "loaded",
883
+ "start",
884
+ "firstQuartile",
885
+ "midpoint",
886
+ "thirdQuartile",
887
+ "complete",
888
+ "mute",
889
+ "unmute",
890
+ "pause",
891
+ "resume",
892
+ "fullscreen",
893
+ "exitFullscreen",
894
+ "playerExpand",
895
+ "playerCollapse",
896
+ "notUsed"
897
+ ];
898
+ function textOf(el) {
899
+ var _el_textContent;
900
+ var value = el === null || el === void 0 ? void 0 : (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
901
+ return value ? value : void 0;
902
+ }
903
+ function parseVastTime(value) {
904
+ if (!value) return void 0;
905
+ var parts = value.trim().split(":");
906
+ if (parts.length !== 3) return void 0;
907
+ var _parts_map = _sliced_to_array(parts.map(function(p) {
908
+ return parseFloat(p);
909
+ }), 3), h = _parts_map[0], m = _parts_map[1], s = _parts_map[2];
910
+ if (![
911
+ h,
912
+ m,
913
+ s
914
+ ].every(function(n) {
915
+ return n !== void 0 && Number.isFinite(n);
916
+ })) {
917
+ return void 0;
918
+ }
919
+ return h * 3600 + m * 60 + s;
920
+ }
921
+ function parseProgressOffset(offset) {
922
+ if (!offset) return void 0;
923
+ var trimmed = offset.trim();
924
+ if (trimmed.endsWith("%")) {
925
+ var percent = parseFloat(trimmed);
926
+ return Number.isFinite(percent) ? {
927
+ offsetPercent: percent
928
+ } : void 0;
929
+ }
930
+ var seconds = parseVastTime(trimmed);
931
+ return seconds !== void 0 ? {
932
+ offsetSeconds: seconds
933
+ } : void 0;
934
+ }
875
935
  var MAX_VAST_WRAPPER_DEPTH = 5;
876
936
  var BEACON_TIMEOUT_MS = 3e4;
877
937
  var inFlightBeacons = /* @__PURE__ */ new Set();
878
938
  var VAST_ERROR_MEDIA_DISPLAY = 405;
939
+ var VAST_ERROR_WRAPPER_TIMEOUT = 301;
940
+ var VAST_ERROR_WRAPPER_LIMIT = 302;
941
+ var VAST_ERROR_WRAPPER_NO_ADS = 303;
942
+ var VAST_ERROR_NO_SUPPORTED_MEDIA = 403;
943
+ var VERIFICATION_NOT_SUPPORTED_REASON = 2;
944
+ var VIEWABLE_MIN_VISIBLE_RATIO = 0.5;
945
+ var VIEWABLE_MIN_CONTINUOUS_S = 2;
879
946
  function toVastMediaErrorCode(error) {
880
947
  switch(error === null || error === void 0 ? void 0 : error.code){
881
948
  case 1:
@@ -903,6 +970,7 @@ function createHlsAdPlayer(contentVideo, options) {
903
970
  var adHls;
904
971
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
905
972
  var adEventHandlers = [];
973
+ var containerHandlers = [];
906
974
  var currentAd;
907
975
  var currentAdMediaFile;
908
976
  var podAds = [];
@@ -920,14 +988,28 @@ function createHlsAdPlayer(contentVideo, options) {
920
988
  var sawDecodedVideoFrame = false;
921
989
  var videoFrameCallbackHandle;
922
990
  var pendingPlayPromise;
923
- var trackingFired = {
924
- impression: false,
925
- start: false,
926
- firstQuartile: false,
927
- midpoint: false,
928
- thirdQuartile: false,
929
- complete: false
930
- };
991
+ function createTrackingState() {
992
+ return {
993
+ impression: false,
994
+ loaded: false,
995
+ start: false,
996
+ firstQuartile: false,
997
+ midpoint: false,
998
+ thirdQuartile: false,
999
+ complete: false,
1000
+ viewabilitySettled: false,
1001
+ lastMuted: void 0,
1002
+ progressFired: /* @__PURE__ */ new Set()
1003
+ };
1004
+ }
1005
+ var trackingFired = createTrackingState();
1006
+ var resolvedAds = /* @__PURE__ */ new Set();
1007
+ var viewObserver;
1008
+ var visibleRatio = 0;
1009
+ var continuousVisibleS = 0;
1010
+ var lastViewSampleTime;
1011
+ var lastPlayerExpanded = false;
1012
+ var documentHandlers = [];
931
1013
  function emit(event, payload) {
932
1014
  var set = listeners.get(event);
933
1015
  if (!set) return;
@@ -956,7 +1038,11 @@ function createHlsAdPlayer(contentVideo, options) {
956
1038
  }
957
1039
  }
958
1040
  }
959
- function buildTrackingMacroContext(errorCode) {
1041
+ function buildTrackingMacroContext() {
1042
+ var options2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
1043
+ var _options2_ad;
1044
+ var errorCode = options2.errorCode, reason = options2.reason;
1045
+ var ad = (_options2_ad = options2.ad) !== null && _options2_ad !== void 0 ? _options2_ad : currentAd;
960
1046
  var context = {
961
1047
  adPlayheadSeconds: adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.currentTime,
962
1048
  contentPlayheadSeconds: contentVideo.currentTime,
@@ -977,11 +1063,17 @@ function createHlsAdPlayer(contentVideo, options) {
977
1063
  if (podAds.length > 0) {
978
1064
  context.podSequence = podIndex + 1;
979
1065
  }
1066
+ if (ad === null || ad === void 0 ? void 0 : ad.adServingId) {
1067
+ context.adServingId = ad.adServingId;
1068
+ }
1069
+ if (reason != null) {
1070
+ context.reason = reason;
1071
+ }
980
1072
  return context;
981
1073
  }
982
1074
  function fireTrackingPixels(urls, options2) {
983
1075
  if (!urls || urls.length === 0) return;
984
- var macroContext = buildTrackingMacroContext(options2 === null || options2 === void 0 ? void 0 : options2.errorCode);
1076
+ var macroContext = buildTrackingMacroContext(options2);
985
1077
  urls.forEach(function(url) {
986
1078
  try {
987
1079
  var trackingUrl = substituteVastTrackingMacros(url, macroContext);
@@ -1092,8 +1184,8 @@ function createHlsAdPlayer(contentVideo, options) {
1092
1184
  var url = (mediaFile.url.toLowerCase().split("?")[0] || "").trim();
1093
1185
  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");
1094
1186
  }
1095
- function collectVideoMediaFiles(scope, verbose) {
1096
- var mediaFileElements = scope.querySelectorAll("MediaFile");
1187
+ function collectVideoMediaFiles(linear, verbose) {
1188
+ var mediaFileElements = linear.querySelectorAll(":scope > MediaFiles > MediaFile");
1097
1189
  var mediaFiles = [];
1098
1190
  if (verbose) {
1099
1191
  console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
@@ -1113,6 +1205,13 @@ function createHlsAdPlayer(contentVideo, options) {
1113
1205
  }
1114
1206
  return;
1115
1207
  }
1208
+ var apiFramework = (mf.getAttribute("apiFramework") || "").toUpperCase();
1209
+ if (apiFramework === "VPAID") {
1210
+ if (verbose) {
1211
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, " ignored (VPAID creatives are not supported)"));
1212
+ }
1213
+ return;
1214
+ }
1116
1215
  var bitrateAttr = mf.getAttribute("bitrate");
1117
1216
  var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1118
1217
  var mediaFile = {
@@ -1143,114 +1242,144 @@ function createHlsAdPlayer(contentVideo, options) {
1143
1242
  return mediaFiles;
1144
1243
  }
1145
1244
  function createEmptyTrackingUrls() {
1146
- return {
1245
+ var urls = {
1147
1246
  impression: [],
1148
- start: [],
1149
- firstQuartile: [],
1150
- midpoint: [],
1151
- thirdQuartile: [],
1152
- complete: [],
1153
- mute: [],
1154
- unmute: [],
1155
- pause: [],
1156
- resume: [],
1157
- fullscreen: [],
1158
- exitFullscreen: [],
1159
- skip: [],
1160
- error: []
1247
+ clickTracking: [],
1248
+ error: [],
1249
+ viewable: [],
1250
+ notViewable: [],
1251
+ viewUndetermined: [],
1252
+ verificationNotExecuted: [],
1253
+ progress: []
1161
1254
  };
1255
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1256
+ try {
1257
+ for(var _iterator = LINEAR_TRACKING_EVENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1258
+ var event = _step.value;
1259
+ urls[event] = [];
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
+ return urls;
1162
1276
  }
1163
- function extractTrackingUrls(scope) {
1164
- var trackingUrls = createEmptyTrackingUrls();
1165
- scope.querySelectorAll("Impression").forEach(function(el) {
1166
- var _el_textContent;
1167
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
1168
- if (url) trackingUrls.impression.push(url);
1277
+ function pushUrls(target, elements) {
1278
+ elements.forEach(function(el) {
1279
+ var url = textOf(el);
1280
+ if (url) target.push(url);
1169
1281
  });
1170
- scope.querySelectorAll("Tracking").forEach(function(el) {
1171
- var _el_textContent;
1282
+ }
1283
+ function collectLinearTracking(linear, into) {
1284
+ linear.querySelectorAll(":scope > TrackingEvents > Tracking").forEach(function(el) {
1172
1285
  var event = el.getAttribute("event");
1173
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
1174
- if (event && url) {
1175
- var eventKey = event;
1176
- if (trackingUrls[eventKey]) {
1177
- trackingUrls[eventKey].push(url);
1178
- }
1286
+ var url = textOf(el);
1287
+ if (!event || !url) return;
1288
+ if (event === "progress") {
1289
+ var offset = parseProgressOffset(el.getAttribute("offset"));
1290
+ if (offset) into.progress.push(_object_spread({
1291
+ url: url
1292
+ }, offset));
1293
+ return;
1294
+ }
1295
+ if (LINEAR_TRACKING_EVENTS.indexOf(event) !== -1) {
1296
+ into[event].push(url);
1179
1297
  }
1180
1298
  });
1181
- scope.querySelectorAll("Error").forEach(function(el) {
1182
- var _el_textContent;
1183
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
1184
- if (url) trackingUrls.error.push(url);
1299
+ pushUrls(into.clickTracking, linear.querySelectorAll(":scope > VideoClicks > ClickTracking"));
1300
+ }
1301
+ function collectAdLevelTracking(adBody, into) {
1302
+ pushUrls(into.impression, adBody.querySelectorAll(":scope > Impression"));
1303
+ pushUrls(into.error, adBody.querySelectorAll(":scope > Error"));
1304
+ pushUrls(into.viewable, adBody.querySelectorAll(":scope > ViewableImpression > Viewable"));
1305
+ pushUrls(into.notViewable, adBody.querySelectorAll(":scope > ViewableImpression > NotViewable"));
1306
+ pushUrls(into.viewUndetermined, adBody.querySelectorAll(":scope > ViewableImpression > ViewUndetermined"));
1307
+ adBody.querySelectorAll(':scope > AdVerifications > Verification, :scope > Extensions > Extension[type="AdVerifications"] > AdVerifications > Verification').forEach(function(verification) {
1308
+ pushUrls(into.verificationNotExecuted, verification.querySelectorAll(':scope > TrackingEvents > Tracking[event="verificationNotExecuted"]'));
1185
1309
  });
1186
- return trackingUrls;
1187
1310
  }
1188
1311
  function mergeTrackingUrls(target, source) {
1189
- Object.keys(target).forEach(function(key) {
1190
- if (source[key] && source[key].length > 0) {
1191
- target[key] = target[key].concat(source[key]);
1312
+ var targetLists = target;
1313
+ var sourceLists = source;
1314
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1315
+ try {
1316
+ for(var _iterator = Object.keys(targetLists)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1317
+ var key = _step.value;
1318
+ var incoming = sourceLists[key];
1319
+ if (incoming && incoming.length > 0) {
1320
+ targetLists[key] = targetLists[key].concat(incoming);
1321
+ }
1192
1322
  }
1193
- });
1323
+ } catch (err) {
1324
+ _didIteratorError = true;
1325
+ _iteratorError = err;
1326
+ } finally{
1327
+ try {
1328
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1329
+ _iterator.return();
1330
+ }
1331
+ } finally{
1332
+ if (_didIteratorError) {
1333
+ throw _iteratorError;
1334
+ }
1335
+ }
1336
+ }
1194
1337
  return target;
1195
1338
  }
1339
+ function parseXml(xmlString) {
1340
+ var xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
1341
+ var parserError = xmlDoc.querySelector("parsererror");
1342
+ if (parserError) {
1343
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1344
+ return null;
1345
+ }
1346
+ return xmlDoc;
1347
+ }
1348
+ function getAdSequence(adElement) {
1349
+ var sequence = parseInt(adElement.getAttribute("sequence") || "", 10);
1350
+ return Number.isFinite(sequence) ? sequence : void 0;
1351
+ }
1352
+ function emptyVastResult(root) {
1353
+ var errorUrls = [];
1354
+ pushUrls(errorUrls, root.querySelectorAll(":scope > Error"));
1355
+ return {
1356
+ type: "empty",
1357
+ errorUrls: errorUrls,
1358
+ errorCode: VAST_ERROR_WRAPPER_NO_ADS
1359
+ };
1360
+ }
1196
1361
  function parseVastXml(xmlString) {
1197
1362
  try {
1198
- var _xmlDoc_querySelector, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent1, _xmlDoc_querySelector2, _xmlDoc_querySelector3;
1199
- var parser = new DOMParser();
1200
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
1201
- var parserError = xmlDoc.querySelector("parsererror");
1202
- if (parserError) {
1203
- console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1204
- return {
1205
- type: "empty"
1206
- };
1207
- }
1208
- var adElement = xmlDoc.querySelector("Ad");
1363
+ var _adElements_find;
1364
+ var xmlDoc = parseXml(xmlString);
1365
+ if (!xmlDoc) return {
1366
+ type: "empty"
1367
+ };
1368
+ var root = xmlDoc.documentElement;
1369
+ var adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1370
+ var adElement = (_adElements_find = adElements.find(function(el) {
1371
+ return getAdSequence(el) === void 0;
1372
+ })) !== null && _adElements_find !== void 0 ? _adElements_find : adElements[0];
1209
1373
  if (!adElement) {
1210
- console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
1211
- return {
1212
- type: "empty"
1213
- };
1374
+ var _root_getAttribute;
1375
+ console.warn("[HlsAdPlayer] No Ad element found in VAST ".concat((_root_getAttribute = root.getAttribute("version")) !== null && _root_getAttribute !== void 0 ? _root_getAttribute : "", " response"));
1376
+ return emptyVastResult(root);
1214
1377
  }
1215
- var adId = adElement.getAttribute("id") || "unknown";
1216
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
1217
- 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();
1218
- 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();
1219
- if (wrapperUri) {
1220
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(wrapperUri));
1221
- return {
1222
- type: "wrapper",
1223
- vastAdTagUri: wrapperUri,
1224
- trackingUrls: extractTrackingUrls(xmlDoc),
1225
- clickThrough: clickThrough
1226
- };
1227
- }
1228
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
1229
- var durationText = ((_xmlDoc_querySelector3 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector3 === void 0 ? void 0 : _xmlDoc_querySelector3.textContent) || "00:00:30";
1230
- var durationParts = durationText.split(":");
1231
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
1232
- var mediaFiles = collectVideoMediaFiles(xmlDoc, true);
1233
- if (mediaFiles.length === 0) {
1234
- if (isNoAdAvailable) {
1235
- console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1236
- } else {
1237
- console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1238
- }
1239
- return {
1240
- type: "empty"
1241
- };
1378
+ var parsed = parseAdElement(adElement, true);
1379
+ if (parsed.type === "wrapper") {
1380
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
1242
1381
  }
1243
- return {
1244
- type: "inline",
1245
- ad: {
1246
- id: adId,
1247
- title: title,
1248
- duration: duration,
1249
- mediaFiles: mediaFiles,
1250
- trackingUrls: extractTrackingUrls(xmlDoc),
1251
- clickThrough: clickThrough
1252
- }
1253
- };
1382
+ return parsed;
1254
1383
  } catch (error) {
1255
1384
  console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
1256
1385
  return {
@@ -1259,48 +1388,101 @@ function createHlsAdPlayer(contentVideo, options) {
1259
1388
  }
1260
1389
  }
1261
1390
  function parseAdElement(adElement) {
1391
+ var verbose = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
1262
1392
  try {
1263
- var _adElement_querySelector, _adElement_querySelector_textContent, _adElement_querySelector1, _adElement_querySelector_textContent1, _adElement_querySelector2, _adElement_querySelector3;
1264
- var adId = adElement.getAttribute("id") || "unknown";
1265
- var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
1266
- 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();
1267
- 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();
1268
- if (wrapperUri) {
1393
+ var _parseVastTime;
1394
+ var wrapper = adElement.querySelector(":scope > Wrapper");
1395
+ if (wrapper) {
1396
+ var vastAdTagUri = textOf(wrapper.querySelector(":scope > VASTAdTagURI"));
1397
+ if (!vastAdTagUri) {
1398
+ console.warn("[HlsAdPlayer] <Wrapper> has no VASTAdTagURI");
1399
+ return {
1400
+ type: "empty"
1401
+ };
1402
+ }
1403
+ var trackingUrls2 = createEmptyTrackingUrls();
1404
+ collectAdLevelTracking(wrapper, trackingUrls2);
1405
+ wrapper.querySelectorAll(":scope > Creatives > Creative > Linear").forEach(function(linear2) {
1406
+ return collectLinearTracking(linear2, trackingUrls2);
1407
+ });
1269
1408
  return {
1270
1409
  type: "wrapper",
1271
- vastAdTagUri: wrapperUri,
1272
- trackingUrls: extractTrackingUrls(adElement),
1273
- clickThrough: clickThrough
1410
+ vastAdTagUri: vastAdTagUri,
1411
+ trackingUrls: trackingUrls2,
1412
+ rules: {
1413
+ followAdditionalWrappers: wrapper.getAttribute("followAdditionalWrappers") !== "false"
1414
+ }
1274
1415
  };
1275
1416
  }
1276
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
1277
- var durationText = ((_adElement_querySelector3 = adElement.querySelector("Duration")) === null || _adElement_querySelector3 === void 0 ? void 0 : _adElement_querySelector3.textContent) || "00:00:30";
1278
- var durationParts = durationText.split(":");
1279
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
1280
- var mediaFiles = collectVideoMediaFiles(adElement, false);
1281
- if (mediaFiles.length === 0) {
1282
- if (isNoAdAvailable) {
1283
- console.warn("[HlsAdPlayer] Pod <Ad> indicates no ad available");
1284
- } else {
1285
- console.warn("[HlsAdPlayer] No supported media files in pod <Ad>");
1286
- }
1417
+ var inLine = adElement.querySelector(":scope > InLine");
1418
+ if (!inLine) {
1419
+ console.warn("[HlsAdPlayer] <Ad> has neither <InLine> nor <Wrapper>");
1287
1420
  return {
1288
1421
  type: "empty"
1289
1422
  };
1290
1423
  }
1424
+ var errorUrls = [];
1425
+ pushUrls(errorUrls, inLine.querySelectorAll(":scope > Error"));
1426
+ if (adElement.getAttribute("conditionalAd") === "true") {
1427
+ console.warn("[HlsAdPlayer] Skipping conditional <Ad> (VPAID-only)");
1428
+ return {
1429
+ type: "empty",
1430
+ errorUrls: errorUrls,
1431
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1432
+ };
1433
+ }
1434
+ var linear;
1435
+ var mediaFiles = [];
1436
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1437
+ try {
1438
+ for(var _iterator = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear"))[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1439
+ var candidate = _step.value;
1440
+ var files = collectVideoMediaFiles(candidate, verbose);
1441
+ if (files.length > 0) {
1442
+ linear = candidate;
1443
+ mediaFiles = files;
1444
+ break;
1445
+ }
1446
+ }
1447
+ } catch (err) {
1448
+ _didIteratorError = true;
1449
+ _iteratorError = err;
1450
+ } finally{
1451
+ try {
1452
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1453
+ _iterator.return();
1454
+ }
1455
+ } finally{
1456
+ if (_didIteratorError) {
1457
+ throw _iteratorError;
1458
+ }
1459
+ }
1460
+ }
1461
+ if (!linear) {
1462
+ console.warn("[HlsAdPlayer] No supported linear media files in <Ad>");
1463
+ return {
1464
+ type: "empty",
1465
+ errorUrls: errorUrls,
1466
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1467
+ };
1468
+ }
1469
+ var trackingUrls = createEmptyTrackingUrls();
1470
+ collectAdLevelTracking(inLine, trackingUrls);
1471
+ collectLinearTracking(linear, trackingUrls);
1291
1472
  return {
1292
1473
  type: "inline",
1293
1474
  ad: {
1294
- id: adId,
1295
- title: title,
1296
- duration: duration,
1475
+ id: adElement.getAttribute("id") || "unknown",
1476
+ title: textOf(inLine.querySelector(":scope > AdTitle")) || "Ad",
1477
+ duration: (_parseVastTime = parseVastTime(textOf(linear.querySelector(":scope > Duration")))) !== null && _parseVastTime !== void 0 ? _parseVastTime : 30,
1297
1478
  mediaFiles: mediaFiles,
1298
- trackingUrls: extractTrackingUrls(adElement),
1299
- clickThrough: clickThrough
1479
+ trackingUrls: trackingUrls,
1480
+ clickThrough: textOf(linear.querySelector(":scope > VideoClicks > ClickThrough")),
1481
+ adServingId: textOf(inLine.querySelector(":scope > AdServingId"))
1300
1482
  }
1301
1483
  };
1302
1484
  } catch (error) {
1303
- console.error("[HlsAdPlayer] Error parsing pod <Ad> element:", error);
1485
+ console.error("[HlsAdPlayer] Error parsing <Ad> element:", error);
1304
1486
  return {
1305
1487
  type: "empty"
1306
1488
  };
@@ -1379,30 +1561,63 @@ function createHlsAdPlayer(contentVideo, options) {
1379
1561
  }
1380
1562
  function fetchAndParseVastAd(_0) {
1381
1563
  return _async_to_generator(function(vastTagUrl) {
1382
- var depth, accumulatedTracking, vastXml, parsed;
1564
+ var depth, accumulatedTracking, rules, vastXml, error, parsed, _parsed_errorUrls, _parsed_errorCode;
1383
1565
  var _arguments = arguments;
1384
1566
  return _ts_generator(this, function(_state) {
1385
1567
  switch(_state.label){
1386
1568
  case 0:
1387
- depth = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : 0, accumulatedTracking = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : createEmptyTrackingUrls();
1569
+ 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] : {
1570
+ followAdditionalWrappers: true
1571
+ };
1572
+ _state.label = 1;
1573
+ case 1:
1574
+ _state.trys.push([
1575
+ 1,
1576
+ 3,
1577
+ ,
1578
+ 4
1579
+ ]);
1388
1580
  return [
1389
1581
  4,
1390
1582
  fetchVastXml(vastTagUrl, depth === 0 ? "include" : "omit")
1391
1583
  ];
1392
- case 1:
1584
+ case 2:
1393
1585
  vastXml = _state.sent();
1586
+ return [
1587
+ 3,
1588
+ 4
1589
+ ];
1590
+ case 3:
1591
+ error = _state.sent();
1592
+ if (depth === 0) throw error;
1593
+ console.warn("[HlsAdPlayer] Wrapped VAST request failed:", error);
1594
+ fireTrackingPixels(accumulatedTracking.error, {
1595
+ errorCode: VAST_ERROR_WRAPPER_TIMEOUT
1596
+ });
1597
+ return [
1598
+ 2,
1599
+ null
1600
+ ];
1601
+ case 4:
1394
1602
  console.log("[HlsAdPlayer] VAST XML received");
1395
1603
  console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1396
1604
  parsed = parseVastXml(vastXml);
1397
1605
  if (parsed.type === "empty") {
1606
+ ;
1607
+ fireTrackingPixels(((_parsed_errorUrls = parsed.errorUrls) !== null && _parsed_errorUrls !== void 0 ? _parsed_errorUrls : []).concat(accumulatedTracking.error), {
1608
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1609
+ });
1398
1610
  return [
1399
1611
  2,
1400
1612
  null
1401
1613
  ];
1402
1614
  }
1403
1615
  if (parsed.type === "wrapper") {
1404
- if (depth >= MAX_VAST_WRAPPER_DEPTH) {
1405
- console.warn("[HlsAdPlayer] VAST wrapper depth limit (".concat(MAX_VAST_WRAPPER_DEPTH, ") reached, aborting redirect chain"));
1616
+ if (depth >= MAX_VAST_WRAPPER_DEPTH || !rules.followAdditionalWrappers) {
1617
+ 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');
1618
+ fireTrackingPixels(accumulatedTracking.error.concat(parsed.trackingUrls.error), {
1619
+ errorCode: VAST_ERROR_WRAPPER_LIMIT
1620
+ });
1406
1621
  return [
1407
1622
  2,
1408
1623
  null
@@ -1411,7 +1626,7 @@ function createHlsAdPlayer(contentVideo, options) {
1411
1626
  mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);
1412
1627
  return [
1413
1628
  2,
1414
- fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking)
1629
+ fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking, parsed.rules)
1415
1630
  ];
1416
1631
  }
1417
1632
  mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);
@@ -1425,7 +1640,7 @@ function createHlsAdPlayer(contentVideo, options) {
1425
1640
  }
1426
1641
  function fetchAndParsePod(vastTagUrl) {
1427
1642
  return _async_to_generator(function() {
1428
- var vastXml, trimmedXml, parser, xmlDoc, adElements, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, adElement, parsed, resolved, error, err;
1643
+ 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;
1429
1644
  return _ts_generator(this, function(_state) {
1430
1645
  switch(_state.label){
1431
1646
  case 0:
@@ -1444,125 +1659,212 @@ function createHlsAdPlayer(contentVideo, options) {
1444
1659
  []
1445
1660
  ];
1446
1661
  }
1447
- parser = new DOMParser();
1448
- xmlDoc = parser.parseFromString(vastXml, "text/xml");
1449
- if (xmlDoc.querySelector("parsererror")) {
1450
- console.error("[HlsAdPlayer] Pod VAST XML parsing error (malformed). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1662
+ xmlDoc = parseXml(vastXml);
1663
+ if (!xmlDoc) {
1664
+ console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1451
1665
  return [
1452
1666
  2,
1453
1667
  []
1454
1668
  ];
1455
1669
  }
1456
- adElements = Array.from(xmlDoc.querySelectorAll("Ad"));
1670
+ root = xmlDoc.documentElement;
1671
+ adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1457
1672
  if (adElements.length === 0) {
1458
- console.warn("[HlsAdPlayer] No <Ad> elements found in pod VAST response (no fill). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1673
+ ;
1674
+ ;
1675
+ 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)"));
1676
+ empty = emptyVastResult(root);
1677
+ if (empty.type === "empty" && ((_empty_errorUrls = empty.errorUrls) === null || _empty_errorUrls === void 0 ? void 0 : _empty_errorUrls.length)) {
1678
+ ;
1679
+ fireTrackingPixels(empty.errorUrls, {
1680
+ errorCode: (_empty_errorCode = empty.errorCode) !== null && _empty_errorCode !== void 0 ? _empty_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1681
+ });
1682
+ }
1459
1683
  return [
1460
1684
  2,
1461
1685
  []
1462
1686
  ];
1463
1687
  }
1464
- adElements.sort(function(a, b) {
1465
- var aSeq = parseInt(a.getAttribute("sequence") || "", 10);
1466
- var bSeq = parseInt(b.getAttribute("sequence") || "", 10);
1467
- var aVal = Number.isFinite(aSeq) ? aSeq : Number.MAX_SAFE_INTEGER;
1468
- var bVal = Number.isFinite(bSeq) ? bSeq : Number.MAX_SAFE_INTEGER;
1469
- return aVal - bVal;
1688
+ resolveAd = function resolveAd(adElement) {
1689
+ return _async_to_generator(function() {
1690
+ var _parsed_errorUrls, parsed, _parsed_errorCode;
1691
+ return _ts_generator(this, function(_state) {
1692
+ parsed = parseAdElement(adElement);
1693
+ if (parsed.type === "inline") return [
1694
+ 2,
1695
+ parsed.ad
1696
+ ];
1697
+ if (parsed.type === "wrapper") {
1698
+ return [
1699
+ 2,
1700
+ fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls, parsed.rules)
1701
+ ];
1702
+ }
1703
+ if ((_parsed_errorUrls = parsed.errorUrls) === null || _parsed_errorUrls === void 0 ? void 0 : _parsed_errorUrls.length) {
1704
+ ;
1705
+ fireTrackingPixels(parsed.errorUrls, {
1706
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_NO_SUPPORTED_MEDIA
1707
+ });
1708
+ }
1709
+ return [
1710
+ 2,
1711
+ null
1712
+ ];
1713
+ });
1714
+ })();
1715
+ };
1716
+ podElements = adElements.filter(function(el) {
1717
+ return getAdSequence(el) !== void 0;
1718
+ }).sort(function(a, b) {
1719
+ return getAdSequence(a) - getAdSequence(b);
1720
+ });
1721
+ buffet = adElements.filter(function(el) {
1722
+ return getAdSequence(el) === void 0;
1470
1723
  });
1471
1724
  ads = [];
1725
+ if (!(podElements.length === 0)) return [
1726
+ 3,
1727
+ 10
1728
+ ];
1472
1729
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1473
1730
  _state.label = 2;
1474
1731
  case 2:
1475
1732
  _state.trys.push([
1476
1733
  2,
1477
- 10,
1478
- 11,
1479
- 12
1734
+ 7,
1735
+ 8,
1736
+ 9
1480
1737
  ]);
1481
- _iterator = adElements[Symbol.iterator]();
1738
+ _iterator = buffet[Symbol.iterator]();
1482
1739
  _state.label = 3;
1483
1740
  case 3:
1484
1741
  if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
1485
1742
  3,
1486
- 9
1743
+ 6
1487
1744
  ];
1488
1745
  adElement = _step.value;
1489
- parsed = parseAdElement(adElement);
1490
- if (!(parsed.type === "inline")) return [
1491
- 3,
1492
- 4
1493
- ];
1494
- ads.push(parsed.ad);
1495
1746
  return [
1496
- 3,
1497
- 8
1747
+ 4,
1748
+ resolveAd(adElement)
1498
1749
  ];
1499
1750
  case 4:
1500
- if (!(parsed.type === "wrapper")) return [
1501
- 3,
1502
- 8
1503
- ];
1751
+ ad = _state.sent();
1752
+ if (ad) ads.push(ad);
1504
1753
  _state.label = 5;
1505
1754
  case 5:
1506
- _state.trys.push([
1507
- 5,
1508
- 7,
1509
- ,
1510
- 8
1511
- ]);
1755
+ _iteratorNormalCompletion = true;
1512
1756
  return [
1513
- 4,
1514
- fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls)
1757
+ 3,
1758
+ 3
1515
1759
  ];
1516
1760
  case 6:
1517
- resolved = _state.sent();
1518
- if (resolved) {
1519
- ads.push(resolved);
1520
- }
1521
1761
  return [
1522
1762
  3,
1523
- 8
1763
+ 9
1524
1764
  ];
1525
1765
  case 7:
1526
- error = _state.sent();
1527
- console.warn("[HlsAdPlayer] Failed to resolve wrapper <Ad> in pod:", error);
1766
+ err = _state.sent();
1767
+ _didIteratorError = true;
1768
+ _iteratorError = err;
1528
1769
  return [
1529
1770
  3,
1530
- 8
1771
+ 9
1531
1772
  ];
1532
1773
  case 8:
1533
- _iteratorNormalCompletion = true;
1774
+ try {
1775
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1776
+ _iterator.return();
1777
+ }
1778
+ } finally{
1779
+ if (_didIteratorError) {
1780
+ throw _iteratorError;
1781
+ }
1782
+ }
1534
1783
  return [
1535
- 3,
1536
- 3
1784
+ 7
1537
1785
  ];
1538
1786
  case 9:
1539
1787
  return [
1540
1788
  3,
1541
- 12
1789
+ 21
1542
1790
  ];
1543
1791
  case 10:
1544
- err = _state.sent();
1545
- _didIteratorError = true;
1546
- _iteratorError = err;
1792
+ _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
1793
+ _state.label = 11;
1794
+ case 11:
1795
+ _state.trys.push([
1796
+ 11,
1797
+ 19,
1798
+ 20,
1799
+ 21
1800
+ ]);
1801
+ _iterator1 = podElements[Symbol.iterator]();
1802
+ _state.label = 12;
1803
+ case 12:
1804
+ if (!!(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done)) return [
1805
+ 3,
1806
+ 18
1807
+ ];
1808
+ adElement1 = _step1.value;
1809
+ return [
1810
+ 4,
1811
+ resolveAd(adElement1)
1812
+ ];
1813
+ case 13:
1814
+ ad1 = _state.sent();
1815
+ _state.label = 14;
1816
+ case 14:
1817
+ if (!(!ad1 && buffet.length > 0)) return [
1818
+ 3,
1819
+ 16
1820
+ ];
1821
+ return [
1822
+ 4,
1823
+ resolveAd(buffet.shift())
1824
+ ];
1825
+ case 15:
1826
+ ad1 = _state.sent();
1827
+ return [
1828
+ 3,
1829
+ 14
1830
+ ];
1831
+ case 16:
1832
+ if (ad1) ads.push(ad1);
1833
+ _state.label = 17;
1834
+ case 17:
1835
+ _iteratorNormalCompletion1 = true;
1547
1836
  return [
1548
1837
  3,
1549
1838
  12
1550
1839
  ];
1551
- case 11:
1840
+ case 18:
1841
+ return [
1842
+ 3,
1843
+ 21
1844
+ ];
1845
+ case 19:
1846
+ err = _state.sent();
1847
+ _didIteratorError1 = true;
1848
+ _iteratorError1 = err;
1849
+ return [
1850
+ 3,
1851
+ 21
1852
+ ];
1853
+ case 20:
1552
1854
  try {
1553
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1554
- _iterator.return();
1855
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1856
+ _iterator1.return();
1555
1857
  }
1556
1858
  } finally{
1557
- if (_didIteratorError) {
1558
- throw _iteratorError;
1859
+ if (_didIteratorError1) {
1860
+ throw _iteratorError1;
1559
1861
  }
1560
1862
  }
1561
1863
  return [
1562
1864
  7
1563
1865
  ];
1564
- case 12:
1565
- console.log("[HlsAdPlayer] Parsed ".concat(ads.length, " ad(s) from pod VAST response"));
1866
+ case 21:
1867
+ 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"));
1566
1868
  return [
1567
1869
  2,
1568
1870
  ads
@@ -1592,7 +1894,40 @@ function createHlsAdPlayer(contentVideo, options) {
1592
1894
  var onTimeUpdate = function onTimeUpdate() {
1593
1895
  if (!currentAd || !adVideoElement) return;
1594
1896
  noteAdProgress();
1595
- var progress = adVideoElement.currentTime / currentAd.duration;
1897
+ sampleViewability();
1898
+ var currentTime = adVideoElement.currentTime;
1899
+ if (trackingFired.start) {
1900
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1901
+ try {
1902
+ for(var _iterator = currentAd.trackingUrls.progress[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1903
+ var event = _step.value;
1904
+ var _event_offsetSeconds, _event_offsetPercent;
1905
+ if (trackingFired.progressFired.has(event)) continue;
1906
+ 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;
1907
+ if (currentTime >= threshold) {
1908
+ trackingFired.progressFired.add(event);
1909
+ fireTrackingPixels([
1910
+ event.url
1911
+ ]);
1912
+ }
1913
+ }
1914
+ } catch (err) {
1915
+ _didIteratorError = true;
1916
+ _iteratorError = err;
1917
+ } finally{
1918
+ try {
1919
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1920
+ _iterator.return();
1921
+ }
1922
+ } finally{
1923
+ if (_didIteratorError) {
1924
+ throw _iteratorError;
1925
+ }
1926
+ }
1927
+ }
1928
+ }
1929
+ if (!(currentAd.duration > 0)) return;
1930
+ var progress = currentTime / currentAd.duration;
1596
1931
  if (progress >= 0.25 && !trackingFired.firstQuartile) {
1597
1932
  trackingFired.firstQuartile = true;
1598
1933
  fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
@@ -1614,15 +1949,38 @@ function createHlsAdPlayer(contentVideo, options) {
1614
1949
  handleVideoDecodeFailure();
1615
1950
  }
1616
1951
  };
1952
+ var onCanPlay = function onCanPlay() {
1953
+ if (!currentAd || trackingFired.loaded) return;
1954
+ trackingFired.loaded = true;
1955
+ fireTrackingPixels(currentAd.trackingUrls.loaded);
1956
+ };
1617
1957
  var onPlaying = function onPlaying() {
1618
1958
  startStallWatchdog();
1619
- if (!currentAd || trackingFired.start) return;
1959
+ if (!currentAd || !adVideoElement) return;
1960
+ if (!trackingFired.impression) {
1961
+ trackingFired.impression = true;
1962
+ resolvedAds.add(currentAd);
1963
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1964
+ fireTrackingPixels(currentAd.trackingUrls.creativeView);
1965
+ fireTrackingPixels(currentAd.trackingUrls.verificationNotExecuted, {
1966
+ reason: VERIFICATION_NOT_SUPPORTED_REASON
1967
+ });
1968
+ emit("ad_impression", {
1969
+ adId: currentAd.id,
1970
+ index: podIndex,
1971
+ total: podAds.length || 1
1972
+ });
1973
+ }
1974
+ if (trackingFired.start) return;
1620
1975
  trackingFired.start = true;
1976
+ trackingFired.lastMuted = adVideoElement.muted || adVideoElement.volume === 0;
1621
1977
  fireTrackingPixels(currentAd.trackingUrls.start);
1622
1978
  console.log("[HlsAdPlayer] Ad started playing");
1623
1979
  };
1624
1980
  var onEnded = function onEnded() {
1625
1981
  if (!currentAd || trackingFired.complete) return;
1982
+ sampleViewability();
1983
+ settleViewability();
1626
1984
  trackingFired.complete = true;
1627
1985
  fireTrackingPixels(currentAd.trackingUrls.complete);
1628
1986
  console.log("[HlsAdPlayer] Ad completed");
@@ -1634,11 +1992,7 @@ function createHlsAdPlayer(contentVideo, options) {
1634
1992
  var onError = function onError(e) {
1635
1993
  if (!adPlaying) return;
1636
1994
  console.error("[HlsAdPlayer] Ad video error:", e);
1637
- if (currentAd) {
1638
- fireTrackingPixels(currentAd.trackingUrls.error, {
1639
- errorCode: toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error)
1640
- });
1641
- }
1995
+ reportCurrentAdError(toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error));
1642
1996
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1643
1997
  return;
1644
1998
  }
@@ -1646,19 +2000,26 @@ function createHlsAdPlayer(contentVideo, options) {
1646
2000
  };
1647
2001
  var onVolumeChange = function onVolumeChange() {
1648
2002
  if (!currentAd || !adVideoElement) return;
1649
- if (adVideoElement.muted) {
1650
- fireTrackingPixels(currentAd.trackingUrls.mute);
1651
- } else {
1652
- fireTrackingPixels(currentAd.trackingUrls.unmute);
2003
+ var muted = adVideoElement.muted || adVideoElement.volume === 0;
2004
+ if (!trackingFired.start) {
2005
+ trackingFired.lastMuted = muted;
2006
+ return;
1653
2007
  }
2008
+ if (muted === trackingFired.lastMuted) return;
2009
+ trackingFired.lastMuted = muted;
2010
+ fireTrackingPixels(muted ? currentAd.trackingUrls.mute : currentAd.trackingUrls.unmute);
2011
+ };
2012
+ var isTrackablePlayback = function isTrackablePlayback() {
2013
+ return adPlaying && !!currentAd && !!adVideoElement && trackingFired.start && !trackingFired.complete && !adVideoElement.ended;
1654
2014
  };
1655
2015
  var onPause = function onPause() {
1656
- if (currentAd && adVideoElement && !adVideoElement.ended) {
2016
+ continuousVisibleS = 0;
2017
+ if (isTrackablePlayback()) {
1657
2018
  fireTrackingPixels(currentAd.trackingUrls.pause);
1658
2019
  }
1659
2020
  };
1660
2021
  var onPlay = function onPlay() {
1661
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
2022
+ if (isTrackablePlayback()) {
1662
2023
  fireTrackingPixels(currentAd.trackingUrls.resume);
1663
2024
  }
1664
2025
  };
@@ -1671,6 +2032,10 @@ function createHlsAdPlayer(contentVideo, options) {
1671
2032
  type: "loadedmetadata",
1672
2033
  handler: onLoadedMetadata
1673
2034
  },
2035
+ {
2036
+ type: "canplay",
2037
+ handler: onCanPlay
2038
+ },
1674
2039
  {
1675
2040
  type: "playing",
1676
2041
  handler: onPlaying
@@ -1742,6 +2107,229 @@ function createHlsAdPlayer(contentVideo, options) {
1742
2107
  }
1743
2108
  adEventHandlers = [];
1744
2109
  }
2110
+ function handleAdClick() {
2111
+ if (!adPlaying || !currentAd) return;
2112
+ fireTrackingPixels(currentAd.trackingUrls.clickTracking);
2113
+ emit("ad_click", {
2114
+ adId: currentAd.id,
2115
+ clickThrough: currentAd.clickThrough
2116
+ });
2117
+ if (currentAd.clickThrough) {
2118
+ try {
2119
+ window.open(currentAd.clickThrough, "_blank", "noopener");
2120
+ } catch (error) {
2121
+ console.warn("[HlsAdPlayer] Failed to open ClickThrough URL:", error);
2122
+ }
2123
+ }
2124
+ }
2125
+ function reportCurrentAdError(errorCode) {
2126
+ if (!currentAd) return;
2127
+ resolvedAds.add(currentAd);
2128
+ fireTrackingPixels(currentAd.trackingUrls.error, {
2129
+ errorCode: errorCode
2130
+ });
2131
+ }
2132
+ function fireNotUsedForUnplayedAds() {
2133
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2134
+ try {
2135
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2136
+ var ad = _step.value;
2137
+ if (resolvedAds.has(ad)) continue;
2138
+ resolvedAds.add(ad);
2139
+ fireTrackingPixels(ad.trackingUrls.notUsed, {
2140
+ ad: ad
2141
+ });
2142
+ }
2143
+ } catch (err) {
2144
+ _didIteratorError = true;
2145
+ _iteratorError = err;
2146
+ } finally{
2147
+ try {
2148
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2149
+ _iterator.return();
2150
+ }
2151
+ } finally{
2152
+ if (_didIteratorError) {
2153
+ throw _iteratorError;
2154
+ }
2155
+ }
2156
+ }
2157
+ }
2158
+ function sampleViewability() {
2159
+ if (!currentAd || !adVideoElement || !viewObserver || !trackingFired.impression || trackingFired.viewabilitySettled) {
2160
+ return;
2161
+ }
2162
+ var now = adVideoElement.currentTime;
2163
+ var inView = visibleRatio >= VIEWABLE_MIN_VISIBLE_RATIO && document.visibilityState === "visible" && !adVideoElement.paused;
2164
+ if (!inView) {
2165
+ continuousVisibleS = 0;
2166
+ } else if (lastViewSampleTime !== void 0 && now >= lastViewSampleTime) {
2167
+ continuousVisibleS += now - lastViewSampleTime;
2168
+ }
2169
+ lastViewSampleTime = now;
2170
+ if (continuousVisibleS >= VIEWABLE_MIN_CONTINUOUS_S) {
2171
+ trackingFired.viewabilitySettled = true;
2172
+ fireTrackingPixels(currentAd.trackingUrls.viewable);
2173
+ }
2174
+ }
2175
+ function settleViewability() {
2176
+ if (!currentAd || !trackingFired.impression || trackingFired.viewabilitySettled) {
2177
+ return;
2178
+ }
2179
+ trackingFired.viewabilitySettled = true;
2180
+ fireTrackingPixels(viewObserver ? currentAd.trackingUrls.notViewable : currentAd.trackingUrls.viewUndetermined);
2181
+ }
2182
+ function handleFullscreenChange() {
2183
+ var _document_fullscreenElement;
2184
+ if (!adPlaying || !currentAd || !adContainerEl || !trackingFired.start) return;
2185
+ var fullscreenEl = (_document_fullscreenElement = document.fullscreenElement) !== null && _document_fullscreenElement !== void 0 ? _document_fullscreenElement : document.webkitFullscreenElement;
2186
+ var expanded = !!fullscreenEl && fullscreenEl.contains(adContainerEl);
2187
+ if (expanded === lastPlayerExpanded) return;
2188
+ lastPlayerExpanded = expanded;
2189
+ var urls = currentAd.trackingUrls;
2190
+ fireTrackingPixels(expanded ? urls.fullscreen.concat(urls.playerExpand) : urls.exitFullscreen.concat(urls.playerCollapse));
2191
+ }
2192
+ function attachContainerHandlers() {
2193
+ if (!adContainerEl || containerHandlers.length > 0) return;
2194
+ var onClick = function onClick() {
2195
+ return handleAdClick();
2196
+ };
2197
+ var onInteraction = function onInteraction(event) {
2198
+ if (adPlaying) emit("ad_interaction", event);
2199
+ };
2200
+ containerHandlers = [
2201
+ {
2202
+ type: "click",
2203
+ handler: onClick
2204
+ },
2205
+ {
2206
+ type: "mousedown",
2207
+ handler: onInteraction
2208
+ },
2209
+ {
2210
+ type: "touchstart",
2211
+ handler: onInteraction
2212
+ }
2213
+ ];
2214
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2215
+ try {
2216
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2217
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
2218
+ adContainerEl.addEventListener(type, handler);
2219
+ }
2220
+ } catch (err) {
2221
+ _didIteratorError = true;
2222
+ _iteratorError = err;
2223
+ } finally{
2224
+ try {
2225
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2226
+ _iterator.return();
2227
+ }
2228
+ } finally{
2229
+ if (_didIteratorError) {
2230
+ throw _iteratorError;
2231
+ }
2232
+ }
2233
+ }
2234
+ var onFullscreenChange = function onFullscreenChange() {
2235
+ return handleFullscreenChange();
2236
+ };
2237
+ documentHandlers = [
2238
+ {
2239
+ type: "fullscreenchange",
2240
+ handler: onFullscreenChange
2241
+ },
2242
+ {
2243
+ type: "webkitfullscreenchange",
2244
+ handler: onFullscreenChange
2245
+ }
2246
+ ];
2247
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2248
+ try {
2249
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2250
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
2251
+ document.addEventListener(type1, handler1);
2252
+ }
2253
+ } catch (err) {
2254
+ _didIteratorError1 = true;
2255
+ _iteratorError1 = err;
2256
+ } finally{
2257
+ try {
2258
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2259
+ _iterator1.return();
2260
+ }
2261
+ } finally{
2262
+ if (_didIteratorError1) {
2263
+ throw _iteratorError1;
2264
+ }
2265
+ }
2266
+ }
2267
+ if (typeof IntersectionObserver !== "undefined") {
2268
+ viewObserver = new IntersectionObserver(function(entries) {
2269
+ var entry = entries[entries.length - 1];
2270
+ if (entry) {
2271
+ visibleRatio = entry.isIntersecting ? entry.intersectionRatio : 0;
2272
+ }
2273
+ }, {
2274
+ threshold: [
2275
+ 0,
2276
+ 0.25,
2277
+ 0.5,
2278
+ 0.75,
2279
+ 1
2280
+ ]
2281
+ });
2282
+ viewObserver.observe(adContainerEl);
2283
+ }
2284
+ }
2285
+ function detachContainerHandlers() {
2286
+ if (adContainerEl) {
2287
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2288
+ try {
2289
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2290
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
2291
+ adContainerEl.removeEventListener(type, handler);
2292
+ }
2293
+ } catch (err) {
2294
+ _didIteratorError = true;
2295
+ _iteratorError = err;
2296
+ } finally{
2297
+ try {
2298
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2299
+ _iterator.return();
2300
+ }
2301
+ } finally{
2302
+ if (_didIteratorError) {
2303
+ throw _iteratorError;
2304
+ }
2305
+ }
2306
+ }
2307
+ }
2308
+ containerHandlers = [];
2309
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2310
+ try {
2311
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2312
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
2313
+ document.removeEventListener(type1, handler1);
2314
+ }
2315
+ } catch (err) {
2316
+ _didIteratorError1 = true;
2317
+ _iteratorError1 = err;
2318
+ } finally{
2319
+ try {
2320
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2321
+ _iterator1.return();
2322
+ }
2323
+ } finally{
2324
+ if (_didIteratorError1) {
2325
+ throw _iteratorError1;
2326
+ }
2327
+ }
2328
+ }
2329
+ documentHandlers = [];
2330
+ viewObserver === null || viewObserver === void 0 ? void 0 : viewObserver.disconnect();
2331
+ viewObserver = void 0;
2332
+ }
1745
2333
  function setAdPlayingFlag(isPlaying) {
1746
2334
  if (isPlaying) {
1747
2335
  contentVideo.dataset.stormcloudAdPlaying = "true";
@@ -1749,15 +2337,10 @@ function createHlsAdPlayer(contentVideo, options) {
1749
2337
  delete contentVideo.dataset.stormcloudAdPlaying;
1750
2338
  }
1751
2339
  }
1752
- function resetQuartileTracking(preserveImpression) {
1753
- trackingFired = {
1754
- impression: preserveImpression ? trackingFired.impression : false,
1755
- start: false,
1756
- firstQuartile: false,
1757
- midpoint: false,
1758
- thirdQuartile: false,
1759
- complete: false
1760
- };
2340
+ function resetAdTracking() {
2341
+ trackingFired = createTrackingState();
2342
+ continuousVisibleS = 0;
2343
+ lastViewSampleTime = void 0;
1761
2344
  }
1762
2345
  function isRvfcSupported(video) {
1763
2346
  return typeof video.requestVideoFrameCallback === "function";
@@ -1863,13 +2446,12 @@ function createHlsAdPlayer(contentVideo, options) {
1863
2446
  if (podIndex >= podAds.length - 1) {
1864
2447
  return false;
1865
2448
  }
2449
+ settleViewability();
1866
2450
  podIndex++;
1867
2451
  currentAd = podAds[podIndex];
1868
2452
  currentAdMediaFile = void 0;
1869
- resetQuartileTracking(false);
2453
+ resetAdTracking();
1870
2454
  if (currentAd) {
1871
- fireTrackingPixels(currentAd.trackingUrls.impression);
1872
- trackingFired.impression = true;
1873
2455
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1874
2456
  }
1875
2457
  clearStallWatchdog();
@@ -1907,11 +2489,7 @@ function createHlsAdPlayer(contentVideo, options) {
1907
2489
  function handleAdStall() {
1908
2490
  console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
1909
2491
  clearStallWatchdog();
1910
- if (currentAd) {
1911
- fireTrackingPixels(currentAd.trackingUrls.error, {
1912
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1913
- });
1914
- }
2492
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1915
2493
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1916
2494
  return;
1917
2495
  }
@@ -1977,11 +2555,7 @@ function createHlsAdPlayer(contentVideo, options) {
1977
2555
  function handleVideoDecodeFailure() {
1978
2556
  console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1979
2557
  clearStallWatchdog();
1980
- if (currentAd) {
1981
- fireTrackingPixels(currentAd.trackingUrls.error, {
1982
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1983
- });
1984
- }
2558
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1985
2559
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1986
2560
  return;
1987
2561
  }
@@ -2036,6 +2610,7 @@ function createHlsAdPlayer(contentVideo, options) {
2036
2610
  }
2037
2611
  function handleAdComplete() {
2038
2612
  console.log("[HlsAdPlayer] Handling ad completion");
2613
+ settleViewability();
2039
2614
  clearStallWatchdog();
2040
2615
  adPlaying = false;
2041
2616
  setAdPlayingFlag(false);
@@ -2059,6 +2634,7 @@ function createHlsAdPlayer(contentVideo, options) {
2059
2634
  }
2060
2635
  function handleAdError() {
2061
2636
  console.log("[HlsAdPlayer] Handling ad error");
2637
+ settleViewability();
2062
2638
  clearStallWatchdog();
2063
2639
  adPlaying = false;
2064
2640
  setAdPlayingFlag(false);
@@ -2091,6 +2667,7 @@ function createHlsAdPlayer(contentVideo, options) {
2091
2667
  adContainerEl = container;
2092
2668
  }
2093
2669
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
2670
+ attachContainerHandlers();
2094
2671
  },
2095
2672
  requestAds: function requestAds(vastTagUrl) {
2096
2673
  return _async_to_generator(function() {
@@ -2153,10 +2730,6 @@ function createHlsAdPlayer(contentVideo, options) {
2153
2730
  currentAd = ads[0];
2154
2731
  currentAdMediaFile = void 0;
2155
2732
  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"));
2156
- if (currentAd) {
2157
- fireTrackingPixels(currentAd.trackingUrls.impression);
2158
- trackingFired.impression = true;
2159
- }
2160
2733
  return [
2161
2734
  2,
2162
2735
  Promise.resolve()
@@ -2196,7 +2769,7 @@ function createHlsAdPlayer(contentVideo, options) {
2196
2769
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
2197
2770
  }
2198
2771
  setupAdEventListeners();
2199
- resetQuartileTracking(true);
2772
+ resetAdTracking();
2200
2773
  contentVolume = contentVideo.volume;
2201
2774
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
2202
2775
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -2267,6 +2840,8 @@ function createHlsAdPlayer(contentVideo, options) {
2267
2840
  var previousMutedState;
2268
2841
  return _ts_generator(this, function(_state) {
2269
2842
  console.log("[HlsAdPlayer] Stopping ad");
2843
+ settleViewability();
2844
+ fireNotUsedForUnplayedAds();
2270
2845
  clearStallWatchdog();
2271
2846
  adPlaying = false;
2272
2847
  setAdPlayingFlag(false);
@@ -2297,6 +2872,8 @@ function createHlsAdPlayer(contentVideo, options) {
2297
2872
  },
2298
2873
  destroy: function destroy() {
2299
2874
  console.log("[HlsAdPlayer] Destroying");
2875
+ settleViewability();
2876
+ fireNotUsedForUnplayedAds();
2300
2877
  destroyed = true;
2301
2878
  clearStallWatchdog();
2302
2879
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2325,6 +2902,7 @@ function createHlsAdPlayer(contentVideo, options) {
2325
2902
  contentVideo.muted = originalMutedState;
2326
2903
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
2327
2904
  teardownAdEventListeners();
2905
+ detachContainerHandlers();
2328
2906
  releaseAdDecoder();
2329
2907
  currentAd = void 0;
2330
2908
  currentAdMediaFile = void 0;
@@ -2470,6 +3048,7 @@ function toDevSafeUrl(rawUrl) {
2470
3048
  // src/sdk/pal.ts
2471
3049
  var PAL_SDK_URL = "https://imasdk.googleapis.com/pal/sdkloader/pal.js";
2472
3050
  var _nonceLoader;
3051
+ var _nonceLoaderAllowStorage;
2473
3052
  var _palLoadPromise;
2474
3053
  function loadPalSdk() {
2475
3054
  var _window_goog;
@@ -2512,12 +3091,15 @@ function loadPalSdk() {
2512
3091
  });
2513
3092
  return _palLoadPromise;
2514
3093
  }
2515
- function getOrCreateNonceLoader() {
2516
- if (_nonceLoader) return _nonceLoader;
3094
+ function getOrCreateNonceLoader(allowStorage) {
3095
+ if (_nonceLoader && _nonceLoaderAllowStorage === allowStorage) {
3096
+ return _nonceLoader;
3097
+ }
2517
3098
  var goog = window.goog;
2518
3099
  var consentSettings = new goog.pal.ConsentSettings();
2519
- consentSettings.allowStorage = true;
3100
+ consentSettings.allowStorage = allowStorage;
2520
3101
  _nonceLoader = new goog.pal.NonceLoader(consentSettings);
3102
+ _nonceLoaderAllowStorage = allowStorage;
2521
3103
  return _nonceLoader;
2522
3104
  }
2523
3105
  function createPalNonceManager() {
@@ -2526,7 +3108,7 @@ function createPalNonceManager() {
2526
3108
  return {
2527
3109
  generateNonce: function generateNonce() {
2528
3110
  return _async_to_generator(function() {
2529
- var options, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
3111
+ var options, _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
2530
3112
  var _arguments = arguments;
2531
3113
  return _ts_generator(this, function(_state) {
2532
3114
  switch(_state.label){
@@ -2546,7 +3128,7 @@ function createPalNonceManager() {
2546
3128
  ];
2547
3129
  case 2:
2548
3130
  _state.sent();
2549
- loader = getOrCreateNonceLoader();
3131
+ loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
2550
3132
  goog = window.goog;
2551
3133
  request = new goog.pal.NonceRequest();
2552
3134
  request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
@@ -2737,6 +3319,8 @@ function ingestPlayerTracking(licenseKey, channel, body) {
2737
3319
  }
2738
3320
  // src/utils/vastEnvironmentSignals.ts
2739
3321
  var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3322
+ var WEB_SESSION_STORAGE_KEY = "stormcloud.web.sid";
3323
+ var inMemoryWebSessionId;
2740
3324
  var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
2741
3325
  var DEVICE_ID_STORAGE_KEYS = [
2742
3326
  "rdid",
@@ -2758,7 +3342,7 @@ function resolveVastEnvironmentSignals(isCtv) {
2758
3342
  var _ref;
2759
3343
  var bridgeSignals = readNativeBridgeSignals();
2760
3344
  var platformDevice = readPlatformNativeDeviceId();
2761
- var realDeviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
3345
+ var realDeviceId = bridgeSignals.deviceId || (isCtv ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
2762
3346
  var deviceId = realDeviceId;
2763
3347
  var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
2764
3348
  var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
@@ -2772,6 +3356,7 @@ function resolveVastEnvironmentSignals(isCtv) {
2772
3356
  limitAdTracking = (_ref1 = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref1 !== void 0 ? _ref1 : false;
2773
3357
  }
2774
3358
  }
3359
+ var deviceTypeHint = resolveDeviceTypeHint(isCtv);
2775
3360
  if (isCtv) {
2776
3361
  return _object_spread_props(_object_spread({
2777
3362
  isCtv: true,
@@ -2783,18 +3368,157 @@ function resolveVastEnvironmentSignals(isCtv) {
2783
3368
  } : {}, deviceId && limitAdTracking != null ? {
2784
3369
  limitAdTracking: limitAdTracking
2785
3370
  } : {}), {
2786
- deviceTypeHint: 5
3371
+ deviceTypeHint: deviceTypeHint
2787
3372
  });
2788
3373
  }
2789
- return _object_spread({
3374
+ var webSessionId = getOrCreateWebSessionId();
3375
+ return _object_spread_props(_object_spread({
2790
3376
  isCtv: false
2791
- }, deviceId ? {
3377
+ }, webSessionId ? {
3378
+ sessionId: webSessionId
3379
+ } : {}, deviceId ? {
2792
3380
  deviceId: deviceId
2793
3381
  } : {}, deviceId && deviceIdType ? {
2794
3382
  deviceIdType: deviceIdType
2795
3383
  } : {}, deviceId && limitAdTracking != null ? {
2796
3384
  limitAdTracking: limitAdTracking
2797
- } : {});
3385
+ } : {}), {
3386
+ deviceTypeHint: deviceTypeHint
3387
+ });
3388
+ }
3389
+ var DEVICE_TYPE_HINT = {
3390
+ FEATURE_PHONE: 1,
3391
+ SMARTPHONE: 2,
3392
+ DESKTOP: 3,
3393
+ TABLET: 4,
3394
+ CONNECTED_TV: 5,
3395
+ GAME_CONSOLE: 6,
3396
+ SET_TOP_BOX: 7
3397
+ };
3398
+ var DEVICE_TYPE_HINT_ALIASES = {
3399
+ featurephone: DEVICE_TYPE_HINT.FEATURE_PHONE,
3400
+ smartphone: DEVICE_TYPE_HINT.SMARTPHONE,
3401
+ mobile: DEVICE_TYPE_HINT.SMARTPHONE,
3402
+ phone: DEVICE_TYPE_HINT.SMARTPHONE,
3403
+ desktop: DEVICE_TYPE_HINT.DESKTOP,
3404
+ pc: DEVICE_TYPE_HINT.DESKTOP,
3405
+ tablet: DEVICE_TYPE_HINT.TABLET,
3406
+ ctv: DEVICE_TYPE_HINT.CONNECTED_TV,
3407
+ tv: DEVICE_TYPE_HINT.CONNECTED_TV,
3408
+ connectedtv: DEVICE_TYPE_HINT.CONNECTED_TV,
3409
+ smarttv: DEVICE_TYPE_HINT.CONNECTED_TV,
3410
+ console: DEVICE_TYPE_HINT.GAME_CONSOLE,
3411
+ gameconsole: DEVICE_TYPE_HINT.GAME_CONSOLE,
3412
+ stb: DEVICE_TYPE_HINT.SET_TOP_BOX,
3413
+ settopbox: DEVICE_TYPE_HINT.SET_TOP_BOX
3414
+ };
3415
+ 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;
3416
+ var GAME_CONSOLE_UA = /PlayStation|Xbox|Nintendo/i;
3417
+ 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;
3418
+ var FEATURE_PHONE_UA = /KAIOS|MIDP|J2ME|Series40|Opera Mini/i;
3419
+ function resolveDeviceTypeHint(isCtv) {
3420
+ var override = readDeviceTypeHintOverride(isCtv);
3421
+ if (override != null) return override;
3422
+ return inferDeviceTypeHint(isCtv);
3423
+ }
3424
+ function inferDeviceTypeHint(isCtv) {
3425
+ var fallback = isCtv ? DEVICE_TYPE_HINT.CONNECTED_TV : DEVICE_TYPE_HINT.DESKTOP;
3426
+ if (typeof navigator === "undefined") return fallback;
3427
+ var ua = navigator.userAgent || "";
3428
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
3429
+ if (SET_TOP_BOX_UA.test(ua)) return DEVICE_TYPE_HINT.SET_TOP_BOX;
3430
+ if (GAME_CONSOLE_UA.test(ua)) return DEVICE_TYPE_HINT.GAME_CONSOLE;
3431
+ if (CONNECTED_TV_UA.test(ua) && !/Mobile/i.test(ua)) {
3432
+ return DEVICE_TYPE_HINT.CONNECTED_TV;
3433
+ }
3434
+ if (FEATURE_PHONE_UA.test(ua)) return DEVICE_TYPE_HINT.FEATURE_PHONE;
3435
+ if (/iPad/i.test(ua) || /Macintosh/i.test(ua) && maxTouchPoints > 1) {
3436
+ return DEVICE_TYPE_HINT.TABLET;
3437
+ }
3438
+ if (/iPhone|iPod/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3439
+ if (/Android/i.test(ua)) {
3440
+ if (/Mobile/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3441
+ if (maxTouchPoints === 0) return DEVICE_TYPE_HINT.SET_TOP_BOX;
3442
+ return DEVICE_TYPE_HINT.TABLET;
3443
+ }
3444
+ if (/Mobile|Windows Phone|BlackBerry/i.test(ua)) return DEVICE_TYPE_HINT.SMARTPHONE;
3445
+ return fallback;
3446
+ }
3447
+ function readDeviceTypeHintOverride(isCtv) {
3448
+ if (typeof window === "undefined") return void 0;
3449
+ var keys = [
3450
+ "dth",
3451
+ "deviceTypeHint"
3452
+ ];
3453
+ var fromGlobal = normalizeDeviceTypeHint(window.__STORMCLOUD_DTH__);
3454
+ if (fromGlobal != null) return fromGlobal;
3455
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3456
+ try {
3457
+ for(var _iterator = getNativeBridgeSources()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3458
+ var source = _step.value;
3459
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
3460
+ try {
3461
+ for(var _iterator1 = keys[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
3462
+ var key = _step1.value;
3463
+ var value = source === null || source === void 0 ? void 0 : source[key];
3464
+ var normalized = normalizeDeviceTypeHint(typeof value === "function" ? safeCall(value, source) : value);
3465
+ if (normalized != null) return normalized;
3466
+ }
3467
+ } catch (err) {
3468
+ _didIteratorError1 = true;
3469
+ _iteratorError1 = err;
3470
+ } finally{
3471
+ try {
3472
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
3473
+ _iterator1.return();
3474
+ }
3475
+ } finally{
3476
+ if (_didIteratorError1) {
3477
+ throw _iteratorError1;
3478
+ }
3479
+ }
3480
+ }
3481
+ }
3482
+ } catch (err) {
3483
+ _didIteratorError = true;
3484
+ _iteratorError = err;
3485
+ } finally{
3486
+ try {
3487
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3488
+ _iterator.return();
3489
+ }
3490
+ } finally{
3491
+ if (_didIteratorError) {
3492
+ throw _iteratorError;
3493
+ }
3494
+ }
3495
+ }
3496
+ if (!isCtv) return void 0;
3497
+ for(var _i = 0, _iter = [
3498
+ "stormcloud.dth",
3499
+ "dth"
3500
+ ]; _i < _iter.length; _i++){
3501
+ var key1 = _iter[_i];
3502
+ var normalized1 = normalizeDeviceTypeHint(readStoredString(key1));
3503
+ if (normalized1 != null) return normalized1;
3504
+ }
3505
+ return void 0;
3506
+ }
3507
+ function normalizeDeviceTypeHint(value) {
3508
+ if (typeof value === "number") {
3509
+ return Number.isInteger(value) && value >= 1 && value <= 7 ? value : void 0;
3510
+ }
3511
+ if (typeof value !== "string") return void 0;
3512
+ var trimmed = value.trim();
3513
+ if (/^[1-7]$/.test(trimmed)) return parseInt(trimmed, 10);
3514
+ return DEVICE_TYPE_HINT_ALIASES[trimmed.toLowerCase().replace(/[\s_-]/g, "")];
3515
+ }
3516
+ function safeCall(fn, thisArg) {
3517
+ try {
3518
+ return fn.call(thisArg);
3519
+ } catch (unused) {
3520
+ return void 0;
3521
+ }
2798
3522
  }
2799
3523
  function inferDeviceIdType() {
2800
3524
  if (typeof navigator === "undefined") {
@@ -2818,9 +3542,10 @@ function isEquivalentDeviceIdType(tagType, runtimeType) {
2818
3542
  return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2819
3543
  }
2820
3544
  function resolveNativeDeviceId() {
3545
+ var includeStored = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
2821
3546
  var bridgeSignals = readNativeBridgeSignals();
2822
3547
  var platformDevice = readPlatformNativeDeviceId();
2823
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
3548
+ var deviceId = bridgeSignals.deviceId || (includeStored ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
2824
3549
  if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {
2825
3550
  return void 0;
2826
3551
  }
@@ -2849,6 +3574,21 @@ function getOrCreateCtvSessionId() {
2849
3574
  writePersistentId(CTV_SESSION_STORAGE_KEY, sessionId);
2850
3575
  return sessionId;
2851
3576
  }
3577
+ function getOrCreateWebSessionId() {
3578
+ if (typeof window === "undefined") return void 0;
3579
+ try {
3580
+ var _window_sessionStorage;
3581
+ var existing = (_window_sessionStorage = window.sessionStorage) === null || _window_sessionStorage === void 0 ? void 0 : _window_sessionStorage.getItem(WEB_SESSION_STORAGE_KEY);
3582
+ if (existing && !isMacroPlaceholder(existing)) return existing;
3583
+ } catch (unused) {}
3584
+ var sessionId = inMemoryWebSessionId || createUuid();
3585
+ inMemoryWebSessionId = sessionId;
3586
+ try {
3587
+ var _window_sessionStorage1;
3588
+ (_window_sessionStorage1 = window.sessionStorage) === null || _window_sessionStorage1 === void 0 ? void 0 : _window_sessionStorage1.setItem(WEB_SESSION_STORAGE_KEY, sessionId);
3589
+ } catch (unused) {}
3590
+ return sessionId;
3591
+ }
2852
3592
  function readPersistentId(storageKey) {
2853
3593
  return readStoredString(storageKey) || readCookie(storageKey);
2854
3594
  }
@@ -3000,22 +3740,9 @@ function isZeroedAdId(value) {
3000
3740
  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
3001
3741
  }
3002
3742
  function readNativeBridgeSignals() {
3003
- if (typeof window === "undefined") {
3004
- return {};
3005
- }
3006
- var candidates = [
3007
- window.__STORMCLOUD_CTV_AD_INFO__,
3008
- window.__STORMCLOUD_CTV__,
3009
- window.stormcloudCtv,
3010
- window.AiryTV,
3011
- window.Android,
3012
- window.webOS,
3013
- window.tizen,
3014
- window.amazon
3015
- ].filter(Boolean);
3016
3743
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3017
3744
  try {
3018
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3745
+ for(var _iterator = getNativeBridgeSources()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3019
3746
  var source = _step.value;
3020
3747
  var contentUrl = readBridgeValue(source, [
3021
3748
  "contentUrl",
@@ -3090,6 +3817,21 @@ function readNativeBridgeSignals() {
3090
3817
  }
3091
3818
  return {};
3092
3819
  }
3820
+ function getNativeBridgeSources() {
3821
+ if (typeof window === "undefined") {
3822
+ return [];
3823
+ }
3824
+ return [
3825
+ window.__STORMCLOUD_CTV_AD_INFO__,
3826
+ window.__STORMCLOUD_CTV__,
3827
+ window.stormcloudCtv,
3828
+ window.AiryTV,
3829
+ window.Android,
3830
+ window.webOS,
3831
+ window.tizen,
3832
+ window.amazon
3833
+ ].filter(Boolean);
3834
+ }
3093
3835
  function readBridgeValue(source, keys) {
3094
3836
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3095
3837
  try {
@@ -3448,7 +4190,7 @@ function sha256Hex(input) {
3448
4190
  })();
3449
4191
  }
3450
4192
  function resolvePlayerIdentitySeed(clientInfo) {
3451
- var nativeDeviceId = resolveNativeDeviceId();
4193
+ var nativeDeviceId = resolveNativeDeviceId(clientInfo.isSmartTV);
3452
4194
  if (nativeDeviceId) {
3453
4195
  return "device:".concat(nativeDeviceId);
3454
4196
  }
@@ -4217,6 +4959,12 @@ function applyDeviceIdentityParams(params, ctx) {
4217
4959
  params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
4218
4960
  return;
4219
4961
  }
4962
+ if (!ctx.isCtv) {
4963
+ params.delete("rdid");
4964
+ params.delete("idtype");
4965
+ params.delete("is_lat");
4966
+ return;
4967
+ }
4220
4968
  var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
4221
4969
  var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
4222
4970
  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
@@ -4371,15 +5119,24 @@ function applyVastMacros(baseUrl, ctx) {
4371
5119
  if (ctx.podMaxAds != null) {
4372
5120
  params.set("pmad", String(Math.max(1, Math.round(ctx.podMaxAds))));
4373
5121
  }
4374
- if (!ctx.isCtv && ctx.pageUrl) {
4375
- params.set("url", ctx.pageUrl);
4376
- params.set("description_url", ctx.pageUrl);
4377
- }
4378
5122
  var existingUrl = params.get("url") || "";
4379
5123
  if (EXAMPLE_COM_URL.test(existingUrl)) {
4380
5124
  params.delete("url");
4381
5125
  params.delete("description_url");
4382
5126
  }
5127
+ if (!ctx.isCtv && ctx.pageUrl) {
5128
+ if (isMacroPlaceholder2(params.get("url"))) {
5129
+ params.set("url", ctx.pageUrl);
5130
+ }
5131
+ if (isMacroPlaceholder2(params.get("description_url"))) {
5132
+ params.set("description_url", params.get("url") || ctx.pageUrl);
5133
+ }
5134
+ }
5135
+ if (!ctx.isCtv) {
5136
+ params.delete("an");
5137
+ params.delete("msid");
5138
+ params.delete("sid");
5139
+ }
4383
5140
  if (ctx.adWillPlayMuted != null) {
4384
5141
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
4385
5142
  }
@@ -4413,6 +5170,9 @@ function applyVastMacros(baseUrl, ctx) {
4413
5170
  if (ctx.programTitle) {
4414
5171
  params.set("ct_ti", ctx.programTitle);
4415
5172
  }
5173
+ if (ctx.channelName) {
5174
+ params.set("ct_ch", ctx.channelName);
5175
+ }
4416
5176
  var staleKeys = [];
4417
5177
  params.forEach(function(value, key) {
4418
5178
  if (isMacroPlaceholder2(value)) {
@@ -4465,8 +5225,10 @@ function fetchConsentSignals() {
4465
5225
  tcfApi("addEventListener", 2, function(tcData, success) {
4466
5226
  if (settled) return;
4467
5227
  if (success && tcData && (tcData.eventStatus === "tcloaded" || tcData.eventStatus === "useractioncomplete")) {
5228
+ var _tcData_purpose_consents, _tcData_purpose;
4468
5229
  settled = true;
4469
5230
  signals.gdpr = tcData.gdprApplies ? "1" : "0";
5231
+ 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;
4470
5232
  if (typeof tcData.tcString === "string" && tcData.tcString) {
4471
5233
  signals.gdprConsent = tcData.tcString;
4472
5234
  }
@@ -5999,7 +6761,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
5999
6761
  pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
6000
6762
  adWillPlayMuted: adWillPlayMuted,
6001
6763
  adWillAutoPlay: !!this.config.autoplay,
6002
- sessionId: envSignals.sessionId,
6764
+ sessionId: envSignals.isCtv || this.consentSignals.storageAllowed !== false ? envSignals.sessionId : void 0,
6003
6765
  deviceId: envSignals.deviceId,
6004
6766
  deviceIdType: envSignals.deviceIdType,
6005
6767
  limitAdTracking: envSignals.limitAdTracking,
@@ -6007,6 +6769,8 @@ var AdConfigManager = /*#__PURE__*/ function() {
6007
6769
  adTest: this.config.adTest
6008
6770
  }, this.config.programTitle ? {
6009
6771
  programTitle: this.config.programTitle
6772
+ } : {}, this.config.channelName ? {
6773
+ channelName: this.config.channelName
6010
6774
  } : {}), {
6011
6775
  consent: this.consentSignals
6012
6776
  }));
@@ -7546,6 +8310,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7546
8310
  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 : "?"));
7547
8311
  }
7548
8312
  });
8313
+ adPlayer.on("ad_click", function() {
8314
+ _this.host.onAdClick();
8315
+ });
8316
+ adPlayer.on("ad_interaction", function(event) {
8317
+ if (event) _this.host.onAdInteraction(event);
8318
+ });
7549
8319
  adPlayer.on("all_ads_completed", function() {
7550
8320
  sendAdImpressionTracking(_this.host.config.licenseKey, {
7551
8321
  source: "hls",
@@ -9075,6 +9845,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9075
9845
  },
9076
9846
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
9077
9847
  return _this.generatePodVastUrl(base, breakDurationMs);
9848
+ },
9849
+ onAdClick: function onAdClick() {
9850
+ return _this.palNonce.sendAdClick();
9851
+ },
9852
+ onAdInteraction: function onAdInteraction(event) {
9853
+ return _this.palNonce.sendAdTouch(event);
9078
9854
  }
9079
9855
  }, this.timing, this.adConfig, this.cueManager, this.placeholder);
9080
9856
  }
@@ -9115,7 +9891,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9115
9891
  // ───────────────────────────────────────────────────────────────
9116
9892
  function load() {
9117
9893
  return _async_to_generator(function() {
9118
- var _this, _this_config_lowLatencyMode, error, palDescriptionUrl, continueLiveStreamDuringAds;
9894
+ var _this, error, palDescriptionUrl, continueLiveStreamDuringAds;
9119
9895
  return _ts_generator(this, function(_state) {
9120
9896
  switch(_state.label){
9121
9897
  case 0:
@@ -9151,19 +9927,25 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9151
9927
  4
9152
9928
  ];
9153
9929
  case 4:
9154
- palDescriptionUrl = this.adConfig.getPalDescriptionUrl();
9155
- this.palNonce.generateNonce(_object_spread({
9156
- videoWidth: this.video.offsetWidth || this.video.clientWidth || 640,
9157
- videoHeight: this.video.offsetHeight || this.video.clientHeight || 480,
9158
- adWillAutoPlay: !!this.config.autoplay,
9159
- adWillPlayMuted: true,
9160
- playerVolume: 0,
9161
- continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
9162
- }, palDescriptionUrl ? {
9163
- descriptionUrl: palDescriptionUrl
9164
- } : {})).catch(function() {});
9165
- fetchConsentSignals().then(function(signals) {
9930
+ palDescriptionUrl = this.config.ctvAdRequest ? this.adConfig.getPalDescriptionUrl() : void 0;
9931
+ fetchConsentSignals().catch(function() {
9932
+ return {};
9933
+ }).then(function(signals) {
9934
+ var _this_config_lowLatencyMode;
9166
9935
  _this.adConfig.consentSignals = signals;
9936
+ var muted = _this.video.muted;
9937
+ return _this.palNonce.generateNonce(_object_spread({
9938
+ videoWidth: _this.video.offsetWidth || _this.video.clientWidth || 640,
9939
+ videoHeight: _this.video.offsetHeight || _this.video.clientHeight || 480,
9940
+ adWillAutoPlay: !!_this.config.autoplay,
9941
+ adWillPlayMuted: muted,
9942
+ playerVolume: muted ? 0 : _this.video.volume,
9943
+ continuousPlayback: (_this_config_lowLatencyMode = _this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
9944
+ }, palDescriptionUrl ? {
9945
+ descriptionUrl: palDescriptionUrl
9946
+ } : {}, signals.storageAllowed != null ? {
9947
+ allowStorage: signals.storageAllowed
9948
+ } : {}));
9167
9949
  }).catch(function() {});
9168
9950
  this.adConfig.initializeTracking();
9169
9951
  if (!this.hlsEngine.shouldUseNativeHls(function() {
@@ -9885,7 +10667,7 @@ var CRITICAL_PROPS = [
9885
10667
  var CONTROLS_HIDE_DELAY = 3e3;
9886
10668
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
9887
10669
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9888
- 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, [
10670
+ 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, [
9889
10671
  "src",
9890
10672
  "autoplay",
9891
10673
  "muted",
@@ -9917,7 +10699,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9917
10699
  "vmapUrl",
9918
10700
  "minSegmentsBeforePlay",
9919
10701
  "ctvAdRequest",
9920
- "programTitle"
10702
+ "programTitle",
10703
+ "channelName"
9921
10704
  ]);
9922
10705
  var videoRef = (0, import_react.useRef)(null);
9923
10706
  var playerRef = (0, import_react.useRef)(null);
@@ -10109,6 +10892,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
10109
10892
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
10110
10893
  if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;
10111
10894
  if (programTitle !== void 0) cfg.programTitle = programTitle;
10895
+ if (channelName !== void 0) cfg.channelName = channelName;
10112
10896
  var player = new StormcloudVideoPlayer(cfg);
10113
10897
  playerRef.current = player;
10114
10898
  player.load().then(function() {