Modern CRO strategies rely on behavioral triggersβlike exit intent, scroll depth, and engagement levelβto show popups only when users are likely to bounce without converting.
This technique boosts cart recovery, lead capture, and discount promo performance without annoying engaged users.
π§° Prerequisites
Tool | Purpose |
---|---|
OpenCart v3/v4 | Storefront with theme access |
Google Tag Manager | Trigger logic and behavioral tracking |
GA4 | Engagement metrics and audience tuning |
Popup Tool | (Custom HTML, ConvertBox, OptiMonk, etc.) |
π§ Strategy Breakdown
We will trigger a popup only if all of the following are true:
- User scrolled > 50%
- No
purchase
oradd_to_cart
recorded (via GA4) - Mouse movement toward browser top (exit intent)
- One-time trigger per session
π Step 1: Add Scroll Depth Trigger in GTM
A. Enable Built-in Scroll Variables
In GTM:
- Variables > Enable:
Scroll Depth Threshold
Scroll Direction
B. Create Scroll Trigger (50%+)
- Trigger Type: Scroll Depth
- Vertical Scroll: 50, 75
- Trigger on: All Pages
- Name it:
Scroll - 50%
π±οΈ Step 2: Create Exit Intent Detection Script
A. Add the script via GTM (Custom HTML tag):
<script>
document.addEventListener('DOMContentLoaded', function () {
var exitIntentFired = false;
document.addEventListener('mouseout', function (e) {
if (e.clientY < 50 && !exitIntentFired) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'exit_intent'
});
exitIntentFired = true;
}
});
});
</script>
- Trigger: All Pages
- This fires
exit_intent
when the mouse leaves toward the top
π§ Step 3: Create a One-Time Popup Trigger
A. Tag: Show Popup (Custom HTML)
<script>
if (!sessionStorage.getItem('popup_shown')) {
// Custom popup logic (HTML/3rd party embed)
alert('Wait! Grab a 10% discount before you go.');
sessionStorage.setItem('popup_shown', 'true');
}
</script>
Replace
alert()
with your actual popup tool (OptiMonk, ConvertBox embed, or custom modal)
π Step 4: Combine Scroll + Exit + No GA4 Event with Custom Trigger
A. Create Trigger: Custom Event
Name: Trigger - Exit + Scroll
- Trigger Type: Custom Event
- Event name:
exit_intent
- Additional Condition:
{{Scroll Depth Threshold}} > 49 AND {{DLV - add_to_cart}} != true AND {{DLV - purchase}} != true
You must push these GA4 events into the dataLayer to reference their absence.
π§Ύ Step 5: Push add_to_cart
and purchase
into dataLayer
In product.twig
and success.twig
, include:
A. Add to Cart (JS listener or backend trigger)
dataLayer.push({
event: 'add_to_cart'
});
B. On Purchase:
dataLayer.push({
event: 'purchase'
});
π Step 6: Optional β Push GA4 Engagement Flags for Future Use
GA4 sends engagement_time_msec
, which you can use via BigQuery or custom audiences, but for real-time GTM, it’s better to flag your own:
window.addEventListener('scroll', function() {
if (window.scrollY > 1000 && !window._hasScrolledDeep) {
window._hasScrolledDeep = true;
dataLayer.push({ event: 'scrolled_deep' });
}
});
Use scrolled_deep
as a signal to enrich the exit trigger condition.
π§ͺ Step 7: Test and Debug
Tool | What to Look For |
---|---|
GTM Preview | Does exit_intent fire after scroll? |
GA4 DebugView | Does add_to_cart / purchase exist? |
DevTools > Console | Check if popup script runs once |
Tag Assistant | Validate conditional firing logic |
π§ Bonus: Fire GA4 Event on Popup Trigger
To track effectiveness:
gtag('event', 'popup_shown', {
engagement_type: 'exit_scroll_trigger',
page_location: window.location.href
});
Use this in a GA4 tag or inline within your popup tag.