Implementing Presence - When to Change Status to Offline - javascript

I am working on implementing a "presence" feature on a website built on a classic asp (vbscript), SQL Server, javascript, IIS7 stack.
The existing authentication/log in system uses sessions, with a default 20 minute session timeout. The user data is stored in a SQL Server table. A cookie is also set when a user logs in, which enables tracking of registered users even when not logged in.
There is a column in the USERS table which holds the state e.g. "online" or "offline". The following is the logic I've come up with thus far:
Status is set to "online" when:
user logs in
a cookie is detected e.g. user returns but doesn't yet log in
Status set to "offline" when:
user logs out
user closes browser (use a javascript event to detect)
user navigates away from the site (not sure yet how best to detect this)
users session expires (handled in global.asa's Session_OnEnd subroutine)
Questions:
Am I overlooking anything in the logic presented above?
What is the best way (within js / classic asp) to detect items 2 and 3 above in the "when to set status to 'offline'" list
Thanks

With 2 and 3 there are js restrictions as to what you can do when js detects a potential leaving of the page. I think all you can do is to show a message before they leave. This means you wont be able to run any js as they are leaving.
Best way to detect when a user leaves a web page?
As Gary said probably the most effective way is to use some ajax to ping a script on the server to update a LastTimeOnline field in your db.
Another way is to use the Session_OnEnd but this may give a false figure as a user could be online for 5 secs which would trigger a 20 minute session.
Best to do the ping really.
All the other logic you have there seems fine.
Just spotted your other comment. Yes if someone leaves their browser open at the page then potentially this could be pinging all day. But then they maybe online so you'd have no choice but to presume that a session is active really. You could always add a bit of js that detects clicks and scrolling to determine activity.

IMHO, the best way to handle 2 and 3 is to have the client send a ping every x seconds, update last access time in DB, then have a logout function on the server side that looks for non-access within x amount of time, and update flag.
These automatic pings will make it seem like there is activity from the client when there may not be, and in this case add some events that capture mouse and keyboard activity. If they stop for some period of time, stop sending pings. Restart pings when activity resumes.
A ping is the only way that you will be 100% sure that the user is still there. Think of example where a user just shuts off the machine. You will not know that they are gone until 20 minute timeout expires. If you set your ping for 60 seconds, you will know very quickly is a user disappears.

Related

Proper way to detect user's leaving page

I am building a WebApp (ERP) and I need to display the people currently logged in and active on the page. I managed to get something pretty accurate by listening on the mouse/keyboard events and periodically reporting to the DB.
I don't know how to mark people offline when they close the page. I tried using onbeforeunload, but it obviously fires when the user simply changes pages (click a link inside the ERP, that point to another page in the ERP).
I then tried to use WebSockets, but the problem is the same : everytime the page is realoded, the WebSockets connection is closed.
So I can think of two ways:
Use WebSockets indeed, and replace all links by a call to a javascript function that would somehow tell the server that the user is going to change page (so that the server doesn't mark it as offline). But that doesn't feel right, semantically speaking, links should be links, it simply points to another location.
Use either WebSockets or AJAX and never actually change page: links are replaces by a function that will call for the content, and display it on screen (updating the DOM with Javascript). But again, it doesn't feel right either, because semantically speaking the page would have no meaning and the URL would never change, so the user can't "copy paste" the link of the page to refer to it, right ?
So, is there a proper, clean way of doing this? Thanks for your help.
If each of your pages has a webSocket connection to your server, then on the server you can see when any given page is closed by seeing that the webSocket gets closed.
To avoid thinking that a user has left the site when they are just navigating from one page in your site to another, you simply need to add a delay server-side so that you only report that the user has left your site if there has been no webSocket connection from this user for some time period (probably at least a few seconds).
So, on your server when you detect that the last webSocket connection for this user has been closed, you set a timer for some number of seconds. If the user opens up another page on your site (either via navigation or just opens another page) before the timer goes off, you cancel the timer and count the user as still connected. If the timer goes off, then you now know that the user has been away from your site for whatever time period you picked (say 10 seconds) and to you, this will signify that they have left the site. You can control how long you want that time period to be before you decide that, yes they are gone.
All attempts at trying to "see" the user leaving your page IN the browser with Javascript are going to have holes in them because there are always ways for a web page to get closed without your client-side javascript having a chance to tell your server. The beauty of the webSocket solution is that the browser automatically and reliably tells your server when the page is now gone because it closes the webSocket and your server receives the notification that the socket has been closed.
As I understand you want to compute users active on website/pages.
Identify the user (99% unique id computed):
http://valve.github.io/blog/2013/07/14/anonymous-browser-fingerprinting/ you can use another library, there are few.
On each page send from time to time at page load meaning user is navigating or (60sec you can chose lower time frame meaning user is staing on the page) computed id (fingerprint js) to server (web-socket/ajax)
On server you need to have list of id's with expiration date (60s) increment when new user log's in (stored in database or session).
Retrieve on your website the count (60sec ajax/websocket) of id's having timestamp <= server time - let say 120sec.
Knowing if user is logged, and specify the page:
use an object to be sent at server {fingerprint: 123123124234, logged : true, page: home}
Clear your list if you are not storing in Database the users:
Separate thread (server only) access the object and destroy all nodes older then 10 min or whatever your page session is set.
js timer: http://www.w3schools.com/jsref/met_win_setinterval.asp
Let hope it's helpful, id did something similar using the timer at 5 min to sent to server if user is still on the page, or signal at page load.
Getting the cont of users in frame of 60 sec. And even the users with names present on page :)
Somebody already post this kind of question.
Hope this could help you .
Detect if user has closed ALL windows for a website?

An indication of whether the user is still on site

I'm looking for an event that will return when close page whether the user is connected to my site.
onbeforeunload does not help me because it is also activated in efresh, submit, browse from page to page on the same site.
There is no client side event that triggers when a user leaves your site for another site specifically.
If you want to know if users are online you can make repeated ajax calls on a timer, and use a server side session that updates a timestamp of the last request. Using this you can query the timestamps for example, get sessions where the timestamp is in the last 2 minutes.
If polling is an option and you have a server-side backend, you could make a keep-alive script polling the server every x seconds and add it to all pages on your site. If you do not receive enough calls (i suggest at least 3 or so), consider it as a signal the user has logged out. Of course this won't provide an immediate feedback, but should be reliable enough.

Send info to the server when someone leaves a specific page

I'm coding a translation system for multiple messages.
I've a page with a table listing all the messages that need to be translated. When a translator click on a message to translate it, I lock it cause no other translator can be assigned to it.
The problem arises when a translator enters and instead to write something, leaves the page in an unconventional way like back button or closing the browser.
If this happens I want to unlock the message to make it available again to other translators.
How can I reach this behavior?
I know the javascript onbeforeunload event but triggers also every time a user refresh the page and this isn't what I want.
ty in advance
EDIT:
seems that implementing a js ajax call to notify every minute the server is the way to go. Now the question is how to handle the PHP server side?
You can use WebSockets, but in my opinion its a immature technology and still away from being firewall friendly.1
So, you can use HTTP polling. Use a JavaScript to make a HTTP request to the server from time to time, so it will show to the server the client is still in the page. The time will depend on connection, number of user's etc, but putting it before the keep-alive expires is a good idea as the TCP/IP connection is still open.
If the user leaves the page, the polling will not execute, and after not receiving the HTTP request for x seconds plus some time, the server can assume the user is not more on the page.
1 - Well its the firewall that is not friendly of WebSockets, this probably will change with time
What's wrong with using onbeforunload and asking the person if they really want to leave the page with unsaved changes?
I'd use the mentioned approach while proving a manual save button.
Also, a timeout on locks would help, so if the person has not edited the field for several minutes, it'd be unlocked and the person would be notified via a JS AJAX call.
EDIT: to implement the AJAX timer, I'd do the following:
save last access time to the translation item in a database or in a file on the PHP side
once every 30 seconds, do an AJAX call to a PHP script that will verify the last access time
depending on the result, return an "OK" or "TIMEOUT" message from the PHP script to the JavaScript part, which will then either do nothing (for OK) or deactivate the translation and inform the translation about the timeout

On site notification system

I was tasked to build a calendar and agenda library (I'm working on the CodeIgniter framework), that shows a calendar and the user has the possibility to set events on that calendar.
These events will have a notification system both email, and when the user is browsing the site, a popup.
My issue is how to approach the notification part when the user is on the site. The email is something that I already decided would be done trough a cronjob that will run every x minutes and check if there is any need to send a notification email.
The on site notification is something else.
How would I approach this? I just can't make a ajax request to the server every x seconds, since that would put an unnaceptable load on the system. (Of course when the user is eventually notified, a request must be made, to set the user as "remined" on the database).
I can't just depend on the user's date time, since he could be anywhere in the world and the time would be different.
How can I check that the user must be notified of a event, avoiding making repeated requests to the server? Would appreciate any input.
I could see using setTimeout to do this. Say a user visits your page $minutesTilDue minutes prior the reminder being due. Assuming jQuery/PHP:
$(function(){
setTimeout(function(){
showEventReminder(<?php json_encode($event) ?>);
}, <?php echo $minutesTilDue ?> * 60 * 1000);
});
Nothing too fancy, but depending on your requirements...
Cheers
Easily scalable notification systems use websockets, which today reach the majority of the users, even on mobile devices. Unfortunately, you'll need a websocket-enabled server - node, glassfish, whatever - this can't be done with standard PHP deployments (mod_php or fcgi). Server events (so called server push) are sent when they are generated, so once you have your websocket client-server pair, sending a reminder is just like sending an email.
Actually things are more complicated because most likely users won't be online at the exact time the reminder should pop up. I suggest a notification icon which is refreshed each time the user hits a page. This way your calendar system (suppose a cronjob) will simply update a flag for the user row in the DB, and when you build the page, you already know if there reminders (let's say, in the next 60 minutes) or not, and choose the icon accordingly. At this point, you have two choices:
sending the reminders to the client along with each and every request (it could be a waste of bandwidth, but I don't thing a JSON-encoded list of events is so heavyweight)
Download the reminders asynchronously on demand, ie only when the user hits the notification icon
This scenario lets you reuse the PHP environment and code, and doesn't require another host for the websocket server. I think this is the best solution, even if this doesn't fulfill your requirement of a truly popup reminder triggered by the server at the right time. BTW, if you send events with every request, your javascript can pop up when needed - you can use setTimeout() for this.

Security question: Using ajax and events to keep session alive

I know a few sites (such as my bank and my school) that kill a session after their has been idle for a set amount of time. It is my understanding that session activity is determined by users following links or at the very least from some kind of active interaction, like updating a form via ajax. Basically the server gets a request to do something during the session and goes ahead and extends the session time another 15 minutes.
But on some occasions I have lost major amounts of time and info while filling out a text box or reading some long set of instructions along the way.
So why not have an ajax script that listens for keyboard activity and mouse movement and lets the server know that the user is still there and active, even if they aren't clicking a submit button or following a link?
I was wondering if anyone knew of respectable sites that already do this, or if I was overlooking some major security hazard with this idea.
The only thing I can imagine would be risky are the random acts of cats, vibrating electronics nearby, or a hyper child.
But in all of the above, the user is most likely at home and -- unless they are trying to get exploited -- have probably minimized the window and thus these things are very unlikely to trigger as an event.
Does anybody see any other major risks?
Typical AJAX sites are making posts back to the server anyway. These events are renewing the users session already.
If you put these events on keyboard or mouse clicks, how many times are you going to be posting to the server? If I am typing in a form field like I am now, that means you could potentially have a ping to the server for each letter I type; not a very efficient solution. On the other end, what if your user is just sitting their reading or using an external text editor to type their text into and will copy it into your form later.
I think the more typical solution to provide a friendly UI so that long posts do not get dropped because of a session expiration is to use an auto-save feature. Google Docs does this. Every few seconds/minutes, they post the contents of the editor back to the server without the user actually clicking save/submit. The other option is to inform the user that their session is about to expire (could be done with a javascript timeout). Provide a link to ping the server to renew the session.
Your solution lends itself to the same problem: you are relying on user behavior. In the first case, navigating between pages and in the second, mouse clicks.
I used to work for a company that did a lot of online contests where users would have to enter essay content as well as shorter blocks of data; we used to modify the session time out "session.setMaxInactiveInterval()" for the user's session when they hit the "long-winded" page so that they would have more time to edit, and then we would set it back to normal after the submit.
Later at that company and a couple others I worked at I proposed a solution similar to what you are describing, but for various reasons it was never accepted. It was never considered a bad idea, just not one we chose. Basically it was going to be an ajax call on a timer so that just before the session timed out, it would fire off a light-weight ajax "ping" and keep the session alive as long as that page was open. I have never had the chance to implement it in the "real world" so perhaps there are negatives that I have not thought of.
Good luck.

Categories

Resources