Track how long a user stays on a page? - php

How can I track how long a user stays on a page before they request another or simply leave the site?
Basically, I want to do a check, if a user stays on the page for 20 minutes or longer, then do something.
I believe this would require php and javascript, but I am not exactly sure how to accomplish it.
Maybe using this $_SERVER in php to get the time of execution, and then get a timestamp when the user clicks somewhere else and simply compare the two?

You can do all this with simple javascript.
For a single page:
window.setTimeout(function(){
// Do stuff after 20 minutes of loading the page
// Then using jQuery you can call a PHP script to do stuff like so:
$.ajax({
url: '/myScript.php',
method: 'POST',
success: function(result){
//The request was successful and the output is stored in a variable: result
},
complete: function(){
//Do stuff when the request is completed (Ignores if success or not)
},
beforeSend: function(){
//Do something before the request is sent
}
});
}, 20 * 60 * 1000); //This is in milliseconds that's why I use the equation
For multiple pages:
I suggest you set a cookie with the time a user hits a page and on each page check if the cookie exists. If it exists run a query every x ammount of seconds to see if the 20 minutes have passed since the cookie has been created.
For full Ajax documentation head to: http://api.jquery.com/jQuery.ajax/

I've put some work into a small JavaScript library and service that times how long a user is on a web page. It has the added benefit of more accurately (not perfectly, though) tracking how long a user is actually interacting with the page. It ignores time that a user switches to different tabs, goes idle, minimizes the browser, etc. The Google Analytics method has the shortcoming (as I understand it) that it only checks when a new request is handled by your domain, which is not always accurate. It doesn't consider if someone is no longer viewing your page, has minimized the browser, has switched tabs to 3 different web pages since last loading your page, etc.
For reference - no solution is perfect. But hopefully this one provides value, too. You can implement the Javaacript API and gather the statistics yourself or you can use the service which does it all for you.
http://timemejs.com
An example of its usage:
Include in your page:
<script src="https://timemejs.com/timeme.min.js"></script>
<script type="text/javascript">
TimeMe.initialize({
currentPageName: "home-page", // page name
idleTimeoutInSeconds: 15 // time before user considered idle
});
</script>
If you want to report the times yourself to your backend:
xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","ENTER_URL_HERE",true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var timeSpentOnPage = TimeMe.getTimeOnCurrentPageInSeconds();
xmlhttp.send(timeSpentOnPage);
TimeMe.js also supports sending timing data via websockets, so you don't have to try to force a full http request into the document.onbeforeunload event.

Related

Using Jquery unload function to delete user from online users list

I want to know is there a way correct way to delete user from online users list with $(window).unload jQuery function?
or keep using PHP to check it?
i think this is not a correct way because user can edit it, but i need more reasons.
Code example:
<script src="jquery.min.js"></script>
<script>
$(window).unload(function() {
$.ajax({
type: "GET",
url: 'http://localhost/delete_session.php',
data: "id=" + "session id";
});
});
</script>
Thanks!
Doesn't work well with multiple tabs : if your the user opens your app in two different tabs, closing any of the two tabs will delete the session, and the other tab will become "unusable".
You should not solely rely on the client's behaviour to manage your sessions : the client's browser may exit incorrectly (program bug, battery out, kill -9, etc...) and not execute the unload callback on exit.
A correct way to do online list is probably using heartbeat requests.
Your javascript sends small requests to server indicating they are "alive".
If all pages are closed by user, the heartbeat stops and you somehow remove it from online user list on the server.

Detect Live Server Side changes (Long Polling, Short Polling or Web Sockets)

