3

I wanted to track visitors going to my web site. When a visitor arrives I want to add into my database that there has been a new visitor, and be able to tell if they are returning or new.

Would it be best to track them with a cookie, or via IP address? There would be a table called visitors, which would have the visitor_id, and their IP address, or cookie code. Another table called visits, which would track each time a "visitor" arrives at the site, with visit_id, visitor_id and date/time.

How can I identify if this is a new visit or just another page view? i.e. every page on the site would have this code that would add the visitor, but I wouldnt want it to record as a new visit every time they view a page.

The other thought I had was to use $_SERVER['HTTP_REFERER'], then I can tell the visitor is not making another page view from my site, but I am not sure how reliable that is.

So I was wondering how can we do this?

matronator
  • 465
  • 6
  • 13
Source
  • 1,026
  • 4
  • 11
  • 23
  • I would create a tracking cookie with a unique ID. Using IP only works if you know that all your visitors have unique IP's, which isn't always the case (companies etc usually have one external IP). The `HTTP_REFERER`-header isn't that reliable for two reasons. 1. It can easily be spoofed since it's the client that sends it. 2. It doesn't always exist/or populated. Many routers filters that out for privacy reasons. – M. Eriksson Mar 06 '17 at 22:44

3 Answers3

5

The best way is to use combination of IP address and COOKIES. Saving just IP address in not enough because it can change often when user is using proxy. For every page load you can use code like this

// Get IP address of user
function getUserIP() {    
  if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
  } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  } else {
    $ip = $_SERVER['REMOTE_ADDR'];
  }
  return $ip;
}

// Check if cookie exists. If not then set new cookie. Return its value
function getUserCookie() {
  if(isset($_COOKIE['visited'])) {
    // cookie is already set
  } else {
    list($usec, $sec) = explode(" ", microtime()); // Micro time!
    $expire = time()+60*60*24*30; // expiration after 30 day
    setcookie("visited", "".md5("".$sec.".".$usec."")."", $expire, "/", "", "0"); 
  }
  return $_COOKIE['visited'];
}

You can save both values to database table visitor if there are none visitor with these values and so you can say that it is unique new visitor. If there is visitor with one of these values then it is returning visitor and so you should update your visits table.

But i think its much better to have just one table since you don't know you visitors. With single sql query you will be still able to distinguish unique visitors, page views, visitors flow, time of visit and so on.

tomslou
  • 51
  • 2
3

I would suggest using a persisting cookie to store visitor information.

Tracking returning visitors

When a visitor comes to your site, you could check if they already have a visitor_id cookie in their browser:

  • If they do not, create a visitor ID for them and save it in a cookie, then use AJAX to send the ID to your server and create a new visitor from it in the database.
  • If they do, you can simply query your server via AJAX to get previous visitor information, or append their current session to their previous visits. More on this below.

This way you can track individual users by identifying the browser they're visiting from, as that's more likely to be stable than their IP or any other anonymous identification.

Note: you can also do it purely using PHP's $_COOKIE without AJAX, but I find it more comfortable to completely separate the client-side code from the back-end. It is only a matter of personal preference.

Some front-end pseudocode for this

if (haveVisitorCookie) {

    getVisitorDataByID(visitorCookie); //some ajax implementation

} else {

    createVisitorCookie(); //save to back-end
}

Tracking user activity on the site

The above part only covers identifying new/returning visitors and persisting visitor information. To record what a user does in a single visit, the easiest way is to use PHP's built-in sessions.

All you need to do is call session_start() at the beginning of your code and your visitor is assigned a session that will remain open until the visitor remains on any page of your site. You can then add data to the current session with the magic $_SESSION variable. You can store any data in it in the form of $_SESSION['key'] = value.

For example, you could query the current session ID on each page load, and if it already exists append the current action to it, otherwise save as a new visit from the same visitor.

Some back-end pseudocode

session_start();

if ($visitorID) { //visitorID is sent from your front-end and contains the cookie data

    $previousSession = getLastVisitorSession($visitorID);
    $currentSession = session_id();

    if ($previousSession) {

        if ($previousSession === $currentSession) {

            // New pageview on same session

        } else {

            // New session
            ...
            saveNewVisitorSession($visitorID, $currentSession)
        }
    }
}

Bonus points: you can even help your users continue from where they left off by loading their last session in case they don't have a current session ID but have a visitor ID with a previous session stored

Hope this helps!

ppajer
  • 3,045
  • 1
  • 15
  • 22
1

Sorry in advance, it's not really the prettiest of all codes :) But this I guess might be roughly it.

<?php
  //Step over if cookie is
  if (!isset($_COOKIE["SITE_VISITED"])) {  already set
    setcookie('SITE_VISITED', 'X');
    $db = mysqli_connect('localhost', 'bfu', '1234', 'visits');
    //Do we already have a record in the DB?
    $res = mysqli_query($db, sprintf("SELECT * FROM visits WHERE ipaddr='%s';",$_SERVER['REMOTE_ADDR']));
    if ($res === FALSE && $res->num_rows = 0) {
      //Record in DB not found, let's create one
      $res2 = mysqli_query($db, sprintf("INSERT INTO visits('ipaddr','page') VALUES ('%s','%s');",$_SERVER['REMOTE_ADDR'],$_SERVER['REQUEST_URI']));
    }
    mysqli_close($res);
  }
?>
Tommander
  • 76
  • 5