stormcloud-video-player 0.8.68 → 0.8.69

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 (37) hide show
  1. package/dist/stormcloud-vp.min.js +1 -1
  2. package/lib/Player.cjs +30 -8
  3. package/lib/Player.cjs.map +1 -1
  4. package/lib/Player.d.cts +2 -1
  5. package/lib/StormcloudPlayer.cjs +5615 -5101
  6. package/lib/StormcloudPlayer.cjs.map +1 -1
  7. package/lib/StormcloudPlayer.d.cts +1 -0
  8. package/lib/index.cjs +5688 -5117
  9. package/lib/index.cjs.map +1 -1
  10. package/lib/index.d.cts +2 -1
  11. package/lib/index.d.ts +81 -1
  12. package/lib/index.js +5663 -5119
  13. package/lib/index.js.map +1 -1
  14. package/lib/player/AdBreakOrchestrator.cjs +314 -113
  15. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  16. package/lib/player/AdBreakOrchestrator.d.cts +9 -3
  17. package/lib/player/FloorLadder.cjs +578 -0
  18. package/lib/player/FloorLadder.cjs.map +1 -0
  19. package/lib/player/FloorLadder.d.cts +74 -0
  20. package/lib/player/StormcloudVideoPlayer.cjs +5615 -5101
  21. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  22. package/lib/player/StormcloudVideoPlayer.d.cts +9 -1
  23. package/lib/players/HlsPlayer.cjs +5615 -5101
  24. package/lib/players/HlsPlayer.cjs.map +1 -1
  25. package/lib/players/index.cjs +5615 -5101
  26. package/lib/players/index.cjs.map +1 -1
  27. package/lib/props.cjs +30 -8
  28. package/lib/props.cjs.map +1 -1
  29. package/lib/props.d.cts +1 -0
  30. package/lib/types.d.cts +22 -1
  31. package/lib/ui/StormcloudVideoPlayer.cjs +5634 -5091
  32. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  33. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -0
  34. package/lib/utils/vastMacros.cjs +4 -0
  35. package/lib/utils/vastMacros.cjs.map +1 -1
  36. package/lib/utils/vastMacros.d.cts +2 -1
  37. package/package.json +1 -1
@@ -284,84 +284,6 @@ __export(AdBreakOrchestrator_exports, {
284
284
  }
285
285
  });
286
286
  module.exports = __toCommonJS(AdBreakOrchestrator_exports);
287
- // src/utils/trackingIngest.ts
288
- var DEFAULT_TRACKING_INGEST_CONFIG = {
289
- enabled: true,
290
- baseUrl: "https://player-analytics-ingest-api-760490581852.us-central1.run.app/api/adstorm/player-tracking"
291
- };
292
- var trackingIngestConfig = _object_spread({}, DEFAULT_TRACKING_INGEST_CONFIG);
293
- function isTrackingIngestEnabled() {
294
- return trackingIngestConfig.enabled === true;
295
- }
296
- function normalizeIngestBaseUrl(baseUrl) {
297
- return baseUrl.replace(/\/+$/, "");
298
- }
299
- function buildTrackingIngestUrl(channel) {
300
- var base = normalizeIngestBaseUrl(trackingIngestConfig.baseUrl);
301
- if (channel === "impressions") {
302
- return "".concat(base, "/impressions/ingest");
303
- }
304
- return "".concat(base, "/metrics/ingest");
305
- }
306
- function ingestPlayerTracking(licenseKey, channel, body) {
307
- return _async_to_generator(function() {
308
- var response, error;
309
- return _ts_generator(this, function(_state) {
310
- switch(_state.label){
311
- case 0:
312
- if (!isTrackingIngestEnabled() || !licenseKey) {
313
- return [
314
- 2,
315
- false
316
- ];
317
- }
318
- _state.label = 1;
319
- case 1:
320
- _state.trys.push([
321
- 1,
322
- 3,
323
- ,
324
- 4
325
- ]);
326
- return [
327
- 4,
328
- fetch(buildTrackingIngestUrl(channel), {
329
- method: "POST",
330
- headers: {
331
- "Content-Type": "application/json",
332
- Authorization: "License-Key ".concat(licenseKey)
333
- },
334
- body: JSON.stringify(body)
335
- })
336
- ];
337
- case 2:
338
- response = _state.sent();
339
- if (!response.ok) {
340
- console.warn("[StormcloudVideoPlayer] Tracking ingest failed (".concat(response.status, ") for ").concat(channel));
341
- return [
342
- 2,
343
- false
344
- ];
345
- }
346
- return [
347
- 2,
348
- true
349
- ];
350
- case 3:
351
- error = _state.sent();
352
- console.warn("[StormcloudVideoPlayer] Tracking ingest error for ".concat(channel, ":"), error);
353
- return [
354
- 2,
355
- false
356
- ];
357
- case 4:
358
- return [
359
- 2
360
- ];
361
- }
362
- });
363
- })();
364
- }
365
287
  // src/utils/vastEnvironmentSignals.ts
