@atlaskit/react-ufo 4.8.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/create-extra-search-page-interaction-payload/index.js +50 -0
  3. package/dist/cjs/create-payload/index.js +63 -0
  4. package/dist/cjs/create-payload/utils/get-vc-metrics.js +15 -12
  5. package/dist/cjs/interaction-metrics/index.js +15 -7
  6. package/dist/cjs/interaction-metrics-init/index.js +29 -2
  7. package/dist/cjs/vc/index.js +4 -3
  8. package/dist/cjs/vc/vc-observer-new/index.js +4 -3
  9. package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -8
  10. package/dist/cjs/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -1
  11. package/dist/cjs/vc/vc-observer-new/metric-calculator/utils/is-entry-smart-answers-in-search.js +27 -0
  12. package/dist/es2019/create-extra-search-page-interaction-payload/index.js +32 -0
  13. package/dist/es2019/create-payload/index.js +49 -0
  14. package/dist/es2019/create-payload/utils/get-vc-metrics.js +3 -2
  15. package/dist/es2019/interaction-metrics/index.js +15 -7
  16. package/dist/es2019/interaction-metrics-init/index.js +29 -2
  17. package/dist/es2019/vc/index.js +4 -2
  18. package/dist/es2019/vc/vc-observer-new/index.js +4 -2
  19. package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +6 -5
  20. package/dist/es2019/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -1
  21. package/dist/es2019/vc/vc-observer-new/metric-calculator/utils/is-entry-smart-answers-in-search.js +22 -0
  22. package/dist/esm/create-extra-search-page-interaction-payload/index.js +43 -0
  23. package/dist/esm/create-payload/index.js +62 -0
  24. package/dist/esm/create-payload/utils/get-vc-metrics.js +15 -12
  25. package/dist/esm/interaction-metrics/index.js +15 -7
  26. package/dist/esm/interaction-metrics-init/index.js +29 -2
  27. package/dist/esm/vc/index.js +4 -3
  28. package/dist/esm/vc/vc-observer-new/index.js +4 -3
  29. package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -8
  30. package/dist/esm/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -1
  31. package/dist/esm/vc/vc-observer-new/metric-calculator/utils/is-entry-smart-answers-in-search.js +21 -0
  32. package/dist/types/config/index.d.ts +7 -0
  33. package/dist/types/create-extra-search-page-interaction-payload/index.d.ts +3 -0
  34. package/dist/types/create-payload/index.d.ts +25434 -0
  35. package/dist/types/create-payload/utils/get-vc-metrics.d.ts +1 -1
  36. package/dist/types/vc/types.d.ts +1 -0
  37. package/dist/types/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +2 -2
  38. package/dist/types/vc/vc-observer-new/metric-calculator/fy25_03/index.d.ts +1 -1
  39. package/dist/types/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
  40. package/dist/types/vc/vc-observer-new/metric-calculator/utils/is-entry-smart-answers-in-search.d.ts +2 -0
  41. package/dist/types/vc/vc-observer-new/types.d.ts +1 -0
  42. package/dist/types-ts4.5/config/index.d.ts +7 -0
  43. package/dist/types-ts4.5/create-extra-search-page-interaction-payload/index.d.ts +3 -0
  44. package/dist/types-ts4.5/create-payload/index.d.ts +25434 -0
  45. package/dist/types-ts4.5/create-payload/utils/get-vc-metrics.d.ts +1 -1
  46. package/dist/types-ts4.5/vc/types.d.ts +1 -0
  47. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +2 -2
  48. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/fy25_03/index.d.ts +1 -1
  49. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
  50. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/utils/is-entry-smart-answers-in-search.d.ts +2 -0
  51. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -0
  52. package/package.json +4 -1
@@ -3,6 +3,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import coinflip from '../coinflip';
4
4
  import { getAwaitBM3TTIList, getCapabilityRate, getConfig, getExperimentalInteractionRate, getExtraInteractionRate, getFinishInteractionOnTransition, getInteractionTimeout, getPostInteractionRate, getReactHydrationStats } from '../config';
5
5
  import { experimentalVC, getExperimentalVCMetrics, onExperimentalInteractionComplete } from '../create-experimental-interaction-metrics-payload';
6
+ import { onSearchPageInteractionComplete } from '../create-extra-search-page-interaction-payload';
6
7
  import { sanitizeUfoName, stringifyLabelStackFully } from '../create-payload/common/utils';
7
8
  import { clearActiveTrace } from '../experience-trace-id-context';
8
9
  import { allFeatureFlagsAccessed, currentFeatureFlagsAccessed } from '../feature-flags-accessed';