Justification and Research
I have a site that requires users to login in order to view. Whilst users are logged in, I would like to keep an eye on their user session. By this, I mean that I would like to know whether or not their user session has expired, and therefore redirect them.
Each user's session lasts 1 hour (or whatever I set it to), and is reset if they visit a different page (like most login systems).
At present, I have the following algorithm:
User arrives at private page (javascript method called isUserAuthorized() is executed)
The isUserAuthorized() javascript method makes an AJAX request to the page 'ajax.example.net/authorized'
This page returns a JSON object indicating the current status of the user like so:
{ authorized: true, timeout: 3600000 }
The javascript method then sets a timeout to call the method again in timeout milliseconds, assuming that the session will have ended then.
If the session has ended then redirect the user, otherwise recall in the method in timeout milliseconds.
There are two reasons I do not like this current method:
I have had issues with time syncing between client and server clocks, this is weird but it definitely causes an issue...
It leaves a timeout in the background of the webpage, and as this site is very javascript heavy, I would rather not have this additional timeout in order to keep the site as smooth as possible.
My Question
My question is therefore, can anybody think of a better way to achieve this? I have thought of long polling or websockets, but I am not 100% sure how to use either of these and the tutorials on websockets that I found were not very good! Would these actually be a better solution?
I could workaround the time syncing issues but before I do, I want to ensure that there are not better ways to achieve this...
In case it helps, here is my current code:
// Set the Authorized Timeout
MN.authorizedTimeout = setTimeout(function(){MN.isUserAuthorized});
/**
* Is User Authorized
* Checks to see if the current user is authorized and
* makes sure their session is still active
*/
MN.isUserAuthorized = isUserAuthorized;
function isUserAuthorized(){
// TEMPORARY
console.log('authorising');
// Set the authorized var
var authorized = false;
// Clear the current timeout
clearTimeout(MN.authorizedTimeout);
// Send request to determine whether the user is authorized
$.ajax({
url: "//ajax.example.net/authorized",
type: "GET",
dataType: "JSON",
cache: false,
async: false,
success: function(data){
console.log(data);
if(data.authorized){
// If the user is authorized then check again in timeout milliseconds
MN.authorizedTimeout = setTimeout(MN.isUserAuthorized,data.timeout_milliseconds);
// Set authorized to true
authorized = true;
}else{
// If the session has expired then proceed to informing the user
MN.userSessionExpired();
// Set authorized to false
authorized = false;
}
}
});
// Return the session status boolean
return authorized;
}
Updated Answer:
Nevertheless I'd consider it as a better practice to calculate the online status serverside. So you can make sure that there's no inconsistency with the time. You only have your servertime.
For getting the online status you can go for a long polling approach. I've made you an example:
(function checkLoginStatus(){
$.ajax({
type: 'POST',
url: 'loginstatus.php',
data: {userid : 25},
success: function(data){
if(data.logged_in !== true){
//Log the user out
}
},
dataType: "json",
complete: checkLoginStatus,
timeout: 15000
});
})();
This will make sure that a new request is made only when 15 seconds passed and when the request is complete.
Old Answer:
If your only concern is to watch over logged in users you don't need to poll. I'd keep the whole thing serverside. Just add a "last_active" field to your users table.
Whenever a user interacts (visits another site) update the timestamp to the current timestamp.
To detect whether a user is online take the current timestamp and subtract the "last_active" timestamp from it. If the difference is bigger than one hour, you know your user is inactive.
That's how I usually handle it. It also more efficient (regarding ressources) than doing it
with AJAX.
It sounds like in the big picture you would like something on the server that will alert the frontend at the moment a user's session expires.
Long-polling could do this. Basically you would have a backend controller that accepts connections and holds onto them until it gets a signal to send a response, or the connection times out. So your frontend would have a loop that basically sends a request and waits for a response. If the response comes back empty, it was a timeout, so send a new request. If the response has content, it wasn't a timeout, so you can take action. This achieves your goal, and many such systems are built this way. However, it is kind of a hack to use HTTP in reverse, and doesn't make for clean code.
A websocket is a bi-directional interface between a client and server. Here's what your client-side js would look like.
function connect(){
websocket = new WebSocket("wss://yoursite.com:8080");
//attach event handlers
websocket.onmessage = onMessage;
}
function onMessage(evt){
// do your thing
}
Once you call connect(), you can rest assured that onMessage() will take care of you when the server needs to reach the client. To me, sending messages from server to client is exactly why we have websockets, so they are the right tool for the job.

Curious about AJAX being asynchronous and Scheduled/timer event

I want a clarification about AJAX on something I was thinking about...
AJAX is said to be asynchronous - if you want it to be - meaning that if a javascript is run while a page loads and in that an AJAX call is executed the page will continue to load while the server process the AJAX request... So is it safe to assume that it can be liken to a pseudo-parallelism?
Now, what about two different javascripts making an AJAX call consequently. That is, while the page loads it encounters two js function one after the other each making an AJAX call each. Because they are different js functions/ or two different js files do they have to wait for the functions to return before they move on? I think that is the case...
And finally the real question I have... If I have a js function called and in that function I palce TWO AJAX calls then will they be processed semi-simultaneously... Because I was trying something on a webpage of mine and by accident I placed two AJAX calls one after the other and I think that was the reason I had some unexpected results. Unfortunately I was in a hurry to deliver so I didn't pursue it but I was wondering if it world like that, because it would be very convenient for some cases...
Somethign like this
function finalizeReservation(){
var request = $.ajax({
type: 'POST',
url: './scripts/php/reserve.php',
data: {
},
dataType: "json"
});
request.done(function(data,textStatus,jqXHR) {
});
request.fail(function(jqXHR, textStatus, errorThrown) {
});
var request2 = $.ajax({
type: 'POST',
url: './scripts/php/reserve.php',
data: {
},
dataType: "json"
});
request2.done(function(data,textStatus,jqXHR) {
});
request2.fail(function(jqXHR, textStatus, errorThrown) {
});
}
Simply curious.
I was thinking it because I have a web page that records reservations. Before finalizing a reservation though the guest can see the details and think about it. At that period the slot in the database is set to pending and making unavailable to another guest so they don't clash or enter in race conditions (i.e while thinking about it the other finalizes it and so when he tries to finalize it himself he cant or if was careless in the code also finalizes it). The problem is in the guest behaviour, although I have tried to capture all events of the refresh, backpage, exit tab, close window kind so the slot doesn't stay in a pending state if the guest for some reason doesn't close the form the correct way (cancel) not all are captured in all browsers. So I though about making a time limit in the server and if it exceeds it and the state is still pending the state is reversed to free (I have the form on a minute timer, after the minute goes it automatically closes and frees the slot). The problem is that the hosting server doesn't support chron jobs although I don't know much about them so I am not sure how much help they would be and the mysql doesn't support schedulers.
So i thought about making two ajax call and the one to be a timer that will check the state of the slot after some time passes and act accordingly.
Any thoughts are appreciated.
Sorry for the long post.
You don't have a specific question about Ajax, but you do seem to have a pretty good understanding of it and everything you said is correct. At least with jQuery, it's asynchronous by default and unless you use Deferred there is no guarantee that code that executes after the ajax call won't complete before the ajax call.
Your actual question seems to be about how to handle stale locks for the reservations. A couple suggestions:
Move to another shared host. I pay $15 a year for a shared host that allows cron jobs.
Whenever someone visits the page, check all locked reservations and if they are old enough assume the lock is stale.
Another ajax call won't help. What if they close the page? You could try using onbeforeunload, to alert a dialog that will remove the lock, but that's very intrusive.
the execution of code after the ajax functions will continue, without waiting for the ajax functions to complete, unless the code that follows is in the callback of the ajax function.

