I Added Exit-Intent Email Capture to My Checkout Page. Here Is What I Built.
Draft Disclaimer: Please note that this article is currently in draft form and may undergo revisions before final publication. The content, including information, opinions, and recommendations, is subject to change and may not represent the final version. We appreciate your understanding and patience as we work to refine and improve the quality of this article. Your feedback is valuable in shaping the final release.
Language Mismatch Disclaimer: Please be aware that the language of this article may not match the language settings of your browser or device.
Do you want to read articles in English instead ?
TL;DR
What: An exit-intent modal on the checkout page that captures email and phone before visitors leave, plus an admin filter to find anonymous engaged visitors. Why: Checkout abandoners are high-intent leads that disappear without a trace. How: Desktop detection via mouseleave, mobile detection via the Page Visibility API, background job to create leads in the CRM.
The Problem: Invisible Checkout Abandoners
Someone lands on your checkout page. They looked at the product. They clicked "buy". They got all the way to entering their details. Then they left.
You have no email. No phone number. No way to follow up. That visitor had higher purchase intent than 95% of your traffic, and you lost them completely.
This happens constantly. Industry averages put checkout abandonment around 70%. For most small SaaS and ecommerce shops, those abandoned visitors just disappear into the void.
I decided to fix that for my GPS tracking SaaS.
The Solution: Exit-Intent at the Highest-Intent Moment
Exit-intent modals are not new. But most implementations put them on the homepage or blog. That is low-intent traffic. The real opportunity is the checkout page, where intent is highest.
I added a modal that triggers when a visitor is about to leave the checkout. It asks for their email and phone number. Simple form, no tricks, just: "Before you go, want us to save your progress?"
On submit, the form dispatches a background job called CreateLeadFromCheckoutJob. The job creates a lead in my CRM with source set to "exit_intent" and captures the visitor's city and country from the request context. The lead enters the nurture pipeline automatically.
Desktop Detection: The Easy Part
On desktop, exit-intent detection is straightforward. You listen for the mouseleave event on the document element. When the cursor moves above the viewport (toward the browser's close button or address bar), the event fires.
document.documentElement.addEventListener("mouseleave", (e) => {
if (e.clientY <= 0) {
showExitModal();
}
});
You set a flag so it only fires once per session. You skip it if the visitor has already submitted the form or completed checkout. That is the entire desktop implementation.
Mobile Detection: The Tricky Part
Mobile has no cursor. There is no "moving toward the close button" event. This is where most exit-intent implementations stop.
I used the Page Visibility API. Specifically, the visibilitychange event. It fires when the user switches tabs, switches apps, or locks their screen. On mobile, this covers the most common ways someone leaves your page.
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") {
showExitModal();
}
});
It is not perfect. It does not catch someone hitting the back button and staying in the same browser tab. But it catches the majority of exits, which is good enough. The alternative was capturing zero mobile abandoners, so any improvement is significant.
Surfacing Anonymous Engaged Visitors
The exit-intent modal catches some abandoners. But others close the modal or leave before it triggers. For those, I built a second net.
My CRM already tracks visitor engagement scores. Every page view, click, scroll, and interaction adds points. A visitor who browses five pages and interacts with the product configurator might have a score of 60, even without signing up.
I added a Filament admin filter called "Anonymous and Engaged (40+)". It surfaces visitors with an engagement score of 40 or higher who never created an account or submitted their email. A score of 40 means they viewed multiple pages and did something meaningful on the site.
The sales team can now see a list of high-engagement anonymous visitors, sorted by score. They cannot email them directly (no contact info), but they can watch for return visits or match them to leads that come in through other channels.
Two Nets Are Better Than One
The exit-intent modal captures emails at the moment of highest intent. The anonymous engaged visitor filter surfaces the ones who slipped through.
Together, they cover two failure modes. The modal handles visitors who are willing to give their email but need a prompt. The filter handles visitors who browsed deeply but never engaged with a form.
Neither is complicated to build. The modal is a simple Alpine.js component with a form submission. The filter is a Filament query scope. The real value is connecting both to the CRM pipeline so leads get created and nurtured without manual work.
The Pattern for Other Founders
If you sell anything online, this is a pattern worth stealing.
First, add exit-intent on your checkout page, not your homepage. The intent delta is massive. A homepage visitor might be curious. A checkout visitor was ready to buy.
Second, use the Page Visibility API for mobile. Most exit-intent libraries skip mobile entirely. Even partial coverage beats zero coverage.
Third, connect the capture to your pipeline. An email sitting in a form submission table does nothing. A lead in your CRM with a source tag and geo data can enter an automated sequence and get a follow-up email within minutes.
Fourth, build a way to see who is engaged but anonymous. Not every visitor will give you their email. But knowing that someone spent ten minutes on your site and viewed your pricing page three times is actionable intel, even without their contact info.
The implementation took less than a day. The checkout modal, the background job, the Filament filter. All straightforward. The hard part is not the code. It is remembering that your checkout page is leaking high-intent leads and doing something about it.