用户在访问网站期间所花费的时间如何测量?

10

我正在尝试使用PHP和Javascript以及MAMP在本地构建网站。

我想要的是在网站的每个页面上放置一个计时器,该计时器会计算用户在整个网站中花费的时间。即使用户在页面之间切换,计时器仍将继续计时。我找到的解决方案只显示了在每个页面上花费的时间,并且当我重新加载同一页面时,计时器从零重新开始。

这是我编写的计时器的Javascript代码:

window.onload=function(){
 time=0;
}
window.onbeforeunload=function(){
 timeSite = new Date()-time;
 window.localStorage['timeSite']=timeSite;
}

我已经到处寻找解决方案,但没有成功,如果有人知道如何做,请告诉我。


1
使用会话变量,它将被所有页面共享。 - Barmar
尝试使用纯JavaScript解决方案,查看更新后的答案...我认为咖啡很好用...此外@Barmar有一点。这意味着在您的情况下,我会尝试编写类似的基于会话变量的服务器端代码,以防万一浏览器禁用了JavaScript。(多久发生一次!!!)。 - user2560539
2个回答

12

这里是一个可运行的示例。当用户关闭窗口/标签时,它将停止计数。

var timer;
var timerStart;
var timeSpentOnSite = getTimeSpentOnSite();

function getTimeSpentOnSite(){
    timeSpentOnSite = parseInt(localStorage.getItem('timeSpentOnSite'));
    timeSpentOnSite = isNaN(timeSpentOnSite) ? 0 : timeSpentOnSite;
    return timeSpentOnSite;
}

function startCounting(){
    timerStart = Date.now();
    timer = setInterval(function(){
        timeSpentOnSite = getTimeSpentOnSite()+(Date.now()-timerStart);
        localStorage.setItem('timeSpentOnSite',timeSpentOnSite);
        timerStart = parseInt(Date.now());
        // Convert to seconds
        console.log(parseInt(timeSpentOnSite/1000));
    },1000);
}
startCounting();

如果你想在窗口/选项卡不活动时停止计时器,请添加以下代码:

var stopCountingWhenWindowIsInactive = true; 

if( stopCountingWhenWindowIsInactive ){

    if( typeof document.hidden !== "undefined" ){
        var hidden = "hidden", 
        visibilityChange = "visibilitychange", 
        visibilityState = "visibilityState";
    }else if ( typeof document.msHidden !== "undefined" ){
        var hidden = "msHidden", 
        visibilityChange = "msvisibilitychange", 
        visibilityState = "msVisibilityState";
    }
    var documentIsHidden = document[hidden];

    document.addEventListener(visibilityChange, function() {
        if(documentIsHidden != document[hidden]) {
            if( document[hidden] ){
                // Window is inactive
                clearInterval(timer);
            }else{
                // Window is active
                startCounting();
            }
            documentIsHidden = document[hidden];
        }
    });
}

JSFiddle


1
如果我访问https://jsfiddle.net/4e223aht/44/示例,我会看到控制台写入计数秒数。我关闭窗口。我重新访问jsfiddle上的示例页面,并看到控制台从上次访问的时间开始计数。这正确吗?重新访问时不应该从头开始重新计数吗? - user2560539
这是正确的行为。它完全按照 OP 的要求执行:计算用户在整个网站上花费的时间,即使用户在页面之间切换。 - Etienne Martin
“在页面之间切换”…这难道不意味着,即使用户打开了同一网站的两个或三个浏览器窗口并在每个窗口中获得相同的时间,也要正确计算网站上的时间吗?但是,如果用户关闭浏览器和所有与该网页相关的窗口,脚本是否应在新访问时重新计算时间? - user2560539
我认为 OP 在这个问题中试图做的是确定每次访问的用户时间。术语“每次访问”意味着,如果用户打开同一页面的4个窗口,则不要在每个新窗口上从开始用户时间计数。我认为这是“测量用户在网站访问期间所花费的时间”的标题,我也认为您的方法计算了在网站的所有用户访问中花费的总时间。这是因为您没有清除“localStorage”,因此,如果我重新访问该网站,则时间将从使用之前花费在网站上的时间开始计算。 - user2560539

