PageSourceSearch

https://poxel.io/s/exit-intent.js

js poxel.io collected 2026-09-28 07:01:53 UTC 4,906 bytes, 144 lines download raw bytes

1// Exit intent detection based on mouse movement patterns
2let lastMousePosition = { x: 0, y: 0 };
3let lastMouseMoveTime = 0;
4let lastActivityTime = Date.now();
5let exitIntentDetected = false;
6let cornerDetectionTimeout = null;
7let afkTimeout = null;
8
9// Configuration
10const CORNER_THRESHOLD = 50; // pixels from corner to consider it a corner
11const MOVEMENT_THRESHOLD = 3; // minimum pixels to consider it a movement
12const TIME_THRESHOLD = 3000; // 3 seconds to detect slow movement
13const SLOW_MOVEMENT_THRESHOLD = 100; // pixels per second to consider it slow movement
14const AFK_THRESHOLD = 240000; // 4 minutes in milliseconds
15
16// Check if device is a touch-only mobile device
17function isTouchOnlyDevice() {
18    // Check if device has touch capability
19    const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
20    
21    // Check if device is a mobile device (excluding tablets and laptops with touch)
22    const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
23    
24    // Check if device has a keyboard (laptops/desktops)
25    const hasKeyboard = navigator.keyboard !== undefined;
26    
27    // Device is touch-only if it has touch, is mobile, and doesn't have a keyboard
28    return hasTouch && isMobile && !hasKeyboard;
29}
30
31function sendExitIntentToUnity() {
32    if (typeof unityInstance !== 'undefined') {
33        unityInstance.SendMessage('WebUtils', 'OnExitIntent');
34    }
35}
36
37function initExitIntentDetection() {
38    // Only initialize if not a touch-only device
39    if (isTouchOnlyDevice()) {
40        console.log("[exit-intent] Touch-only device detected, exit intent detection disabled");
41        return;
42    }
43
44    console.log("[exit-intent] Desktop device detected, exit intent detection enabled");
45    document.addEventListener('mousemove', handleMouseMove);
46    document.addEventListener('mouseleave', handleMouseLeave);
47    document.addEventListener('keydown', handleActivity);
48    document.addEventListener('click', handleActivity);
49    
50    // Start AFK timer
51    resetAFKTimer();
52}
53
54function handleActivity() {
55    lastActivityTime = Date.now();
56    resetAFKTimer();
57}
58
59function resetAFKTimer() {
60    // Clear existing AFK timeout if any
61    if (afkTimeout) {
62        clearTimeout(afkTimeout);
63    }
64    
65    // Set new AFK timeout
66    afkTimeout = setTimeout(() => {
67        if (!exitIntentDetected) {
68            exitIntentDetected = true;
69            console.log("[exit-intent] AFK exit intent detected after 4 minutes of inactivity");
70            sendExitIntentToUnity();
71        }
72    }, AFK_THRESHOLD);
73}
74
75function handleMouseMove(e) {
76    const currentTime = Date.now();
77    const timeDiff = currentTime - lastMouseMoveTime;
78    
79    // Update last activity time
80    lastActivityTime = currentTime;
81    resetAFKTimer();
82    
83    // Calculate movement speed
84    const distance = Math.sqrt(
85        Math.pow(e.clientX - lastMousePosition.x, 2) + 
86        Math.pow(e.clientY - lastMousePosition.y, 2)
87    );
88    const speed = distance / (timeDiff / 1000); // pixels per second
89
90    // Check if mouse is in a corner and moving slowly
91    const isInCorner = isMouseInCorner(e.clientX, e.clientY);
92    const isMovingSlowly = speed < SLOW_MOVEMENT_THRESHOLD && distance > MOVEMENT_THRESHOLD;
93
94    if (isInCorner && isMovingSlowly && !exitIntentDetected) {
95        if (!cornerDetectionTimeout) {
96            cornerDetectionTimeout = setTimeout(() => {
97                if (isMouseInCorner(e.clientX, e.clientY)) {
98                    exitIntentDetected = true;
99                    console.log("[exit-intent] Corner exit intent detected - mouse moved slowly to corner for 3 seconds");
100                    sendExitIntentToUnity();
101                }
102            }, TIME_THRESHOLD);
103        }
104    } else if (!isInCorner || !isMovingSlowly) {
105        // Reset detection if mouse moves out of corner or moves too fast
106        if (cornerDetectionTimeout) {
107            clearTimeout(cornerDetectionTimeout);
108            cornerDetectionTimeout = null;
109        }
110        exitIntentDetected = false;
111    }
112
113    // Update last position and time
114    lastMousePosition = { x: e.clientX, y: e.clientY };
115    lastMouseMoveTime = currentTime;
116}
117
118function handleMouseLeave(e) {
119    // If mouse leaves through the top, consider it an exit intent
120    if (e.clientY <= 0) {
121        console.log("[exit-intent] Mouse left through top of window");
122        sendExitIntentToUnity();
123    }
124}
125
126function isMouseInCorner(x, y) {
127    const windowWidth = window.innerWidth;
128    const windowHeight = window.innerHeight;
129
130    // Check top-left corner
131    if (x <= CORNER_THRESHOLD && y <= CORNER_THRESHOLD) {
132        return true;
133    }
134    
135    // Check top-right corner
136    if (x >= windowWidth - CORNER_THRESHOLD && y <= CORNER_THRESHOLD) {
137        return true;
138    }
139
140    return false;
141}
142
143// Initialize when the script loads
144initExitIntentDetection(); 

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.