Codeigniter邮件营销工具:网站停留时间追踪unload事件触发异常求助
解决CodeIgniter邮件营销工具中unload事件请求不稳定的问题
我之前在做用户行为追踪的项目时,也碰到过unload事件发起请求经常失败的情况,结合你邮件营销工具的场景,给你几个经过实践验证的解决方案:
1. 优先使用navigator.sendBeacon()替代普通Ajax
浏览器在触发unload事件时,会快速释放页面资源,普通的XMLHttpRequest或fetch请求很容易被直接丢弃。而sendBeacon是浏览器专门为页面卸载时发送数据设计的API,它会异步发送请求但保证浏览器完成数据传输,不会阻塞页面卸载。
前端代码示例:
// 监听beforeunload事件(比unload更可靠) window.addEventListener('beforeunload', function(event) { // 从Cookie中获取追踪数据 const trackIp = getCookie('track_ip'); const trackUrl = getCookie('track_url'); if (trackIp && trackUrl) { // 构造FormData,sendBeacon支持FormData/Blob类型数据 const formData = new FormData(); formData.append('ip', trackIp); formData.append('url', trackUrl); // 发送到CodeIgniter的追踪更新接口 navigator.sendBeacon('/tracking/update_closed_datetime', formData); } }); // 辅助函数:获取指定Cookie function getCookie(name) { const cookieStr = `; ${document.cookie}`; const cookieParts = cookieStr.split(`; ${name}=`); if (cookieParts.length === 2) { return cookieParts.pop().split(';').shift(); } return null; }
CodeIgniter后端控制器示例:
class Tracking extends CI_Controller { public function update_closed_datetime() { // 验证请求来源(可选,防止恶意请求) if (!$this->input->is_ajax_request()) { exit('Invalid request'); } $ip = $this->input->post('ip'); $url = $this->input->post('url'); if ($ip && $url) { // 更新数据库中的closed_datetime $this->db->where([ 'ip' => $ip, 'url' => $url ])->update('newsletter_tracking', [ 'closed_datetime' => date('Y-m-d H:i:s') ]); } } }
2. 搭配页面可见性API补充追踪
用户切换标签页、最小化窗口等行为,虽然没有关闭页面,但也属于“结束浏览”的场景,可以监听visibilitychange事件作为补充,进一步提升数据准确性:
document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'hidden') { const trackIp = getCookie('track_ip'); const trackUrl = getCookie('track_url'); if (trackIp && trackUrl) { const formData = new FormData(); formData.append('ip', trackIp); formData.append('url', trackUrl); navigator.sendBeacon('/tracking/update_closed_datetime', formData); } } });
3. 优化Cookie存储逻辑
确保Cookie能在整个官网域名下被读取,设置Cookie时指定path=/:
// 存储追踪数据到Cookie时的示例代码 document.cookie = `track_ip=${userIp}; path=/; max-age=3600`; document.cookie = `track_url=${encodeURIComponent(newsletterUrl)}; path=/; max-age=3600`;
同时注意URL的编码一致性,前端存储时用encodeURIComponent处理,后端直接匹配编码后的字符串,避免因特殊字符导致数据库匹配失败。
4. 备选方案:同步请求(不推荐,仅作兜底)
如果需要兼容非常老旧的浏览器(不支持sendBeacon),可以使用同步XMLHttpRequest,但会阻塞页面卸载,影响用户体验,仅作为最后兜底:
window.addEventListener('unload', function(event) { const trackIp = getCookie('track_ip'); const trackUrl = getCookie('track_url'); if (trackIp && trackUrl) { const xhr = new XMLHttpRequest(); xhr.open('POST', '/tracking/update_closed_datetime', false); // 同步请求 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send(`ip=${encodeURIComponent(trackIp)}&url=${encodeURIComponent(trackUrl)}`); } });
内容的提问来源于stack exchange,提问作者user6579211
相关产品推荐
相关产品推荐

