-1

I am currently working on a website in aspx, where I need to detect and record if a user is about to leave the site.

It will need to capture if possible all of the following, if the user:

  • clicks on the browser Back or Forward buttons
  • clicks on the browser close button
  • clicks on the tab close button
  • navigates to a new website
ccStars
  • 817
  • 2
  • 11
  • 34

1 Answers1

1

If it's remotely possible, change the requirement, because it will lead to a less-than-ideal user experience.

On at least some browsers, you can do a synchronous ajax request from the onbeforeunload handler to send information to your server that the user is leaving the page:

window.onbeforeunload = function() {
    $.ajax({
        url:   "/path/to/page",
        data:  {/* ...stuff... */,
        async: false // <== Option is being removed soon
    });
};

The reason I say it's a bad user experience is that since the ajax call is synchronous, it holds them up, and fairly intrusively on some browsers (the whole thing locks up while waiting for the request to complete). This is also why it may well not be reliable cross-browser.

The jQuery team is removing the async option from ajax at some point. It's still there in the underlying XMLHttpRequest object, so when that happens you can use that directly.


The fact the user left the site is already apparent from the web server logs, although you can't tell how long they spent on the final page. If that "how long did they spend on the final page" is really vital information, rather than holding them up when they leave (and relying on something that may not be entirely reliable cross-browser), you could use a background "ping" while they're still on the page. It would probably be best to do the pings further and further apart over time.

So for instance, when the page loads:

(function($) {
    var SECOND = 1000;
    var MINUTE = 60000;
    var arrived = +new Date();
    var pingTimes = {
        0:      10 * SECOND, // Every 10 seconds in first minute
        1:      30 * SECOND, // Every 30 seconds in second minute
        2:      45 * SECOND, // Every 45 seconds in third minute
        other:  60 * SECOND, // Every minute otherwise
        long:   10 * MINUTE  // Every 10 minutes if they've been here a long time
    };

    nextPing();

    function ping() {
        $.ajax({
            url:     "/path/to/ping/page",
            method:  "POST",
            success: nextPing,
            error:   nextPing
        });
    }

    function nextPing() {
        var elapsed, pingTime;

        // Get the # of full minutes they've been here
        elapsed = Math.floor((new Date() - arrived) / MINUTE);

        // If it's been a long time, use `pingTimes.long`.
        // Otherwise, use the time from the table or the default.
        pingTime = elapsed > 15 * MINUTE ? pingTimes.long : (pingTimes[elapsed] || pingTimes.other);

        setTimeout(ping, pingTime);
    }

})(jQuery);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875