jQuery server/browser tax and flicker

I have a few of these on a couple pages on a new portal im building and was wondering how taxing it is on the server/client browser to have the following:
$(document).ready(function(){
var refreshId = setInterval(function() {
$("#passed_views").load('counter_passed.php');
}, 500);
$.ajaxSetup({ cache: false });
});
Also, it does seem to flicker on and off in Chrome... is there a better way to activate a listener like this?
Any help - suggestions are very much appreciated.
I have a script that runs ajax every 60 seconds and typical users have a 1-3 second delay from the time it fired to the time it gets a response back, some users go up to 10 seconds ect. What I would do is verify you got data back from your prior ajax call before sending another request so it doesn't Que up a bunch of requests. That way you could just not even use a set time, just use a loop that calls the script each time it gets a return from the previous call so people with slow times get it say 5 seconds apart and people with faster loads get it 1 second apart.

Getting user selections on clicking browser back button

My application has got several pages. On some pages I have given a back button on other pages it's not given (client's requirement). Now on a particular page, I have a list of choices (choices are image slides using jQuery plugin) to be selected by the user. Selecting a choice takes the user to next page. And now I want to get the same page with same selected choice as highlighted on clicking the browsers back button. On clicking the browsers back button, I guess the page is reloading loosing the cookie values i.e. when I select an image from my image set it takes me to another page. On clicking the browser back button, I wanted to get that page with same image selected from that set.Is there any work around so that I can get the selected values also on browser back.
Another plugin do that:
jQuery BBQ leverages the HTML5 hashchange event to allow simple, yet powerful bookmarkable #hash history. In addition, jQuery BBQ provides a full .deparam() method, along with both hash state management, and fragment / query string parse and merge utility methods.
http://benalman.com/projects/jquery-bbq-plugin/
You could utilize the onunload event, which almost all major browsers* will fire, when the back/forward/refresh button is used. Let the onunload event handler synchronously send an AJAX request, containing all the values needed to restore the current page state, to a PHP script:
$(window).unload(function() {
// Insert your code here to collect all values
// necessary to save a restorable state of the
// current page.
//
// var pageState = {
// page: host.pathname,
// :
// };
$.ajax({
type: "POST",
async: false,
url: "http://mydomain.com/mysave.php",
data: jQuery.param(pageState),
error: function(jqXHR, textStatus, errorThrown){
// your code
}
success: function(data, textStatus, jqXHR){
// your code
}
});
});
Let the PHP script save the received page state somewhere (e.g. session, database, etc.), so it's available, when you're about to generate a page you would like to be restored to a previous state.
Be aware, that this solution has a possible disadvantage.
The synchronous request is used to give the server a real chance to receive and process the request completely. An asynchronous request would return immediately, thus already loading the new page and maybe cancelling the asynchronous request running in parallel, before it has been completed (or even sent).
Otoh synchronous requests block (freeze the browser, user cannot do anything) until the server responds. In case your server does not respond, this would result in a deadlock. Unfortunately there is no way to cancel a synchronous request on client-side (at least none that I'm aware of), so you should always keep synchronous requests short as possible (server side processing time). And to make sure, that you have a fast and reliable server, but you should always have that anyways^^.
*Be aware though, that some browsers (e.g. Opera) do not fire the onunload event, when specific browsers button are used.

Categories