@@ -759,16 +760,19 @@ export function tryComplete(interactionId, endTime) {
759
760
  if (noMoreActiveHolds && interactionExtraMetrics.finishedInteractionId !== interactionId) {
760
761
  // If it's not waiting for extra metrics to complete, finish the interaction as normal
761
762
  if (!activeSubmitted) {
762
- var _getConfig1, _getConfig1$extraInte;
763
+ var _getConfig1, _getConfig1$extraInte, _getConfig10, _getConfig10$extraSea, _getConfig11, _getConfig11$extraSea;
763
764
  finishInteraction(interactionId, interaction, endTime);
764
765
  if ((_getConfig1 = getConfig()) !== null && _getConfig1 !== void 0 && (_getConfig1$extraInte = _getConfig1.extraInteractionMetrics) !== null && _getConfig1$extraInte !== void 0 && _getConfig1$extraInte.enabled) {
765
766
  interactionExtraMetrics.updateFinishedInteractionId(interactionId);
766
767
  }
768
+ if ((_getConfig10 = getConfig()) !== null && _getConfig10 !== void 0 && (_getConfig10$extraSea = _getConfig10.extraSearchPageInteraction) !== null && _getConfig10$extraSea !== void 0 && _getConfig10$extraSea.enabled && interaction.ufoName === ((_getConfig11 = getConfig()) === null || _getConfig11 === void 0 ? void 0 : (_getConfig11$extraSea = _getConfig11.extraSearchPageInteraction) === null || _getConfig11$extraSea === void 0 ? void 0 : _getConfig11$extraSea.searchPageMetricName) && fg('react_ufo_unified_search_ignoring_sain_metric')) {
769
+ onSearchPageInteractionComplete(interactionId, interaction);
770
+ }
767
771
  activeSubmitted = true;
768
772
  }
769
773
  if (noMoreExpHolds) {
770
- var _getConfig10, _getConfig10$experime;
771
- if ((_getConfig10 = getConfig()) !== null && _getConfig10 !== void 0 && (_getConfig10$experime = _getConfig10.experimentalInteractionMetrics) !== null && _getConfig10$experime !== void 0 && _getConfig10$experime.enabled) {
774
+ var _getConfig12, _getConfig12$experime;
775
+ if ((_getConfig12 = getConfig()) !== null && _getConfig12 !== void 0 && (_getConfig12$experime = _getConfig12.experimentalInteractionMetrics) !== null && _getConfig12$experime !== void 0 && _getConfig12$experime.enabled) {
772
776
  onExperimentalInteractionComplete(interactionId, interaction, endTime);
773
777
  }
774
778
  postInteraction();
@@ -784,12 +788,16 @@ export function tryComplete(interactionId, endTime) {
784
788
  } else {
785
789
  if (noMoreActiveHolds) {
786
790
  if (!activeSubmitted) {
791
+ var _getConfig13, _getConfig13$extraSea, _getConfig14, _getConfig14$extraSea;
787
792
  finishInteraction(interactionId, interaction, endTime);
793
+ if ((_getConfig13 = getConfig()) !== null && _getConfig13 !== void 0 && (_getConfig13$extraSea = _getConfig13.extraSearchPageInteraction) !== null && _getConfig13$extraSea !== void 0 && _getConfig13$extraSea.enabled && interaction.ufoName === ((_getConfig14 = getConfig()) === null || _getConfig14 === void 0 ? void 0 : (_getConfig14$extraSea = _getConfig14.extraSearchPageInteraction) === null || _getConfig14$extraSea === void 0 ? void 0 : _getConfig14$extraSea.searchPageMetricName) && fg('react_ufo_unified_search_ignoring_sain_metric')) {
794
+ onSearchPageInteractionComplete(interactionId, interaction);
795
+ }
788
796
  activeSubmitted = true;
789
797
  }
790
798
  if (noMoreExpHolds) {
791
- var _getConfig11, _getConfig11$experime;
792
- if ((_getConfig11 = getConfig()) !== null && _getConfig11 !== void 0 && (_getConfig11$experime = _getConfig11.experimentalInteractionMetrics) !== null && _getConfig11$experime !== void 0 && _getConfig11$experime.enabled) {
799
+ var _getConfig15, _getConfig15$experime;
800
+ if ((_getConfig15 = getConfig()) !== null && _getConfig15 !== void 0 && (_getConfig15$experime = _getConfig15.experimentalInteractionMetrics) !== null && _getConfig15$experime !== void 0 && _getConfig15$experime.enabled) {
793
801
  onExperimentalInteractionComplete(interactionId, interaction, endTime);
794
802
  }
795
803
  postInteraction();
@@ -985,7 +993,7 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
985
993
  addHoldByID(interactionId, [], ufoName, ufoName, true);
986
994
  }
987
995
  if (type === 'transition' || type === 'page_load') {
988
- var _getConfig12, _getConfig12$postInte, _config$extraInteract;
996
+ var _getConfig16, _getConfig16$postInte, _config$extraInteract;
989
997
  // Use per-interaction VC observer if available, otherwise fall back to global
990
998
  const observer = vcObserver;
991
999
  if (observer) {
@@ -996,7 +1004,7 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
996
1004
  }
997
1005
  // Start post interaction observer for all if config is enabled
998
1006
  // in case ufoName is updated at later time
999
- if ((_getConfig12 = getConfig()) !== null && _getConfig12 !== void 0 && (_getConfig12$postInte = _getConfig12.postInteractionLog) !== null && _getConfig12$postInte !== void 0 && _getConfig12$postInte.enabled) {
1007
+ if ((_getConfig16 = getConfig()) !== null && _getConfig16 !== void 0 && (_getConfig16$postInte = _getConfig16.postInteractionLog) !== null && _getConfig16$postInte !== void 0 && _getConfig16$postInte.enabled) {
1000
1008
  postInteractionLog.startVCObserver({
1001
1009
  startTime
1002
1010
  });
@@ -2,6 +2,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
2
2
  import { startLighthouseObserver } from '../additional-payload';
3
3
  import { setUFOConfig } from '../config';
4
4
  import { experimentalVC, sinkExperimentalHandler } from '../create-experimental-interaction-metrics-payload';
5
+ import { sinkExtraSearchPageInteractionHandler } from '../create-extra-search-page-interaction-payload';
5
6
  import { setupHiddenTimingCapture } from '../hidden-timing';
6
7
  import { interactionExtraMetrics, postInteractionLog, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
7
8
  import { getPerformanceObserver } from '../interactions-performance-observer';
@@ -86,6 +87,26 @@ function sinkInteractionExtraMetrics(instance, createInteractionExtraLogPayload)
86
87
  });
87
88
  });
88
89
  }
90
+ function sinkExtraSearchPageInteraction(instance, payloadPackage) {
91
+ function sinkFn(interactionId, interaction) {
92
+ function onIdle() {
93
+ payloadPackage.createExtraSearchPageInteractionPayload(interactionId, interaction).then(payloads => {
94
+ // NOTE: This API is used by the UFO DevTool Chrome Extension and Criterion
95
+ const devToolObserver = globalThis.__ufo_devtool_onUfoPayload;
96
+ payloads === null || payloads === void 0 ? void 0 : payloads.forEach(payload => {
97
+ if (typeof devToolObserver === 'function') {
98
+ devToolObserver === null || devToolObserver === void 0 ? void 0 : devToolObserver(payload);
99
+ }
100
+ instance.sendOperationalEvent(payload);
101
+ });
102
+ }).catch(error => {
103
+ throw error;
104
+ });
105
+ }
106
+ scheduleIdleCallback(onIdle);
107
+ }
108
+ sinkExtraSearchPageInteractionHandler(sinkFn);
109
+ }
89
110
  export function init(analyticsWebClientAsync, config) {
90
111
  var _config$vc;
91
112
  if (initialized) {
@@ -129,7 +150,7 @@ export function init(analyticsWebClientAsync, config) {
129
150
  Promise.all([analyticsWebClientAsync, import( /* webpackChunkName: "create-payloads" */'../create-payload'), import( /* webpackChunkName: "create-post-interaction-log-payload" */'../create-post-interaction-log-payload'), import( /* webpackChunkName: "create-interaction-extra-metrics-payload" */'../create-interaction-extra-metrics-payload')]).then(([awc, payloadPackage, createPostInteractionLogPayloadPackage, createInteractionExtraMetricsPayloadPackage]) => {
130
151
  if (awc.getAnalyticsWebClientPromise) {
131
152
  awc.getAnalyticsWebClientPromise().then(client => {
132
- var _config$experimentalI2, _config$postInteracti, _config$extraInteract2;
153
+ var _config$experimentalI2, _config$postInteracti, _config$extraInteract2, _config$extraSearchPa;
133
154
  const instance = client.getInstance();
134
155
  sinkInteraction(instance, payloadPackage);
135
156
  if (config !== null && config !== void 0 && (_config$experimentalI2 = config.experimentalInteractionMetrics) !== null && _config$experimentalI2 !== void 0 && _config$experimentalI2.enabled) {
@@ -141,9 +162,12 @@ export function init(analyticsWebClientAsync, config) {
141
162
  if (config !== null && config !== void 0 && (_config$extraInteract2 = config.extraInteractionMetrics) !== null && _config$extraInteract2 !== void 0 && _config$extraInteract2.enabled && fg('platform_ufo_enable_ttai_with_3p')) {
142
163
  sinkInteractionExtraMetrics(instance, createInteractionExtraMetricsPayloadPackage.default);
143
164
  }
165
+ if (config !== null && config !== void 0 && (_config$extraSearchPa = config.extraSearchPageInteraction) !== null && _config$extraSearchPa !== void 0 && _config$extraSearchPa.enabled && fg('react_ufo_unified_search_ignoring_sain_metric')) {
166
+ sinkExtraSearchPageInteraction(instance, payloadPackage);
167
+ }
144
168
  });
145
169
  } else if (awc.sendOperationalEvent) {
146
- var _config$experimentalI3, _config$postInteracti2, _config$extraInteract3;
170
+ var _config$experimentalI3, _config$postInteracti2, _config$extraInteract3, _config$extraSearchPa2;
147
171
  sinkInteraction(awc, payloadPackage);
148
172
  if (config !== null && config !== void 0 && (_config$experimentalI3 = config.experimentalInteractionMetrics) !== null && _config$experimentalI3 !== void 0 && _config$experimentalI3.enabled) {
149
173
  sinkExperimentalInteractionMetrics(awc, payloadPackage);
@@ -154,6 +178,9 @@ export function init(analyticsWebClientAsync, config) {
154
178
  if (config !== null && config !== void 0 && (_config$extraInteract3 = config.extraInteractionMetrics) !== null && _config$extraInteract3 !== void 0 && _config$extraInteract3.enabled && fg('platform_ufo_enable_ttai_with_3p')) {
155
179
  sinkInteractionExtraMetrics(awc, createInteractionExtraMetricsPayloadPackage.default);
156
180
  }
181
+ if (config !== null && config !== void 0 && (_config$extraSearchPa2 = config.extraSearchPageInteraction) !== null && _config$extraSearchPa2 !== void 0 && _config$extraSearchPa2.enabled) {
182
+ sinkExtraSearchPageInteraction(awc, payloadPackage);
183
+ }
157
184
  }
158
185
  });
159
186
  }
@@ -95,7 +95,8 @@ export class VCObserverWrapper {
95
95
  var _this$oldVCObserver4, _this$newVCObserver3, _ref;
96
96
  const {
97
97
  experienceKey,
98
- include3p
98
+ include3p,
99
+ excludeSmartAnswersInSearch
99
100
  } = param;
100
101
  const v1v2Result = isVCRevisionEnabled('fy25.01', experienceKey) || isVCRevisionEnabled('fy25.02', experienceKey) ? await ((_this$oldVCObserver4 = this.oldVCObserver) === null || _this$oldVCObserver4 === void 0 ? void 0 : _this$oldVCObserver4.getVCResult(param)) : {};
101
102
  const v3Result = isVCRevisionEnabled('fy25.03', experienceKey) ? await ((_this$newVCObserver3 = this.newVCObserver) === null || _this$newVCObserver3 === void 0 ? void 0 : _this$newVCObserver3.getVCResult({
@@ -103,7 +104,8 @@ export class VCObserverWrapper {
103
104
  stop: param.stop,
104
105
  interactionId: param.interactionId,
105
106
  ssr: param.includeSSRInV3 ? param.ssr : undefined,
106
- include3p
107
+ include3p,
108
+ excludeSmartAnswersInSearch
107
109
  })) : [];
108
110
  if (!v3Result) {
109
111
  return v1v2Result !== null && v1v2Result !== void 0 ? v1v2Result : {};
@@ -196,7 +196,8 @@ export default class VCObserverNew {
196
196
  start,
197
197
  stop,
198
198
  interactionId,
199
- include3p
199
+ include3p,
200
+ excludeSmartAnswersInSearch
200
201
  } = param;
201
202
  const results = [];
202
203
  this.addStartEntry(start);
@@ -214,7 +215,8 @@ export default class VCObserverNew {
214
215
  stopTime: stop,
215
216
  interactionId,
216
217
  isPostInteraction: this.isPostInteraction,
217
- include3p
218
+ include3p,
219
+ excludeSmartAnswersInSearch
218
220
  });
219
221
  if (fy25_03) {
220
222
  results.push(fy25_03);
@@ -55,7 +55,7 @@ export default class AbstractVCCalculatorBase {
55
55
  }
56
56
  return labelStacks;
57
57
  }
58
- async calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionId, dirtyReason, allEntries, include3p) {
58
+ async calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionId, dirtyReason, allEntries, include3p, excludeSmartAnswersInSearch) {
59
59
  var _window, _window2, _window6, _window8;
60
60
  const percentiles = [25, 50, 75, 80, 85, 90, 95, 98, 99, 100];
61
61
  const viewportEntries = this.filterViewportEntries(filteredEntries);
@@ -175,7 +175,7 @@ export default class AbstractVCCalculatorBase {
175
175
  // Group ignored entries by timestamp
176
176
  const ignoredEntriesByTime = new Map();
177
177
  for (const entry of allEntries) {
178
- if ('rect' in entry.data && !this.isEntryIncluded(entry, include3p)) {
178
+ if ('rect' in entry.data && !this.isEntryIncluded(entry, include3p, excludeSmartAnswersInSearch)) {
179
179
  var _ignoredEntriesByTime, _viewportData$rect, _viewportData$previou;
180
180
  const viewportData = entry.data;
181
181
  const timestamp = Math.round(entry.time);
@@ -273,11 +273,12 @@ export default class AbstractVCCalculatorBase {
273
273
  orderedEntries,
274
274
  interactionId,
275
275
  isPostInteraction,
276
- include3p
276
+ include3p,
277
+ excludeSmartAnswersInSearch
277
278
  }) {
278
279
  var _vcDetails$90$t, _vcDetails$;
279
280
  const filteredEntries = orderedEntries.filter(entry => {
280
- return this.isEntryIncluded(entry, include3p);
281
+ return this.isEntryIncluded(entry, include3p, excludeSmartAnswersInSearch);
281
282
  });
282
283
  let isVCClean;
283
284
  let dirtyReason;
@@ -293,7 +294,7 @@ export default class AbstractVCCalculatorBase {
293
294
  abortTimestamp: getVCCleanStatusResult.abortTimestamp
294
295
  };
295
296
  }
296
- const vcDetails = await this.calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionId, dirtyReason, orderedEntries, include3p);
297
+ const vcDetails = await this.calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionId, dirtyReason, orderedEntries, include3p, excludeSmartAnswersInSearch);
297
298
  const result = {
298
299
  revision: this.revisionNo,
299
300
  clean: true,
@@ -1,5 +1,6 @@
1
1
  import { fg } from '@atlaskit/platform-feature-flags';
2
2
  import AbstractVCCalculatorBase from '../abstract-base-vc-calculator';
3
+ import { isEntrySmartAnswersInSearch } from '../utils/is-entry-smart-answers-in-search';
3
4
  import isViewportEntryData from '../utils/is-viewport-entry-data';
4
5
  const ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize'];
5
6
  const REVISION_NO = 'fy25.03';
@@ -33,10 +34,13 @@ export default class VCCalculator_FY25_03 extends AbstractVCCalculatorBase {
33
34
  constructor(revisionNo) {
34
35
  super(revisionNo !== null && revisionNo !== void 0 ? revisionNo : REVISION_NO);
35
36
  }
36
- isEntryIncluded(entry, include3p) {
37
+ isEntryIncluded(entry, include3p, excludeSmartAnswersInSearch) {
37
38
  if (!getConsideredEntryTypes(include3p).includes(entry.data.type)) {
38
39
  return false;
39
40
  }
41
+ if (excludeSmartAnswersInSearch && isEntrySmartAnswersInSearch(entry)) {
42
+ return false;
43
+ }
40
44
  if (entry.data.type === 'mutation:attribute') {
41
45
  const entryData = entry.data;
42
46
  const attributeName = entryData.attributeName;
@@ -0,0 +1,22 @@
1
+ import { getDocument } from '@atlaskit/browser-apis';
2
+ export function isEntrySmartAnswersInSearch(entry) {
3
+ const {
4
+ elementName
5
+ } = entry.data;
6
+ if (!elementName || elementName === 'START') {
7
+ return false;
8
+ }
9
+ const doc = getDocument();
10
+ if (!doc) {
11
+ return false;
12
+ }
13
+ const smartAnswersElement = doc.getElementById('search-page-smart-answers');
14
+ if (!smartAnswersElement) {
15
+ return false;
16
+ }
17
+ const entryDOMElement = doc.querySelector(elementName);
18
+ if (!entryDOMElement) {
19
+ return false;
20
+ }
21
+ return smartAnswersElement.contains(entryDOMElement);
22
+ }
@@ -0,0 +1,43 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ var interactionBuffer = [];
5
+ var bufferInteractionData = function bufferInteractionData(interactionId, data) {
6
+ interactionBuffer.push({
7
+ interactionId: interactionId,
8
+ data: data
9
+ });
10
+ };
11
+ function clearInteractionBuffer() {
12
+ interactionBuffer.length = 0;
13
+ }
14
+ function appendInteractionData(interactionId, data) {
15
+ bufferInteractionData(interactionId, data);
16
+ }
17
+ function installInteractionSink(handler) {
18
+ var _iterator = _createForOfIteratorHelper(interactionBuffer),
19
+ _step;
20
+ try {
21
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
22
+ var _step$value = _step.value,
23
+ _interactionId = _step$value.interactionId,
24
+ data = _step$value.data;
25
+ handler(_interactionId, data);
26
+ }
27
+ } catch (err) {
28
+ _iterator.e(err);
29
+ } finally {
30
+ _iterator.f();
31
+ }
32
+ clearInteractionBuffer();
33
+ bufferInteractionData = handler;
34
+ }
35
+ export function sinkExtraSearchPageInteractionHandler(sinkFn) {
36
+ installInteractionSink(sinkFn);
37
+ }
38
+ export function onSearchPageInteractionComplete(interactionId, data) {
39
+ if (data.ufoName) {
40
+ appendInteractionData(interactionId, data);
41
+ clearInteractionBuffer();
42
+ }
43
+ }
@@ -696,4 +696,66 @@ function _createExperimentalMetricsPayload() {
696
696
  }, _callee3);
697
697
  }));
698
698
  return _createExperimentalMetricsPayload.apply(this, arguments);
699
+ }
700
+ export function createExtraSearchPageInteractionPayload(_x0, _x1) {
701
+ return _createExtraSearchPageInteractionPayload.apply(this, arguments);
702
+ }
703
+ function _createExtraSearchPageInteractionPayload() {
704
+ _createExtraSearchPageInteractionPayload = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(interactionId, interaction) {
705
+ var SAIN_HOLD_NAMES, NAME_OVERRIDE, SEARCH_PAGE_SMART_ANSWERS_SEGMENT_LABEL, newInteractionId, newEnd, holdInfo, reactProfilerTimings, lastHold, isLastHoldSAIN, lastFilteredTime, filteredReactProfilerTimings, lastTiming, modifiedInteraction, payloads, vcMetrics, interactionMetricsPayload;
706
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
707
+ while (1) switch (_context4.prev = _context4.next) {
708
+ case 0:
709
+ SAIN_HOLD_NAMES = ['search-ai-dialog-visible-text-loading', 'search-ai-dialog-all-text-loading'];
710
+ NAME_OVERRIDE = 'search-page-ignoring-smart-answers';
711
+ SEARCH_PAGE_SMART_ANSWERS_SEGMENT_LABEL = 'search-page-smart-answers';
712
+ newInteractionId = "".concat(interactionId, "-ignoring-smart-answers"); // Calculate a new end time which excludes SAIN holds
713
+ holdInfo = interaction.holdInfo, reactProfilerTimings = interaction.reactProfilerTimings;
714
+ lastHold = holdInfo.at(-1);
715
+ isLastHoldSAIN = Boolean(lastHold && SAIN_HOLD_NAMES.includes(lastHold.name)); // A new end time is only calculated if the last hold is a SAIN hold
716
+ if (isLastHoldSAIN) {
717
+ lastFilteredTime = null;
718
+ filteredReactProfilerTimings = reactProfilerTimings.filter(function (timing) {
719
+ if (timing.commitTime === lastFilteredTime) {
720
+ return false;
721
+ }
722
+ var isTimingSmartAnswersInSearch = timing.labelStack.some(function (label) {
723
+ return label.name === SEARCH_PAGE_SMART_ANSWERS_SEGMENT_LABEL;
724
+ });
725
+ if (isTimingSmartAnswersInSearch) {
726
+ lastFilteredTime = timing.commitTime;
727
+ return false;
728
+ }
729
+ return true;
730
+ });
731
+ lastTiming = filteredReactProfilerTimings.at(-1);
732
+ if (lastTiming) {
733
+ newEnd = lastTiming.commitTime;
734
+ }
735
+ }
736
+ modifiedInteraction = _objectSpread(_objectSpread({}, interaction), {}, {
737
+ end: newEnd !== null && newEnd !== void 0 ? newEnd : interaction.end,
738
+ holdInfo: [],
739
+ knownSegments: [],
740
+ reactProfilerTimings: [],
741
+ ufoName: NAME_OVERRIDE
742
+ });
743
+ payloads = [];
744
+ _context4.next = 12;
745
+ return getVCMetrics(interaction, false, true);
746
+ case 12:
747
+ vcMetrics = _context4.sent;
748
+ _context4.next = 15;
749
+ return createInteractionMetricsPayload(modifiedInteraction, newInteractionId, undefined, undefined, vcMetrics);
750
+ case 15:
751
+ interactionMetricsPayload = _context4.sent;
752
+ payloads.push(interactionMetricsPayload);
753
+ return _context4.abrupt("return", payloads.filter(Boolean));
754
+ case 18:
755
+ case "end":
756
+ return _context4.stop();
757
+ }
758
+ }, _callee4);
759
+ }));
760
+ return _createExtraSearchPageInteractionPayload.apply(this, arguments);
699
761
  }
@@ -15,6 +15,7 @@ function _getVCMetrics() {
15
15
  _getVCMetrics = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(interaction) {
16
16
  var _config$vc, _config$vc$ssrWhiteli, _interaction$apdex, _config$vc2, _config$vc3, _result$ufoVcRev;
17
17
  var include3p,
18
+ excludeSmartAnswersInSearch,
18
19
  config,
19
20
  interactionStatus,
20
21
  pageVisibilityUpToTTAI,
@@ -32,29 +33,30 @@ function _getVCMetrics() {
32
33
  while (1) switch (_context.prev = _context.next) {
33
34
  case 0:
34
35
  include3p = _args.length > 1 && _args[1] !== undefined ? _args[1] : false;
36
+ excludeSmartAnswersInSearch = _args.length > 2 && _args[2] !== undefined ? _args[2] : false;
35
37
  config = getConfig();
36
38
  if (config !== null && config !== void 0 && (_config$vc = config.vc) !== null && _config$vc !== void 0 && _config$vc.enabled) {
37
- _context.next = 4;
39
+ _context.next = 5;
38
40
  break;
39
41
  }
40
42
  return _context.abrupt("return", {});
41
- case 4:
43
+ case 5:
42
44
  if (!(interaction.type !== 'page_load' && interaction.type !== 'transition' && interaction.type !== 'press')) {
43
- _context.next = 6;
45
+ _context.next = 7;
44
46
  break;
45
47
  }
46
48
  return _context.abrupt("return", {});
47
- case 6:
49
+ case 7:
48
50
  interactionStatus = getInteractionStatus(interaction);
49
51
  pageVisibilityUpToTTAI = getPageVisibilityUpToTTAI(interaction);
50
52
  shouldReportVCMetrics = interactionStatus.originalInteractionStatus === 'SUCCEEDED' && pageVisibilityUpToTTAI === 'visible'; // Use per-interaction VC observer if available, otherwise fall back to global
51
53
  observer = interaction.vcObserver;
52
54
  if (observer) {
53
- _context.next = 12;
55
+ _context.next = 13;
54
56
  break;
55
57
  }
56
58
  return _context.abrupt("return", {});
57
- case 12:
59
+ case 13:
58
60
  isSSREnabled = interaction.type === 'page_load' && ((config === null || config === void 0 ? void 0 : config.ssr) || (config === null || config === void 0 || (_config$vc$ssrWhiteli = config.vc.ssrWhitelist) === null || _config$vc$ssrWhiteli === void 0 ? void 0 : _config$vc$ssrWhiteli.includes(interaction.ufoName)));
59
61
  ssr = interaction.type === 'page_load' && isSSREnabled ? {
60
62
  ssr: getSSRDoneTimeValue(config)
@@ -62,7 +64,7 @@ function _getVCMetrics() {
62
64
  postInteractionLog.setVCObserverSSRConfig(ssr);
63
65
  tti = (_interaction$apdex = interaction.apdex) === null || _interaction$apdex === void 0 || (_interaction$apdex = _interaction$apdex[0]) === null || _interaction$apdex === void 0 ? void 0 : _interaction$apdex.stopTime;
64
66
  prefix = 'ufo';
65
- _context.next = 19;
67
+ _context.next = 20;
66
68
  return observer.getVCResult(_objectSpread(_objectSpread({
67
69
  start: interaction.start,
68
70
  stop: interaction.end,
@@ -75,9 +77,10 @@ function _getVCMetrics() {
75
77
  interactionId: interaction.id,
76
78
  includeSSRRatio: (_config$vc3 = config.vc) === null || _config$vc3 === void 0 ? void 0 : _config$vc3.includeSSRRatio
77
79
  }, ssr), {}, {
78
- include3p: include3p
80
+ include3p: include3p,
81
+ excludeSmartAnswersInSearch: excludeSmartAnswersInSearch
79
82
  }));
80
- case 19:
83
+ case 20:
81
84
  result = _context.sent;
82
85
  observer.stop(interaction.ufoName);
83
86
  if (!include3p) {
@@ -90,15 +93,15 @@ function _getVCMetrics() {
90
93
  return revision === mostRecentVCRevision;
91
94
  });
92
95
  if (!(!shouldReportVCMetrics || !(mostRecentVCRevisionPayload !== null && mostRecentVCRevisionPayload !== void 0 && mostRecentVCRevisionPayload.clean))) {
93
- _context.next = 26;
96
+ _context.next = 27;
94
97
  break;
95
98
  }
96
99
  return _context.abrupt("return", result);
97
- case 26:
100
+ case 27:
98
101
  return _context.abrupt("return", _objectSpread(_objectSpread({}, result), {}, {
99
102
  'metric:vc90': mostRecentVCRevisionPayload['metric:vc90']
100
103
  }));
101
- case 27:
104
+ case 28:
102
105
  case "end":
103
106
  return _context.stop();
104
107
  }
@@ -13,6 +13,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
13
13
  import coinflip from '../coinflip';
14
14
  import { getAwaitBM3TTIList, getCapabilityRate, getConfig, getExperimentalInteractionRate, getExtraInteractionRate, getFinishInteractionOnTransition, getInteractionTimeout, getPostInteractionRate, getReactHydrationStats } from '../config';
15
15
  import { experimentalVC, getExperimentalVCMetrics, onExperimentalInteractionComplete } from '../create-experimental-interaction-metrics-payload';
16
+ import { onSearchPageInteractionComplete } from '../create-extra-search-page-interaction-payload';
16
17
  import { sanitizeUfoName, stringifyLabelStackFully } from '../create-payload/common/utils';
17
18
  import { clearActiveTrace } from '../experience-trace-id-context';
18
19
  import { allFeatureFlagsAccessed, currentFeatureFlagsAccessed } from '../feature-flags-accessed';
@@ -835,16 +836,19 @@ export function tryComplete(interactionId, endTime) {
835
836
  if (noMoreActiveHolds && interactionExtraMetrics.finishedInteractionId !== interactionId) {
836
837
  // If it's not waiting for extra metrics to complete, finish the interaction as normal
837
838
  if (!activeSubmitted) {
838
- var _getConfig1;
839
+ var _getConfig1, _getConfig10, _getConfig11;
839
840
  finishInteraction(interactionId, interaction, endTime);
840
841
  if ((_getConfig1 = getConfig()) !== null && _getConfig1 !== void 0 && (_getConfig1 = _getConfig1.extraInteractionMetrics) !== null && _getConfig1 !== void 0 && _getConfig1.enabled) {
841
842
  interactionExtraMetrics.updateFinishedInteractionId(interactionId);
842
843
  }
844
+ if ((_getConfig10 = getConfig()) !== null && _getConfig10 !== void 0 && (_getConfig10 = _getConfig10.extraSearchPageInteraction) !== null && _getConfig10 !== void 0 && _getConfig10.enabled && interaction.ufoName === ((_getConfig11 = getConfig()) === null || _getConfig11 === void 0 || (_getConfig11 = _getConfig11.extraSearchPageInteraction) === null || _getConfig11 === void 0 ? void 0 : _getConfig11.searchPageMetricName) && fg('react_ufo_unified_search_ignoring_sain_metric')) {
845
+ onSearchPageInteractionComplete(interactionId, interaction);
846
+ }
843
847
  activeSubmitted = true;
844
848
  }
845
849
  if (noMoreExpHolds) {
846
- var _getConfig10;
847
- if ((_getConfig10 = getConfig()) !== null && _getConfig10 !== void 0 && (_getConfig10 = _getConfig10.experimentalInteractionMetrics) !== null && _getConfig10 !== void 0 && _getConfig10.enabled) {
850
+ var _getConfig12;
851
+ if ((_getConfig12 = getConfig()) !== null && _getConfig12 !== void 0 && (_getConfig12 = _getConfig12.experimentalInteractionMetrics) !== null && _getConfig12 !== void 0 && _getConfig12.enabled) {
848
852
  onExperimentalInteractionComplete(interactionId, interaction, endTime);
849
853
  }
850
854
  postInteraction();
@@ -859,12 +863,16 @@ export function tryComplete(interactionId, endTime) {
859
863
  } else {
860
864
  if (noMoreActiveHolds) {
861
865
  if (!activeSubmitted) {
866
+ var _getConfig13, _getConfig14;
862
867
  finishInteraction(interactionId, interaction, endTime);
868
+ if ((_getConfig13 = getConfig()) !== null && _getConfig13 !== void 0 && (_getConfig13 = _getConfig13.extraSearchPageInteraction) !== null && _getConfig13 !== void 0 && _getConfig13.enabled && interaction.ufoName === ((_getConfig14 = getConfig()) === null || _getConfig14 === void 0 || (_getConfig14 = _getConfig14.extraSearchPageInteraction) === null || _getConfig14 === void 0 ? void 0 : _getConfig14.searchPageMetricName) && fg('react_ufo_unified_search_ignoring_sain_metric')) {
869
+ onSearchPageInteractionComplete(interactionId, interaction);
870
+ }
863
871
  activeSubmitted = true;
864
872
  }
865
873
  if (noMoreExpHolds) {
866
- var _getConfig11;
867
- if ((_getConfig11 = getConfig()) !== null && _getConfig11 !== void 0 && (_getConfig11 = _getConfig11.experimentalInteractionMetrics) !== null && _getConfig11 !== void 0 && _getConfig11.enabled) {
874
+ var _getConfig15;
875
+ if ((_getConfig15 = getConfig()) !== null && _getConfig15 !== void 0 && (_getConfig15 = _getConfig15.experimentalInteractionMetrics) !== null && _getConfig15 !== void 0 && _getConfig15.enabled) {
868
876
  onExperimentalInteractionComplete(interactionId, interaction, endTime);
869
877
  }
870
878
  postInteraction();
@@ -1061,7 +1069,7 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
1061
1069
  addHoldByID(interactionId, [], ufoName, ufoName, true);
1062
1070
  }
1063
1071
  if (type === 'transition' || type === 'page_load') {
1064
- var _getConfig12, _config$extraInteract;
1072
+ var _getConfig16, _config$extraInteract;
1065
1073
  // Use per-interaction VC observer if available, otherwise fall back to global
1066
1074
  var observer = vcObserver;
1067
1075
  if (observer) {
@@ -1072,7 +1080,7 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
1072
1080
  }
1073
1081
  // Start post interaction observer for all if config is enabled
1074
1082
  // in case ufoName is updated at later time
1075
- if ((_getConfig12 = getConfig()) !== null && _getConfig12 !== void 0 && (_getConfig12 = _getConfig12.postInteractionLog) !== null && _getConfig12 !== void 0 && _getConfig12.enabled) {
1083
+ if ((_getConfig16 = getConfig()) !== null && _getConfig16 !== void 0 && (_getConfig16 = _getConfig16.postInteractionLog) !== null && _getConfig16 !== void 0 && _getConfig16.enabled) {
1076
1084
  postInteractionLog.startVCObserver({
1077
1085
  startTime: startTime
1078
1086
  });
@@ -5,6 +5,7 @@ import { fg } from '@atlaskit/platform-feature-flags';
5
5
  import { startLighthouseObserver } from '../additional-payload';
6
6
  import { setUFOConfig } from '../config';
7
7
  import { experimentalVC, sinkExperimentalHandler } from '../create-experimental-interaction-metrics-payload';
8
+ import { sinkExtraSearchPageInteractionHandler } from '../create-extra-search-page-interaction-payload';
8
9
  import { setupHiddenTimingCapture } from '../hidden-timing';
9
10
  import { interactionExtraMetrics, postInteractionLog, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
10
11
  import { getPerformanceObserver } from '../interactions-performance-observer';
@@ -101,6 +102,26 @@ function sinkInteractionExtraMetrics(instance, createInteractionExtraLogPayload)
101
102
  })));
102
103
  });
103
104
  }
105
+ function sinkExtraSearchPageInteraction(instance, payloadPackage) {
106
+ function sinkFn(interactionId, interaction) {
107
+ function onIdle() {
108
+ payloadPackage.createExtraSearchPageInteractionPayload(interactionId, interaction).then(function (payloads) {
109
+ // NOTE: This API is used by the UFO DevTool Chrome Extension and Criterion
110
+ var devToolObserver = globalThis.__ufo_devtool_onUfoPayload;
111
+ payloads === null || payloads === void 0 || payloads.forEach(function (payload) {
112
+ if (typeof devToolObserver === 'function') {
113
+ devToolObserver === null || devToolObserver === void 0 || devToolObserver(payload);
114
+ }
115
+ instance.sendOperationalEvent(payload);
116
+ });
117
+ }).catch(function (error) {
118
+ throw error;
119
+ });
120
+ }
121
+ scheduleIdleCallback(onIdle);
122
+ }
123
+ sinkExtraSearchPageInteractionHandler(sinkFn);
124
+ }
104
125
  export function init(analyticsWebClientAsync, config) {
105
126
  var _config$vc;
106
127
  if (initialized) {
@@ -149,7 +170,7 @@ export function init(analyticsWebClientAsync, config) {
149
170
  createInteractionExtraMetricsPayloadPackage = _ref3[3];
150
171
  if (awc.getAnalyticsWebClientPromise) {
151
172
  awc.getAnalyticsWebClientPromise().then(function (client) {
152
- var _config$experimentalI2, _config$postInteracti, _config$extraInteract2;
173
+ var _config$experimentalI2, _config$postInteracti, _config$extraInteract2, _config$extraSearchPa;
153
174
  var instance = client.getInstance();
154
175
  sinkInteraction(instance, payloadPackage);
155
176
  if (config !== null && config !== void 0 && (_config$experimentalI2 = config.experimentalInteractionMetrics) !== null && _config$experimentalI2 !== void 0 && _config$experimentalI2.enabled) {
@@ -161,9 +182,12 @@ export function init(analyticsWebClientAsync, config) {
161
182
  if (config !== null && config !== void 0 && (_config$extraInteract2 = config.extraInteractionMetrics) !== null && _config$extraInteract2 !== void 0 && _config$extraInteract2.enabled && fg('platform_ufo_enable_ttai_with_3p')) {
162
183
  sinkInteractionExtraMetrics(instance, createInteractionExtraMetricsPayloadPackage.default);
163
184
  }
185
+ if (config !== null && config !== void 0 && (_config$extraSearchPa = config.extraSearchPageInteraction) !== null && _config$extraSearchPa !== void 0 && _config$extraSearchPa.enabled && fg('react_ufo_unified_search_ignoring_sain_metric')) {
186
+ sinkExtraSearchPageInteraction(instance, payloadPackage);
187
+ }
164
188
  });
165
189
  } else if (awc.sendOperationalEvent) {
166
- var _config$experimentalI3, _config$postInteracti2, _config$extraInteract3;
190
+ var _config$experimentalI3, _config$postInteracti2, _config$extraInteract3, _config$extraSearchPa2;
167
191
  sinkInteraction(awc, payloadPackage);
168
192
  if (config !== null && config !== void 0 && (_config$experimentalI3 = config.experimentalInteractionMetrics) !== null && _config$experimentalI3 !== void 0 && _config$experimentalI3.enabled) {
169
193
  sinkExperimentalInteractionMetrics(awc, payloadPackage);
@@ -174,6 +198,9 @@ export function init(analyticsWebClientAsync, config) {
174
198
  if (config !== null && config !== void 0 && (_config$extraInteract3 = config.extraInteractionMetrics) !== null && _config$extraInteract3 !== void 0 && _config$extraInteract3.enabled && fg('platform_ufo_enable_ttai_with_3p')) {
175
199
  sinkInteractionExtraMetrics(awc, createInteractionExtraMetricsPayloadPackage.default);
176
200
  }
201
+ if (config !== null && config !== void 0 && (_config$extraSearchPa2 = config.extraSearchPageInteraction) !== null && _config$extraSearchPa2 !== void 0 && _config$extraSearchPa2.enabled) {
202
+ sinkExtraSearchPageInteraction(awc, payloadPackage);
203
+ }
177
204
  }
178
205
  });
179
206
  }
@@ -112,11 +112,11 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
112
112
  value: function () {
113
113
  var _getVCResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(param) {
114
114
  var _this$oldVCObserver4, _this$newVCObserver3, _ref2;
115
- var experienceKey, include3p, v1v2Result, v3Result;
115
+ var experienceKey, include3p, excludeSmartAnswersInSearch, v1v2Result, v3Result;
116
116
  return _regeneratorRuntime.wrap(function _callee$(_context) {
117
117
  while (1) switch (_context.prev = _context.next) {
118
118
  case 0:
119
- experienceKey = param.experienceKey, include3p = param.include3p;
119
+ experienceKey = param.experienceKey, include3p = param.include3p, excludeSmartAnswersInSearch = param.excludeSmartAnswersInSearch;
120
120
  if (!(isVCRevisionEnabled('fy25.01', experienceKey) || isVCRevisionEnabled('fy25.02', experienceKey))) {
121
121
  _context.next = 7;
122
122
  break;
@@ -141,7 +141,8 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
141
141
  stop: param.stop,
142
142
  interactionId: param.interactionId,
143
143
  ssr: param.includeSSRInV3 ? param.ssr : undefined,
144
- include3p: include3p
144
+ include3p: include3p,
145
+ excludeSmartAnswersInSearch: excludeSmartAnswersInSearch
145
146
  });
146
147
  case 12:
147
148
  _context.t1 = _context.sent;