366
288
  var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
367
289
  var DEVICE_ID_STORAGE_KEYS = [
@@ -807,6 +729,225 @@ function normalizeBoolean(value) {
807
729
  }
808
730
  return void 0;
809
731
  }
732
+ // src/utils/vastMacros.ts
733
+ var GAM_AD_HOSTS = /* @__PURE__ */ new Set([
734
+ "pubads.g.doubleclick.net",
735
+ "securepubads.g.doubleclick.net"
736
+ ]);
737
+ function ensureVideoAdType(rawUrl) {
738
+ try {
739
+ var url = new URL(rawUrl);
740
+ if (!GAM_AD_HOSTS.has(url.hostname)) return rawUrl;
741
+ if (url.searchParams.has("ad_type")) return rawUrl;
742
+ url.searchParams.set("ad_type", "video");
743
+ return url.toString();
744
+ } catch (unused) {
745
+ return rawUrl;
746
+ }
747
+ }
748
+ // src/player/FloorLadder.ts
749
+ var DEFAULT_WEB_FLOOR_LADDER_CONFIG = Object.freeze({
750
+ enabled: false,
751
+ targetingKey: "airytv_web_floor",
752
+ minFloorCents: 25,
753
+ maxFloorCents: 300,
754
+ stepCents: 25,
755
+ selectedFloorCents: 25,
756
+ fallbackFloorCents: 25,
757
+ readyFloorCents: [],
758
+ mode: "fixed",
759
+ allowedPositions: [
760
+ "midroll"
761
+ ],
762
+ targetAdUnitPath: "/21821455290/airytvadx/airytv-web",
763
+ configurationVersion: "2026-09-29.1"
764
+ });
765
+ var DEFAULT_FLOOR_LADDER_BOUNDS = Object.freeze({
766
+ minCents: 25,
767
+ maxCents: 300,
768
+ stepCents: 25
769
+ });
770
+ function decodeQueryComponent(value) {
771
+ try {
772
+ return decodeURIComponent(value.replace(/\+/g, " "));
773
+ } catch (unused) {
774
+ return void 0;
775
+ }
776
+ }
777
+ function mergeCustParams(decoded, key, cents) {
778
+ var prefix = "".concat(key, "=");
779
+ var kept = decoded.split("&").filter(function(pair) {
780
+ return pair !== "" && pair !== key && pair.indexOf(prefix) !== 0;
781
+ });
782
+ kept.push("".concat(prefix).concat(cents));
783
+ return kept.join("&");
784
+ }
785
+ function applyFloorToVastUrl(url, floor) {
786
+ if (floor.status !== "armed" || floor.floorCents == null) {
787
+ return {
788
+ url: url,
789
+ applied: false,
790
+ reason: floor.reason
791
+ };
792
+ }
793
+ var parsed;
794
+ try {
795
+ parsed = new URL(url);
796
+ } catch (unused) {
797
+ return {
798
+ url: url,
799
+ applied: false,
800
+ reason: "invalid_url"
801
+ };
802
+ }
803
+ if (!GAM_AD_HOSTS.has(parsed.hostname)) {
804
+ return {
805
+ url: url,
806
+ applied: false,
807
+ reason: "not_gam_host"
808
+ };
809
+ }
810
+ if (parsed.searchParams.get("iu") !== floor.targetAdUnitPath) {
811
+ return {
812
+ url: url,
813
+ applied: false,
814
+ reason: "ad_unit_mismatch"
815
+ };
816
+ }
817
+ var hashIndex = url.indexOf("#");
818
+ var beforeHash = hashIndex === -1 ? url : url.slice(0, hashIndex);
819
+ var hash = hashIndex === -1 ? "" : url.slice(hashIndex);
820
+ var queryIndex = beforeHash.indexOf("?");
821
+ var base = beforeHash.slice(0, queryIndex);
822
+ var segments = beforeHash.slice(queryIndex + 1).split("&");
823
+ var existing = [];
824
+ var insertAt = -1;
825
+ var rest = [];
826
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
827
+ try {
828
+ for(var _iterator = segments[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
829
+ var segment = _step.value;
830
+ var eq = segment.indexOf("=");
831
+ var rawKey = eq === -1 ? segment : segment.slice(0, eq);
832
+ if (decodeQueryComponent(rawKey) === "cust_params") {
833
+ if (insertAt === -1) insertAt = rest.length;
834
+ var value = eq === -1 ? "" : decodeQueryComponent(segment.slice(eq + 1));
835
+ if (value === void 0) {
836
+ return {
837
+ url: url,
838
+ applied: false,
839
+ reason: "malformed_cust_params"
840
+ };
841
+ }
842
+ if (value) existing.push(value);
843
+ continue;
844
+ }
845
+ rest.push(segment);
846
+ }
847
+ } catch (err) {
848
+ _didIteratorError = true;
849
+ _iteratorError = err;
850
+ } finally{
851
+ try {
852
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
853
+ _iterator.return();
854
+ }
855
+ } finally{
856
+ if (_didIteratorError) {
857
+ throw _iteratorError;
858
+ }
859
+ }
860
+ }
861
+ if (insertAt === -1) insertAt = rest.length;
862
+ var merged = mergeCustParams(existing.join("&"), floor.targetingKey, floor.floorCents);
863
+ rest.splice(insertAt, 0, "cust_params=".concat(encodeURIComponent(merged)));
864
+ var query = rest.filter(function(segment) {
865
+ return segment !== "";
866
+ }).join("&");
867
+ return {
868
+ url: "".concat(base, "?").concat(query).concat(hash),
869
+ applied: true,
870
+ reason: void 0
871
+ };
872
+ }
873
+ // src/utils/trackingIngest.ts
874
+ var DEFAULT_TRACKING_INGEST_CONFIG = {
875
+ enabled: true,
876
+ baseUrl: "https://player-analytics-ingest-api-760490581852.us-central1.run.app/api/adstorm/player-tracking"
877
+ };
878
+ var trackingIngestConfig = _object_spread({}, DEFAULT_TRACKING_INGEST_CONFIG);
879
+ function isTrackingIngestEnabled() {
880
+ return trackingIngestConfig.enabled === true;
881
+ }
882
+ function normalizeIngestBaseUrl(baseUrl) {
883
+ return baseUrl.replace(/\/+$/, "");
884
+ }
885
+ function buildTrackingIngestUrl(channel) {
886
+ var base = normalizeIngestBaseUrl(trackingIngestConfig.baseUrl);
887
+ if (channel === "impressions") {
888
+ return "".concat(base, "/impressions/ingest");
889
+ }
890
+ return "".concat(base, "/metrics/ingest");
891
+ }
892
+ function ingestPlayerTracking(licenseKey, channel, body) {
893
+ return _async_to_generator(function() {
894
+ var response, error;
895
+ return _ts_generator(this, function(_state) {
896
+ switch(_state.label){
897
+ case 0:
898
+ if (!isTrackingIngestEnabled() || !licenseKey) {
899
+ return [
900
+ 2,
901
+ false
902
+ ];
903
+ }
904
+ _state.label = 1;
905
+ case 1:
906
+ _state.trys.push([
907
+ 1,
908
+ 3,
909
+ ,
910
+ 4
911
+ ]);
912
+ return [
913
+ 4,
914
+ fetch(buildTrackingIngestUrl(channel), {
915
+ method: "POST",
916
+ headers: {
917
+ "Content-Type": "application/json",
918
+ Authorization: "License-Key ".concat(licenseKey)
919
+ },
920
+ body: JSON.stringify(body)
921
+ })
922
+ ];
923
+ case 2:
924
+ response = _state.sent();
925
+ if (!response.ok) {
926
+ console.warn("[StormcloudVideoPlayer] Tracking ingest failed (".concat(response.status, ") for ").concat(channel));
927
+ return [
928
+ 2,
929
+ false
930
+ ];
931
+ }
932
+ return [
933
+ 2,
934
+ true
935
+ ];
936
+ case 3:
937
+ error = _state.sent();
938
+ console.warn("[StormcloudVideoPlayer] Tracking ingest error for ".concat(channel, ":"), error);
939
+ return [
940
+ 2,
941
+ false
942
+ ];
943
+ case 4:
944
+ return [
945
+ 2
946
+ ];
947
+ }
948
+ });
949
+ })();
950
+ }
810
951
  // src/utils/tracking.ts