3
使用localStorage可能不是你所需要的最佳选择。但是sessionStoragelocalStorage是最合适的。请注意,当打开一个新标签页时,sessionStorage会解析为一个新的会话,因此使用localStorage是因为如果只使用sessionStorage并且用户在同时打开一个新标签并访问您的网站,将会为该浏览器标签页解析为一个新的单独会话,并从开始计算timeOnSite。在下面的示例中,尝试避免这种情况并准确计算timeOnSite

sessionStorage属性允许您访问当前源的会话存储对象。sessionStorage类似于Window.localStorage,唯一的区别在于存储在localStorage中的数据没有设置过期时间,而存储在sessionStorage中的数据在页面会话结束时会被清除。页面会话持续的时间与浏览器打开的时间一样长,并在页面重新加载和恢复时保留。在新标签页或窗口中打开页面将导致启动一个新的会话,这与会话cookie的工作方式不同。

function myTimer() {
if(!sessionStorage.getItem('firstVisitTime')) {
   var myDate = Date.now();
   if(!localStorage.getItem('timeOnSite')) {
   sessionStorage.setItem('firstVisitTime',myDate);
   } else {
   if(localStorage.getItem('tabsCount') && parseInt(localStorage.getItem('tabsCount'))>1){
   sessionStorage.setItem('firstVisitTime',myDate-parseInt(localStorage.getItem('timeOnSite'))); 
   } else {
   sessionStorage.setItem('firstVisitTime',myDate);
   } 
}
}
var myInterval = setInterval(function(){  
   var time = Date.now()-parseInt(sessionStorage.getItem('firstVisitTime'));
   localStorage.setItem('timeOnSite',time); 
   document.getElementById("output").innerHTML = (time/1000)+' seconds have passed since first visit';
}, 1000);
return myInterval;
}    
window.onbeforeunload=function() {
console.log('Document onbeforeunload state.');
clearInterval(timer);
};
window.onunload=function() {
var time = Date.now();
localStorage.setItem('timeLeftSite',time);
localStorage.setItem("tabsCount",parseInt(localStorage.getItem("tabsCount"))-1);
console.log('Document onunload state.');
};
if (document.readyState == "complete") {
if(localStorage.getItem("tabsCount")){
localStorage.setItem("tabsCount",parseInt(localStorage.getItem("tabsCount"))+1);
var timer = myTimer();
} else {
localStorage.setItem("tabsCount",1);
}
   console.log("Document complete state.");
}

工作中的演示

如果您需要服务器端的解决方案,则设置$_SESSION['timeOnSite']变量,并在每次页面导航时相应地更新。


你的解决方案没有提供用户在网站上花费的时间。它只返回自第一次访问以来经过的时间。 - Etienne Martin
@EtienneMartin... 如果你的意思是即使关闭浏览器,它仍保留localStorage键“firstVisitTime”,并且在下一次访问中从该日期开始计数而不是新的“firstVisitTime”,那么我会尝试相应地进行编辑,一旦我喝了一些......咖啡! :) - user2560539
@EtienneMartin,“sessionStorage”似乎是这个问题的最佳选择。如果您不想在网站上计算花费的时间出现问题。唯一的问题是,在同一页的新浏览器选项卡上,时间仅针对该用户会话计数。 - user2560539
1
@EtienneMartin 我会编辑我的答案,似乎使用localStoragesessionStorage以及一个setInterval可以解决问题。即使有2-3个标签页打开,也可以正确计算用户在网站上花费的时间,但当用户关闭所有标签页并重新打开时,新会话将开始。 - user2560539
2
我从未理解过为什么会有人对一个正常工作的东西进行负评。我的回答展示了用户在网站上花费的时间。只要一个或多个浏览器选项卡处于打开状态并访问单个网站的各个页面,它将正确计算时间。当所有浏览器选项卡关闭时,网站上花费的时间将被重置为零,直到下一次访问。 - user2560539

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接