salsify-experiences-sdk
Version:
SDK to be used by commerce websites to implement product experiences.
68 lines (60 loc) • 2.54 kB
text/typescript
import { Logger } from './logger'
import Timeout from './timeout'
import EnhancedContentApi from '../enhancedContent'
export default class TimeOnPageTracker {
#logger: Logger
#ecApi?: EnhancedContentApi
#timeOnPage = 0 // The total time on page
#timeOnPageSessionStart = Date.now() // The current time on page session start time
#visibilitychangeHandler: () => void
#beforeunloadHandler: () => void
#timeout: Timeout
public constructor(logger: Logger, ecApi?: EnhancedContentApi) {
this.#logger = logger
this.#ecApi = ecApi
this.#visibilitychangeHandler = this.#visibilitychangeCallback.bind(this)
this.#beforeunloadHandler = this.sendEvent.bind(this)
this.#timeout = new Timeout()
}
public start(): void {
document.addEventListener('visibilitychange', this.#visibilitychangeHandler)
window.addEventListener('beforeunload', this.#beforeunloadHandler)
this.#timeout.start(this.sendEvent.bind(this))
}
public stop(): void {
document.removeEventListener('visibilitychange', this.#visibilitychangeHandler)
window.removeEventListener('beforeunload', this.#beforeunloadHandler)
this.#timeout.clear()
}
public restart(): void {
this.stop()
this.#timeOnPage = 0
this.#timeOnPageSessionStart = Date.now()
this.start()
}
public sendEvent(): void {
const currentTime = Date.now()
this.#timeOnPage += (currentTime - this.#timeOnPageSessionStart) / 1000
this.#timeOnPageSessionStart = currentTime
this.#logger.log('time_on_page', {
timeOnPage: this.#timeOnPage,
lastEcRenderConfig: this.#ecApi?.lastRenderConfig,
})
}
#visibilitychangeCallback(): void {
// document.visibilityState returns the current visibility state of the document.
// It returns these states as “hidden“, “visible”, and “prerender”.
// - hidden means the current tab is not in focus, either switched to another tab, minimized, or closed
// - visible means the current tab is in focus
// - prerender means the page has been loaded but the user has not viewed the page
if (document.visibilityState === 'visible') {
// If the document is change to visible, reset the session start time and continue the timeout
this.#timeOnPageSessionStart = Date.now()
} else {
// If the document is not visible, it means the user is swtiching to another tab or closing the tab
// Calculate the time on page and log it, also remove the timeout
this.sendEvent()
this.#timeout.clear()
}
}
}