Some checks failed
Build and Deploy / build (push) Has been cancelled
- Email capture popup with scroll (10%) and exit intent triggers - First name field and full tracking (UTM, device, time on page) - Mautic API integration for contact creation - GeoIP detection for country/region - 4 locale support (sr, en, de, fr) - Mautic tracking script in layout
101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState, useCallback } from "react";
|
|
|
|
const STORAGE_KEY = "manoonoils-visitor";
|
|
const SESSION_DURATION_HOURS = 24;
|
|
|
|
interface VisitorState {
|
|
visitorId: string;
|
|
popupShown: boolean;
|
|
popupShownAt: number | null;
|
|
popupTrigger: "scroll" | "exit" | null;
|
|
subscribed: boolean;
|
|
}
|
|
|
|
export function useVisitorStore() {
|
|
const [state, setState] = useState<VisitorState>({
|
|
visitorId: "",
|
|
popupShown: false,
|
|
popupShownAt: null,
|
|
popupTrigger: null,
|
|
subscribed: false,
|
|
});
|
|
|
|
useEffect(() => {
|
|
// Check for reset flag in URL
|
|
if (typeof window !== 'undefined' && window.location.search.includes('reset-popup=true')) {
|
|
localStorage.removeItem(STORAGE_KEY);
|
|
console.log("[VisitorStore] Reset popup tracking");
|
|
}
|
|
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
if (stored) {
|
|
const parsed = JSON.parse(stored);
|
|
setState(parsed);
|
|
console.log("[VisitorStore] Loaded state:", parsed);
|
|
} else {
|
|
const newState: VisitorState = {
|
|
visitorId: generateVisitorId(),
|
|
popupShown: false,
|
|
popupShownAt: null,
|
|
popupTrigger: null,
|
|
subscribed: false,
|
|
};
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(newState));
|
|
setState(newState);
|
|
console.log("[VisitorStore] Created new state:", newState);
|
|
}
|
|
}, []);
|
|
|
|
const canShowPopup = useCallback((): boolean => {
|
|
if (state.subscribed) {
|
|
console.log("[VisitorStore] canShowPopup: false (already subscribed)");
|
|
return false;
|
|
}
|
|
|
|
if (!state.popupShown || !state.popupShownAt) {
|
|
console.log("[VisitorStore] canShowPopup: true (never shown)");
|
|
return true;
|
|
}
|
|
|
|
const hoursPassed = (Date.now() - state.popupShownAt) / (1000 * 60 * 60);
|
|
const canShow = hoursPassed >= SESSION_DURATION_HOURS;
|
|
console.log("[VisitorStore] canShowPopup:", canShow, "hours passed:", hoursPassed);
|
|
return canShow;
|
|
}, [state.popupShown, state.popupShownAt, state.subscribed]);
|
|
|
|
const markPopupShown = useCallback((trigger: "scroll" | "exit") => {
|
|
const newState: VisitorState = {
|
|
...state,
|
|
popupShown: true,
|
|
popupShownAt: Date.now(),
|
|
popupTrigger: trigger,
|
|
};
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(newState));
|
|
setState(newState);
|
|
}, [state]);
|
|
|
|
const markSubscribed = useCallback(() => {
|
|
const newState: VisitorState = {
|
|
...state,
|
|
subscribed: true,
|
|
};
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(newState));
|
|
setState(newState);
|
|
console.log("[VisitorStore] Marked as subscribed");
|
|
}, [state]);
|
|
|
|
return {
|
|
visitorId: state.visitorId,
|
|
canShowPopup,
|
|
markPopupShown,
|
|
markSubscribed,
|
|
popupTrigger: state.popupTrigger,
|
|
};
|
|
}
|
|
|
|
function generateVisitorId(): string {
|
|
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
}
|