import {useCallback, useEffect, useRef} from 'react' import {useHandleAction} from './useHandleAction' import {useShopActions} from './useShopActions' export interface UseContentImpressionParams { /** * The public ID of the content to report impressions for */ publicId: string /** * Whether to skip reporting impressions */ skip?: boolean } export interface UseContentImpressionReturns { /** * Ref to attach to the content element for visibility tracking. * When the element becomes visible, an impression will be reported. */ ref: {current: HTMLDivElement | null} } export function useContentImpression({ publicId, skip = false, }: UseContentImpressionParams): UseContentImpressionReturns { const {reportContentImpression} = useShopActions() const handleAction = useHandleAction(reportContentImpression) const ref = useRef(null) const hasReportedRef = useRef(false) const reportImpression = useCallback(() => { if (hasReportedRef.current || skip || !publicId) { return } hasReportedRef.current = true handleAction({publicId, pageValue: window.location.pathname}) }, [handleAction, publicId, skip]) useEffect(() => { hasReportedRef.current = false }, [publicId]) useEffect(() => { if (skip || !ref.current) { return } const element = ref.current const observer = new IntersectionObserver( entries => { const [entry] = entries if (entry?.isIntersecting) { reportImpression() observer.disconnect() } }, { threshold: 0.5, } ) observer.observe(element) return () => { observer.disconnect() } }, [reportImpression, skip]) return {ref} }