811
952
  var cachedBrowserId = null;
812
953
  function buildAnalyticsContext(config) {
@@ -1288,22 +1429,6 @@ function sendHeartbeat(_0) {
1288
1429
  function getAdAudioVolume(adPlayer) {
1289
1430
  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();
1290
1431
  }
1291
- // src/utils/vastMacros.ts
1292
- var GAM_AD_HOSTS = /* @__PURE__ */ new Set([
1293
- "pubads.g.doubleclick.net",
1294
- "securepubads.g.doubleclick.net"
1295
- ]);
1296
- function ensureVideoAdType(rawUrl) {
1297
- try {
1298
- var url = new URL(rawUrl);
1299
- if (!GAM_AD_HOSTS.has(url.hostname)) return rawUrl;
1300
- if (url.searchParams.has("ad_type")) return rawUrl;
1301
- url.searchParams.set("ad_type", "video");
1302
- return url.toString();
1303
- } catch (unused) {
1304
- return rawUrl;
1305
- }
1306
- }
1307
1432
  // src/player/AdBreakOrchestrator.ts
1308
1433
  var REQUEST_FAILURE_STAGES = /* @__PURE__ */ new Set([
1309
1434
  "no_fill",
@@ -1612,13 +1737,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1612
1737
  },
1613
1738
  {
1614
1739
  key: "beginVmapBreak",
1615
- value: function beginVmapBreak(breakKey) {
1740
+ value: function beginVmapBreak(breakKey, position) {
1616
1741
  this.breakSource = "vmap";
1617
1742
  this.followUpBaseVastUrl = void 0;
1618
1743
  this.unusableResponsesInBreak = 0;
1619
1744
  this.timing.totalAdRequestsInBreak = 0;
1620
1745
  this.setSlotState("NEEDS_NEXT_AD", "vmap_break_start");
1621
- this.noteOpportunity("vmap", breakKey);
1746
+ this.noteOpportunity("vmap", breakKey, position);
1622
1747
  }
1623
1748
  },
1624
1749
  {
@@ -1673,7 +1798,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1673
1798
  if (this.timing.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
1674
1799
  this.timing.expectedAdBreakDurationMs = adBreakDurationMs;
1675
1800
  }
1676
- this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey);
1801
+ this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
1677
1802
  epoch = this.timing.adBreakEpoch;
1678
1803
  hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
1679
1804
  if (!(adBreakDurationMs == null && !hasPrefetchedUrl)) return [
@@ -1767,7 +1892,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1767
1892
  // ───────────────────────────────────────────────────────────────
1768
1893
  function startOptimizedPod(baseVastUrl, breakDurationMs) {
1769
1894
  return _async_to_generator(function() {
1770
- var podUrl, prefetched, epoch, generation, adPlayer, requestToken, _ref, _adPlayer_getPodAdCount, podCount, error;
1895
+ var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _adPlayer_getPodAdCount, podCount, error;
1771
1896
  return _ts_generator(this, function(_state) {
1772
1897
  switch(_state.label){
1773
1898
  case 0:
@@ -1791,9 +1916,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1791
1916
  adPlayer = this.host.getAdPlayer();
1792
1917
  requestToken = ++this.timing.adRequestTokenCounter;
1793
1918
  this.timing.activeAdRequestToken = requestToken;
1794
- this.currentVastUrl = podUrl;
1795
1919
  this.setSlotState("REQUESTING", "initial_pod");
1796
1920
  this.beginFunnelRequest(adPlayer, requestToken, "initial_pod");
1921
+ requestUrl = this.applyOpportunityFloor(podUrl);
1922
+ this.currentVastUrl = requestUrl;
1797
1923
  _state.label = 1;
1798
1924
  case 1:
1799
1925
  _state.trys.push([
@@ -1816,7 +1942,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1816
1942
  return [
1817
1943
  4,
1818
1944
  this.callController(function() {
1819
- return adPlayer.requestAds(podUrl);
1945
+ return adPlayer.requestAds(requestUrl);
1820
1946
  })
1821
1947
  ];
1822
1948
  case 3:
@@ -1848,7 +1974,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1848
1974
  }
1849
1975
  sendAdLoadedTracking(this.host.config.licenseKey, {
1850
1976
  source: "hls",
1851
- vastUrl: podUrl,
1977
+ vastUrl: requestUrl,
1852
1978
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1853
1979
  }, this.analyticsContext).catch(function() {});
1854
1980
  this.timing.startAdFailsafeTimer(requestToken);
@@ -2195,12 +2321,14 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2195
2321
  this.timing.failedVastUrls.add(vastTagUrl);
2196
2322
  }
2197
2323
  this.countFunnelStage("request_outcome:".concat(outcome));
2198
- this.logOrchestratorFunnel("request_outcome", {
2324
+ this.logOrchestratorFunnel("request_outcome", _object_spread({
2199
2325
  outcome: outcome,
2200
2326
  errorMessage: message,
2201
2327
  consecutiveFailures: this.timing.consecutiveFailures,
2202
- unusableResponsesInBreak: this.unusableResponsesInBreak
2203
- });
2328
+ unusableResponsesInBreak: this.unusableResponsesInBreak,
2329
+ vastAdCount: diag === null || diag === void 0 ? void 0 : diag.vastAdCount,
2330
+ impressionCount: diag === null || diag === void 0 ? void 0 : diag.impressionCount
2331
+ }, this.requestFloorFields(diag)));
2204
2332
  }
2205
2333
  },
2206
2334
  {
@@ -2239,6 +2367,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2239
2367
  break;
2240
2368
  case "impression_fired":
2241
2369
  diag.impressionFired = true;
2370
+ diag.impressionCount++;
2242
2371
  break;
2243
2372
  default:
2244
2373
  if (REQUEST_FAILURE_STAGES.has(payload.stage) && !diag.failureReason) {
@@ -2295,6 +2424,67 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2295
2424
  }
2296
2425
  }
2297
2426
  },
2427
+ {
2428
+ key: "opportunityFloorFields",
2429
+ value: function opportunityFloorFields() {
2430
+ var floor = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : this.opportunityFloor;
2431
+ if (!floor) return {};
2432
+ return {
2433
+ floorStatus: floor.status,
2434
+ floorCents: floor.floorCents,
2435
+ floorSource: floor.source,
2436
+ floorReason: floor.reason,
2437
+ floorSelector: floor.selector,
2438
+ floorConfigVersion: floor.configurationVersion,
2439
+ adPosition: floor.position
2440
+ };
2441
+ }
2442
+ },
2443
+ {
2444
+ key: "requestFloorFields",
2445
+ value: function requestFloorFields(diag) {
2446
+ if (!diag || diag.floorApplied === void 0) return {};
2447
+ return {
2448
+ floorApplied: diag.floorApplied,
2449
+ floorCents: diag.floorCents,
2450
+ floorSource: diag.floorSource,
2451
+ floorReason: diag.floorReason,
2452
+ floorConfigVersion: diag.floorConfigVersion
2453
+ };
2454
+ }
2455
+ },
2456
+ {
2457
+ key: "applyOpportunityFloor",
2458
+ value: function applyOpportunityFloor(url) {
2459
+ var floor = this.opportunityFloor;
2460
+ if (!floor) return url;
2461
+ var result = applyFloorToVastUrl(url, floor);
2462
+ var diag = this.currentRequestId != null ? this.requestDiagnostics.get(this.currentRequestId) : void 0;
2463
+ if (diag) {
2464
+ diag.floorApplied = result.applied;
2465
+ if (result.applied && floor.floorCents != null) diag.floorCents = floor.floorCents;
2466
+ diag.floorSource = result.applied ? floor.source : "none";
2467
+ if (result.reason) diag.floorReason = result.reason;
2468
+ diag.floorConfigVersion = floor.configurationVersion;
2469
+ }
2470
+ if (floor.status === "skipped" && floor.reason === "disabled") {
2471
+ this.countFunnelStage("floor_skipped:disabled");
2472
+ return result.url;
2473
+ }
2474
+ this.logOrchestratorFunnel(result.applied ? "floor_applied" : "floor_skipped", {
2475
+ reason: result.reason,
2476
+ floorCents: result.applied ? floor.floorCents : void 0,
2477
+ floorSource: result.applied ? floor.source : "none",
2478
+ floorSelector: floor.selector,
2479
+ floorConfigVersion: floor.configurationVersion,
2480
+ adPosition: floor.position
2481
+ });
2482
+ if (!result.applied && result.reason) {
2483
+ this.countFunnelStage("floor_skipped:".concat(result.reason));
2484
+ }
2485
+ return result.url;
2486
+ }
2487
+ },
2298
2488
  {
2299
2489
  key: "countFunnelStage",
2300
2490
  value: function countFunnelStage(stage) {
@@ -2317,7 +2507,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2317
2507
  },
2318
2508
  {
2319
2509
  key: "noteOpportunity",
2320
- value: function noteOpportunity(source, breakKey) {
2510
+ value: function noteOpportunity(source, breakKey, position) {
2321
2511
  if (breakKey && breakKey === this.opportunityBreakKey && this.opportunityEpoch === this.timing.adBreakEpoch) {
2322
2512
  this.logOrchestratorFunnel("duplicate_break_start", {
2323
2513
  source: source,
@@ -2327,11 +2517,16 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2327
2517
  }
2328
2518
  this.opportunityBreakKey = breakKey;
2329
2519
  this.opportunityEpoch = this.timing.adBreakEpoch;
2330
- this.logOrchestratorFunnel("opportunity_created", {
2520
+ try {
2521
+ this.opportunityFloor = this.host.getFloorSnapshot(position);
2522
+ } catch (unused) {
2523
+ this.opportunityFloor = void 0;
2524
+ }
2525
+ this.logOrchestratorFunnel("opportunity_created", _object_spread({
2331
2526
  source: source,
2332
2527
  breakKey: breakKey,
2333
2528
  expectedDurationMs: this.timing.expectedAdBreakDurationMs
2334
- });
2529
+ }, this.opportunityFloorFields()));
2335
2530
  }
2336
2531
  },
2337
2532
  {
@@ -2358,6 +2553,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2358
2553
  supportedMediaCount: 0,
2359
2554
  playStarted: false,
2360
2555
  impressionFired: false,
2556
+ impressionCount: 0,
2361
2557
  startedAt: Date.now()
2362
2558
  });
2363
2559
  (_adPlayer_setFunnelContext = adPlayer.setFunnelContext) === null || _adPlayer_setFunnelContext === void 0 ? void 0 : _adPlayer_setFunnelContext.call(adPlayer, {
@@ -2442,7 +2638,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2442
2638
  value: function playSingleAd(vastTagUrl) {
2443
2639
  var trigger = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "vmap";
2444
2640
  return _async_to_generator(function() {
2445
- var epoch, generation, requestToken, ap, requestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
2641
+ var epoch, generation, requestToken, ap, budgetedUrl, requestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
2446
2642
  return _ts_generator(this, function(_state) {
2447
2643
  switch(_state.label){
2448
2644
  case 0:
@@ -2480,10 +2676,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2480
2676
  requestToken = ++this.timing.adRequestTokenCounter;
2481
2677
  this.timing.activeAdRequestToken = requestToken;
2482
2678
  ap = this.host.getAdPlayer();
2483
- requestUrl = this.withCurrentPodBudget(vastTagUrl);
2484
- this.currentVastUrl = requestUrl;
2679
+ budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
2485
2680
  this.setSlotState("REQUESTING", trigger);
2486
2681
  this.beginFunnelRequest(ap, requestToken, trigger);
2682
+ requestUrl = this.applyOpportunityFloor(budgetedUrl);
2683
+ this.currentVastUrl = requestUrl;
2487
2684
  _state.label = 1;
2488
2685
  case 1:
2489
2686
  _state.trys.push([
@@ -2616,10 +2813,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2616
2813
  endReason: endReason
2617
2814
  });
2618
2815
  }
2619
- console.log("[AdBreak][FUNNEL] Break summary", {
2816
+ console.log("[AdBreak][FUNNEL] Break summary", _object_spread_props(_object_spread({
2620
2817
  breakId: breakId,
2621
2818
  endReason: endReason,
2622
- opportunities: count("opportunity_created"),
2819
+ opportunities: count("opportunity_created")
2820
+ }, this.opportunityFloorFields()), {
2821
+ floorAppliedRequests: count("floor_applied"),
2822
+ floorSkippedRequests: count("floor_skipped") + count("floor_skipped:disabled"),
2623
2823
  vastUrlsGenerated: count("vast_url_generated"),
2624
2824
  requests: requests,
2625
2825
  requestRetries: requestRetries,
@@ -2671,7 +2871,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2671
2871
  visibilityHidden: count("while_hidden"),
2672
2872
  playbackFailures: count("play_failed") + count("media_error") + count("hls_fatal") + count("stall") + count("decode_failure") + count("media_unsupported"),
2673
2873
  stages: funnel
2674
- });
2874
+ }));
2675
2875
  }
2676
2876
  },
2677
2877
  {
@@ -2722,6 +2922,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
2722
2922
  this.unusableResponsesInBreak = 0;
2723
2923
  adPlayer.stop().catch(function() {});
2724
2924
  if (!alreadyEnded) this.logBreakFunnel(reason);
2925
+ this.opportunityFloor = void 0;
2725
2926
  this.setSlotState("IDLE", "break_complete");
2726
2927
  var restoredMuted = this.host.getAdPlayer().getOriginalMutedState();
2727
2928
  var restoredVolume = this.host.getAdPlayer().getOriginalVolume();