import { useEffect, useRef } from 'react'; import { useAppSelector } from '@akinon/next/redux/hooks'; import type { RootState } from '@theme/redux/store'; import { pushAddShippingInfo, pushAddPaymentInfo, pushEventGA4 } from '@theme/utils/gtm'; import type { SectionId } from './use-section-state'; const SECTION_EVENT: Record = { contact: 'one_page_contact_complete', address: 'one_page_address_complete', shipping: 'one_page_shipping_complete', payment: 'one_page_payment_open' }; interface UseCheckoutFunnelGtmOptions { enabled?: boolean; } export const useCheckoutFunnelGtm = ( activeSection: SectionId, { enabled = true }: UseCheckoutFunnelGtmOptions = {} ) => { const preOrder = useAppSelector( (state: RootState) => state.checkout.preOrder ); const fired = useRef>(new Set()); useEffect(() => { if (!enabled) return; if (!preOrder?.basket?.basketitem_set) return; // GTM dataLayer may not be initialised (no GTM tag, ad blocker, etc.). // Any failure must NEVER crash the checkout flow — wrap in try/catch. try { const products = preOrder.basket.basketitem_set.map((item) => ({ ...item.product })); if (activeSection === 'shipping' && !fired.current.has('shipping')) { pushAddShippingInfo(products); fired.current.add('shipping'); } if (activeSection === 'payment' && !fired.current.has('payment')) { pushAddPaymentInfo(products, String(preOrder?.payment_option?.name)); fired.current.add('payment'); } pushEventGA4(SECTION_EVENT[activeSection], { section: activeSection, items_count: products.length }); } catch (error) { console.warn('Checkout funnel GTM error (suppressed):', error); } }, [activeSection, enabled, preOrder?.payment_option?.name]); // eslint-disable-line react-hooks/exhaustive-deps };