• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yext / answers-search-ui / 25056892734

28 Apr 2026 01:51PM UTC coverage: 61.914% (+0.09%) from 61.826%
25056892734

Pull #1989

github

web-flow
Merge eda7070fa into e1bc6bfc0
Pull Request #1989: v2.0.0

2050 of 3451 branches covered (59.4%)

Branch coverage included in aggregate %.

12 of 18 new or added lines in 5 files covered. (66.67%)

17 existing lines in 3 files now uncovered.

3495 of 5505 relevant lines covered (63.49%)

26.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

18.37
/src/core/analytics/visibilityanalyticshandler.js
1
import { isIE } from '../utils/useragent';
2
import AnalyticsEvent from '../analytics/analyticsevent';
3
import StorageKeys from '../storage/storagekeys';
4

5
const RESULTS_VISIBILITY_EVENT = {
1✔
6
  HIDDEN: 'RESULTS_HIDDEN',
7
  UNHIDDEN: 'RESULTS_UNHIDDEN'
8
};
9

10
/**
11
 * Manages the document's visibility status and handles any visibility related analytics events.
12
 */
13
export default class VisibilityAnalyticsHandler {
14
  constructor (analyticsReporterService, verticalKey) {
15
    this._previousResultsVisibilityEvent = undefined;
7✔
16
    this._analyticsReporterService = analyticsReporterService;
7✔
17
    this._verticalKey = verticalKey;
7✔
18
  }
19

20
  /**
21
   * Initialize visibility change event listener(s) to send analytics events
22
   * when a result page have become visible or have been hidden.
23
   *
24
   * @param {Storage} storage - a container around application state
25
   */
26
  initVisibilityChangeListeners (storage) {
27
    /**
28
     * Safari desktop listener and IE11 listeners fire visibility change event twice when switch
29
     * to new tab and then close browser. Variable "_previousResultsVisibilityEvent" is used to ensure
30
     * RESULTS_HIDDEN analytics event does not get send again if the page is already hidden.
31
     */
32
    document.addEventListener('visibilitychange', () => {
7✔
33
      if (this._resultsVisibilityChangeToHidden()) {
×
34
        this._previousResultsVisibilityEvent = RESULTS_VISIBILITY_EVENT.HIDDEN;
×
35
        this._reportVisibilityChangeEvent(RESULTS_VISIBILITY_EVENT.HIDDEN);
×
36
      } else if (this._resultsVisibilityChangeToVisible()) {
×
37
        this._previousResultsVisibilityEvent = RESULTS_VISIBILITY_EVENT.UNHIDDEN;
×
38
        this._reportVisibilityChangeEvent(RESULTS_VISIBILITY_EVENT.UNHIDDEN);
×
39
      }
40
    });
41

42
    /**
43
     * VisibilityChange API does not register when page is terminated (close tab/browser) in IE11.
44
     * Unload event is used to capture those RESULTS_HIDDEN scenarios.
45
     */
46
    if (isIE()) {
7!
47
      window.addEventListener('unload', () => {
×
48
        if (this._previousResultsVisibilityEvent !== RESULTS_VISIBILITY_EVENT.HIDDEN) {
×
49
          this._reportVisibilityChangeEvent(RESULTS_VISIBILITY_EVENT.HIDDEN);
×
50
        }
51
      });
52
    }
53

54
    /**
55
     * Page history updates caused by pushState() or replaceState(), such as when a search is performed,
56
     * will not trigger a complete page load so the document's visibility state will not change. Use
57
     * popstate event and storage listener on QUERY_ID to report result visibility change events for
58
     * back/forward page navigation of the same answers page.
59
     */
60
    window.addEventListener('popstate', () => {
7✔
61
      const poppedStateQueryId = storage.get(StorageKeys.HISTORY_POP_STATE)?.get('pop-state-queryId');
×
62
      const storageQueryId = this._analyticsReporterService.getQueryId();
×
63
      this._analyticsReporterService.setQueryId(poppedStateQueryId);
×
64
      this._previousResultsVisibilityEvent = RESULTS_VISIBILITY_EVENT.HIDDEN;
×
65
      this._reportVisibilityChangeEvent(RESULTS_VISIBILITY_EVENT.HIDDEN);
×
66
      this._analyticsReporterService.setQueryId(storageQueryId);
×
67
    });
68

69
    storage.registerListener({
7✔
70
      eventType: 'update',
71
      storageKey: StorageKeys.QUERY_ID,
72
      callback: id => {
73
        if (this._resultsVisibilityChangeToVisible()) {
×
74
          this._previousResultsVisibilityEvent = RESULTS_VISIBILITY_EVENT.UNHIDDEN;
×
75
          this._reportVisibilityChangeEvent(RESULTS_VISIBILITY_EVENT.UNHIDDEN);
×
76
        }
77
      }
78
    });
79
  }
80

81
  /**
82
   * Returns true if results page was previously reported as unhidden and the page is now hidden.
83
   *
84
   * @returns {boolean}
85
   */
86
  _resultsVisibilityChangeToHidden () {
87
    return document.visibilityState === 'hidden' && this._previousResultsVisibilityEvent !== RESULTS_VISIBILITY_EVENT.HIDDEN;
×
88
  }
89

90
  /**
91
   * Returns true if results page was previously reported as hidden and the page is now visible.
92
   *
93
   * @returns {boolean}
94
   */
95
  _resultsVisibilityChangeToVisible () {
96
    return document.visibilityState === 'visible' && this._previousResultsVisibilityEvent !== RESULTS_VISIBILITY_EVENT.UNHIDDEN;
×
97
  }
98

99
  /**
100
   * Send visibility change related analytics event.
101
   *
102
   * @param {string} eventName - the name of the analytics event to report
103
   */
104
  _reportVisibilityChangeEvent (eventName) {
105
    const queryId = this._analyticsReporterService.getQueryId();
×
106
    if (!queryId) {
×
107
      return;
×
108
    }
NEW
109
    const event = new AnalyticsEvent(eventName);
×
110
    this._analyticsReporterService.report(event);
×
111
  }
112
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc