diff --git a/app/page.tsx b/app/page.tsx
index bbd18d6..c702024 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -11,7 +11,6 @@ import TrustBadges from "@/components/marketing/TrustBadges";
import FAQ from "@/components/marketing/FAQ";
import FinalCTA from "@/components/marketing/FinalCTA";
import Footer from "@/components/marketing/Footer";
-import SocialProofTicker from "@/components/marketing/SocialProofTicker";
import ExitIntentPopup from "@/components/marketing/ExitIntentPopup";
import StickyMobileCTA from "@/components/marketing/StickyMobileCTA";
@@ -59,10 +58,7 @@ export default function LandingPage() {
{/* Footer */}
- {/* Social proof notifications (bottom left) */}
-
-
- {/* Exit intent popup (desktop only) */}
+ {/* Exit intent popup */}
{/* Sticky mobile CTA bar */}
diff --git a/components/marketing/AnnouncementBar.tsx b/components/marketing/AnnouncementBar.tsx
index b94f09d..45331ed 100644
--- a/components/marketing/AnnouncementBar.tsx
+++ b/components/marketing/AnnouncementBar.tsx
@@ -9,18 +9,28 @@ export default function AnnouncementBar() {
if (!visible) return null;
return (
-
+
- Places limitées — Nouvelle session de formation TikTok Shop
- ouverte →
Candidater
+
+ Places limitées — Nouvelle session de formation TikTok Shop ouverte →{" "}
+ Candidater
+
+
+ Places limitées —{" "}
+ Candidater maintenant
+
diff --git a/components/marketing/ExitIntentPopup.tsx b/components/marketing/ExitIntentPopup.tsx
index 2a32841..f282ff7 100644
--- a/components/marketing/ExitIntentPopup.tsx
+++ b/components/marketing/ExitIntentPopup.tsx
@@ -1,33 +1,68 @@
"use client";
-import { useState, useEffect } from "react";
+import { useState, useEffect, useRef } from "react";
import Link from "next/link";
import Button from "@/components/ui/Button";
export default function ExitIntentPopup() {
const [show, setShow] = useState(false);
const [dismissed, setDismissed] = useState(false);
+ const lastScrollY = useRef(0);
+ const maxScrollY = useRef(0);
useEffect(() => {
if (dismissed) return;
// Check if already shown this session
- if (sessionStorage.getItem("hooklab_exit_popup")) return;
+ if (typeof window !== "undefined" && sessionStorage.getItem("hooklab_exit_popup")) {
+ setDismissed(true);
+ return;
+ }
- const handleMouseLeave = (e: MouseEvent) => {
- if (e.clientY <= 5 && !show && !dismissed) {
+ const triggerPopup = () => {
+ if (!show && !dismissed) {
setShow(true);
sessionStorage.setItem("hooklab_exit_popup", "1");
}
};
- // Only on desktop
- if (window.innerWidth >= 768) {
- document.addEventListener("mouseleave", handleMouseLeave);
- }
+ // Desktop: mouse leaves viewport at top
+ const handleMouseLeave = (e: MouseEvent) => {
+ if (e.clientY <= 5) {
+ triggerPopup();
+ }
+ };
+
+ // Mobile: user scrolls back up fast after scrolling at least 60% of the page
+ const handleScroll = () => {
+ const currentY = window.scrollY;
+ const pageHeight = document.documentElement.scrollHeight - window.innerHeight;
+ const scrollPercent = pageHeight > 0 ? currentY / pageHeight : 0;
+
+ if (currentY > maxScrollY.current) {
+ maxScrollY.current = currentY;
+ }
+
+ // Trigger if user scrolled past 60% of page and then scrolls up by 300px+
+ const scrolledUpAmount = maxScrollY.current - currentY;
+ const maxScrollPercent = pageHeight > 0 ? maxScrollY.current / pageHeight : 0;
+
+ if (maxScrollPercent > 0.6 && scrolledUpAmount > 300 && scrollPercent < 0.4) {
+ triggerPopup();
+ }
+
+ lastScrollY.current = currentY;
+ };
+
+ // Desktop: mouseleave
+ document.addEventListener("mouseleave", handleMouseLeave);
+
+ // Mobile: scroll-based trigger
+ window.addEventListener("scroll", handleScroll, { passive: true });
return () => {
document.removeEventListener("mouseleave", handleMouseLeave);
+ window.removeEventListener("scroll", handleScroll);
};
}, [show, dismissed]);
@@ -47,7 +82,7 @@ export default function ExitIntentPopup() {
/>
{/* Modal */}
-
+
{/* Close */}