{"version":3,"sources":["../../src/hooks/use-web-analytics.ts"],"sourcesContent":["import { throttle } from '@shware/utils';\nimport { useEffect, useRef } from 'react';\nimport { keys } from '../constants/storage';\nimport { config } from '../setup/index';\nimport { session } from '../setup/session';\nimport { sendBeacon, track } from '../track/index';\nimport { usePrevious } from './use-previous';\n\nfunction sendFirstVisit(pathname: string) {\n  if (config.storage.getItem(keys.first_visit_time)) return;\n  track('first_visit', {\n    page_path: pathname,\n    page_title: document.title,\n    page_referrer: document.referrer,\n    page_location: window.location.href,\n  });\n  config.storage.setItem(keys.first_visit_time, new Date().toISOString());\n}\n\nfunction sendUserEngagement(trigger: 'pagehide' | 'visibilitychange') {\n  const engagement_time_msec = session.flush();\n  if (engagement_time_msec <= 0) return;\n  sendBeacon('user_engagement', { engagement_time_msec, trigger });\n}\n\nfunction sendScroll() {\n  const engagement_time_msec = session.flush();\n  if (engagement_time_msec <= 0) return;\n  track('scroll', { engagement_time_msec });\n}\n\nfunction getScrollPercent() {\n  const scrollTop = window.scrollY || document.documentElement.scrollTop;\n  const windowHeight = window.innerHeight;\n  const docHeight = document.documentElement.scrollHeight;\n  if (docHeight === 0) return 0;\n  return ((scrollTop + windowHeight) * 100) / docHeight;\n}\n\nfunction onPageHide() {\n  session.pagehide();\n  sendUserEngagement('pagehide');\n}\n\nfunction onVisibilityChange() {\n  session.visibilitychange(document.visibilityState);\n  if (document.visibilityState === 'hidden') {\n    sendUserEngagement('visibilitychange');\n  }\n}\n\n/**\n * 1. send session_start event when the page is loaded\n * 2. send scroll event when the user scrolls more than 90% of the page\n * 3. send user_engagement event when the page is hidden or the user is not focused\n */\nexport function useWebAnalytics(pathname: string) {\n  const prevPathname = usePrevious(pathname);\n\n  // reset state when the pathname changes and send scroll when the user navigates to a new page\n  const hasSendScroll = useRef(false);\n  useEffect(() => {\n    hasSendScroll.current = false;\n  }, [pathname]);\n\n  useEffect(() => {\n    sendFirstVisit(pathname);\n    track('session_start', undefined);\n\n    const onScroll = throttle(() => {\n      session.updateAccumulator();\n      if (hasSendScroll.current) return;\n      // only send scroll when the user has scrolled more than 90% of the page\n      if (getScrollPercent() < 90) return;\n      hasSendScroll.current = true;\n      sendScroll();\n    }, 500);\n\n    const checkpointEvents = ['mousedown', 'keydown', 'touchstart'];\n    const checkpoint = throttle(session.updateAccumulator, 1000);\n\n    window.addEventListener('focus', session.focus);\n    window.addEventListener('blur', session.blur);\n    window.addEventListener('scroll', onScroll, { passive: true });\n    window.addEventListener('pageshow', session.pageshow);\n    window.addEventListener('pagehide', onPageHide);\n    document.addEventListener('visibilitychange', onVisibilityChange);\n\n    // save checkpoint\n    checkpointEvents.forEach((e) => {\n      window.addEventListener(e, checkpoint, { passive: true, capture: true });\n    });\n\n    return () => {\n      window.removeEventListener('focus', session.focus);\n      window.removeEventListener('blur', session.blur);\n      window.removeEventListener('scroll', onScroll);\n      window.removeEventListener('pageshow', session.pageshow);\n      window.removeEventListener('pagehide', onPageHide);\n      document.removeEventListener('visibilitychange', onVisibilityChange);\n      checkpointEvents.forEach((e) => window.removeEventListener(e, checkpoint));\n\n      onScroll.cancel();\n      checkpoint.cancel();\n    };\n  }, []);\n\n  useEffect(() => {\n    track('page_view', {\n      page_path: pathname,\n      page_title: document.title,\n      page_referrer: document.referrer,\n      page_location: window.location.href,\n      previous_page_path: prevPathname ?? undefined,\n      engagement_time_msec: prevPathname ? session.flush() : undefined,\n    });\n  }, [pathname]);\n}\n"],"mappings":"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","names":[]}