0

I am tracking the length of time an individual user is on my site. In order to achieve this I am logging the timestamp of when the user first loads the page and each time they click on a new page.

A brief summary:

Database table (time_on_site):

+-------+-----+-----------+----+
| start | end | unique_id | id |
+-------+-----+-----------+----+
  1. INSERT timestamp in start when session is created (just the once).
  2. UPDATE the timestamp in end each time the onbeforeunload event is fired.

This works fine for tracking the time they're on the site while browing pages, but when they leave the site (i.e., browser is closed/exited), a problem is occuring and I don't know how to find it. Basically the end record just isn't getting updated with the timestamp. It's like the AJAX function is not getting called properly since the browser is closing. I have set async to false in the AJAX call, but that does not help.

Why is this function not working when the user closes the browser, but works all other times the onbeforeunload event fires?

Edit

Error was simply that there was no check for else if($_GET['when'] == "end").

Here's my code:

index.php:

// If the session DOES NOT EXIST, make it and set it to TRUE.
if(!isset($_SESSION['new_visit']))
{
    $_SESSION['new_visit'] = true;
}

// If the session is TRUE, make it false.
if($_SESSION['new_visit'] == true)
{
    $this->db->store_visit();

    $_SESSION['unique_session_id'] = hash("sha512", uniqid("", true) . uniqid("", true) . uniqid("", true));

    $_SESSION['new_visit'] = false;
}

At the bottom of index.php:

<script type="text/javascript">

    if(window.addEventListener)
    {
        window.addEventListener("load",         function(){log_time("start");}, false);
        window.addEventListener("beforeunload", function(){log_time("end");  }, false);
    }

    function log_time(time)
    {
        var xmlhttp = "";
        var session = "<?php echo $_SESSION['unique_session_id']; ?>";

        // IE7+, Firefox, Chrome, Opera, Safari.
        if (window.XMLHttpRequest)
        {
            xmlhttp = new XMLHttpRequest();
        }
        // IE6, IE5.  
        else
        {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }

        xmlhttp.open("GET", "/application/logtime.php?session=" + session + "&when=" + time, false);
        xmlhttp.send();
    }

</script>

logtime.php:

//session_start();

require "database.php";

$db = new Database();

$unique_id = $_GET['session']; //$_SESSION['unique_session_id'];
$time      = time();

if($_GET['when'] == "start")
{
    if($get_rows = $db->mysqli->query("SELECT 1 FROM time_on_site WHERE unique_id = '$unique_id'"))
    {
        $rows = $get_rows->num_rows;
    }

    // If rows were afffected, the unique ID has already been stored so we must UPDATE. This happens each time a page is refreshed.
    if($rows >= 1)
    {
        $db->mysqli->query("UPDATE time_on_site SET end = '$time' WHERE unique_id = '$unique_id'");
    }

    // Else if the rows affected were 0, we must INSERT a new record. This happens once per session (visit).
    else
    {
        $db->mysqli->query("INSERT INTO time_on_site(start, unique_id) VALUES('$time', '$unique_id')");
    }
}
George88
  • 101
  • 2
  • 13
  • Maybe you need `onunload` instead `onbeforeunload`? – K-Gun Jan 21 '13 at 16:04
  • 1
    In `logtime.php` you need to either get the `$unique_id` variable from the session (`$_SESSION`), or validate it to prevent a trivial SQL injection attack. Also, `logtime.php` does nothing when `$_GET['when'] != "start"` – George Jan 21 '13 at 16:10
  • 1
    Note that Opera doesn't support the `onbeforeunload` event, and I don't see why the (more widely supported) `onunload` event couldn't be used here. Though it looks like your AJAX call is being made, in general a good way to check this in Chrome is to open up the Developer Tools and click Network (and use the Record button to preserve HTTP calls after you've navigated to a new page). – JacobEvelyn Jan 21 '13 at 16:11
  • @GeorgeP For crying out loud, George! You solved it, no action was being taken for `$_GET['when'] != "start"`. I've got to start checking my code more thoroughly, these questions of mine lately have been simple errors that any amateur could fix. Also, `$_SESSION` was being used originally instead of `$_GET`, but I considered the posibility that the session was unset/destroyed before the AJAX function was called and changed it so the session ID was echoed into JavaScript. Thanks George. – George88 Jan 21 '13 at 16:37
  • @George88, no worries, it happens to all of us! I've moved my answer to an actual answer so you can accept it. And as I said, if you have to get the session ID from the user, be aware that a malicious user could call your PHP script with any session ID they want, which your script would send straight to the database, leading to a major security hole. See: http://stackoverflow.com/questions/601300/what-is-sql-injection – George Jan 21 '13 at 16:43

1 Answers1

1
if($_GET['when'] == "start")
{
    // ...
}

This conditional is missing an else branch, so if $_GET['when'] != "start", nothing will happen.

George
  • 3,918
  • 21
  • 32