33import { useEffect } from "react" ;
44import { umamiTrackEvent } from "@/lib/umami-analytics-track-event" ;
55import { showRandomCTAToast } from "../components/cta-toasts" ;
6+ import { useCTAToast } from "../contexts/cta-toast-context" ;
67import dayjs from "dayjs" ;
78import duration from "dayjs/plugin/duration" ;
89
910dayjs . extend ( duration ) ;
1011
11- const STORAGE_KEY = "EASY_INVOICE_CTA_LAST_SHOWN_AT" ;
12+ export const CTA_TOAST_LAST_SHOWN_STORAGE_KEY =
13+ "EASY_INVOICE_CTA_LAST_SHOWN_AT" ;
1214const COOLDOWN_DAYS = 7 ;
13- const MIN_TIME_ON_PAGE = 15_000 ; // in milliseconds
14- const IDLE_TIME = 5_000 ; // in milliseconds
15+ const MIN_TIME_ON_PAGE = 10_000 ; // in ms
16+ const IDLE_TIME = 7_000 ; // in ms
1517
1618/**
1719 * This hook is used to show a CTA toast after a certain number of interactions with the page.
1820 *
19- * - User stays on page 10s (MIN_TIME_ON_PAGE) → we consider them “ present” .
21+ * - User stays on page Xs (MIN_TIME_ON_PAGE) → we consider them " present" .
2022 * - Any real interaction (type, click) → we mark them engaged.
2123 * - Once they stop interacting for X seconds (IDLE_TIME) → toast appears.
2224 */
2325export function useShowRandomCTAToast ( ) {
26+ const { isToastShownInSession, markToastAsShown } = useCTAToast ( ) ;
27+
2428 useEffect ( ( ) => {
25- const last = localStorage . getItem ( STORAGE_KEY ) ;
29+ // Skip if a CTA toast was already shown in this session (e.g., from PDF download)
30+ if ( isToastShownInSession ) {
31+ umamiTrackEvent ( "cta_toast_skipped_session" ) ;
32+ return ;
33+ }
34+ const last = localStorage . getItem ( CTA_TOAST_LAST_SHOWN_STORAGE_KEY ) ;
2635
2736 // Check if the last time the CTA toast was shown was less than 7 days ago
2837 // Parse and validate the stored timestamp
@@ -31,15 +40,16 @@ export function useShowRandomCTAToast() {
3140
3241 // If invalid timestamp, clear it from storage and treat as not in cooldown
3342 if ( last && ! isValidTimestamp ) {
34- localStorage . removeItem ( STORAGE_KEY ) ;
43+ localStorage . removeItem ( CTA_TOAST_LAST_SHOWN_STORAGE_KEY ) ;
3544 }
3645
3746 const isWithinCooldownPeriod =
3847 isValidTimestamp &&
3948 dayjs ( ) . diff ( dayjs ( parsedLast ) ) <
4049 dayjs . duration ( COOLDOWN_DAYS , "day" ) . asMilliseconds ( ) ;
4150
42- // If the last time the CTA toast was shown was less than 7 days ago, skip showing the toast
51+ // If the last time any CTA toast was shown was less than 7 days ago, skip showing the toast
52+ // This includes both the random CTA toast and the PDF download donation toast
4353 if ( last && isWithinCooldownPeriod ) {
4454 umamiTrackEvent ( "cta_toast_skipped_recently" ) ;
4555 return ;
@@ -59,8 +69,14 @@ export function useShowRandomCTAToast() {
5969 triggered = true ;
6070 showRandomCTAToast ( ) ;
6171
72+ // mark toast as shown in session to prevent duplicate toasts
73+ markToastAsShown ( ) ;
74+
6275 // save last shown timestamp to localStorage
63- localStorage . setItem ( STORAGE_KEY , String ( Date . now ( ) ) ) ;
76+ localStorage . setItem (
77+ CTA_TOAST_LAST_SHOWN_STORAGE_KEY ,
78+ String ( Date . now ( ) ) ,
79+ ) ;
6480
6581 // track event
6682 umamiTrackEvent ( "cta_toast_shown" ) ;
@@ -108,5 +124,5 @@ export function useShowRandomCTAToast() {
108124 window . removeEventListener ( "pointerdown" , resetIdle ) ;
109125 window . removeEventListener ( "keydown" , resetIdle ) ;
110126 } ;
111- } , [ ] ) ;
127+ } , [ isToastShownInSession , markToastAsShown ] ) ;
112128}
0 commit comments