Creative Juices Bo. Co.

Satisfy Your Thirst For Something Refreshing!

CJ Website Visitor Tracking 0.0.5

A Live Visual Representation Of Website Visitors

CJ Website Visitor Tracking is an experimental tool to help you visualize the live traffic on your website. This project is using a variety of technologies, including jQuery, Processing.js and ColdFusion. It should work with any modern web browser. But do to the fact that this is an experimental too, Internet Explorer is not supported at this time.

The Tracker System

In order to keep track of which pages the visitor is viewing, we need to know two things. When the user first loads the page and when the user leaves or unloads the page. I looked at a few ways of doing this but the simplest way was to use JavaScript and jQuery.

To do this all we need to do is attach a onLoad and a onUnload event to the window element. Once we do that we can have them call our functions to process the document location. Here's the code I came up:

jquery.cj.tracker.js

jQuery(function () {
   jQuery(document).ready(function () {
      // check the page url and add it to the sitemap, if it doesn't exist
      jQuery(window).load(function () {
         jQuery.ajax({
            url: "cj_tracker.cfc?method=doSitemap&loc=" + escape(document.location.href),
            cache: false,
            async: false
         });
      });
       // create a unique id that we can attach to this user record
      var uid = "V" + new Date().getTime();
      // handle our page load function
      jQuery(window).load(function () {
         jQuery.ajax({
            url: "cj_tracker.cfc?method=doVisitorTracking&loc=" + escape(document.location.href) + "&action=load&ua=" + escape(navigator.userAgent) + "&uid=" + uid,
            cache: false,
            async: false
         });
      });
      // handle our page unload function
      jQuery(window).unload(function () {
         jQuery.ajax({
            url: "cj_tracker.cfc?method=doVisitorTracking&loc=" + escape(document.location.href) + "&action=unload&ua=" + escape(navigator.userAgent) + "&uid=" + uid,
            cache: false,
            async: false
         });
      });
   });
});

The first ajax call is used to create a dynamic sitemap for my website. It takes the current page URL and then checks to see if that entry exists in our sitemap.js JSON object. If not, it will break the URL down into a hierarchy and add each part to the file. This isn't really needed and honestly after a few days most of my links were already added to the file. So in theory, if all your links are added you could comment this section out. And if you add new pages, you could manually add the links to the file. Having this here may slow down the process, but I haven't done a lot of load test yet. Here's an example of what the sitemap JSON object looks like:

sitemap.js

[
   {
      "PARENTS": [],
      "URL": "http:\/\/www.cjboco.com\/"
   },
   {
      "PARENTS": [ 
         0
      ],
      "URL": "http:\/\/www.cjboco.com\/blog.cfm"
   },
   {
      "PARENTS": [
         0
      ],
      "URL": "http:\/\/www.cjboco.com\/projects.cfm"
   }
]

It's a fairly straight-forward layout. It's basically an array of page entries, where each entry has the URL and an array of parents id's. I'm not using multiple parents on my site, but it's possible that a particular URL could have multiple parents, so I went ahead and took that in account.

The next to calls handle when a user loads and unloads the page. A unique id was created and passed along to each function so we can easily track that page record in the visitor.js JSON object. We have the ability to pass other data at this point to track the user. At this point, I'm just passing along the browser user agent string. Put you could also pass the IP address or whatever else you could think of. This is the basic format of the visitor.js file:

visitor.js

[
   {
      "VISITORS": [
          {
            "TIME_STAMP": "05-04-2010 11:30:51",
            "UID": "V1272990651146",
            "USER_AGENT": "Mozilla\/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us) AppleWebKit\/531.22.7 (KHTML, like Gecko) Version\/4.0.5 Safari\/531.22.7"
         }
      ],
      "URL": "http:\/\/www.cjboco.com\/"
   },
   {
      "VISITORS": [
         
      ],
      "URL": "http:\/\/www.cjboco.com\/blog.cfm"
   }
]

Again, the structure is failry simple. It contains entries of each page. Within each entry is the URL and an array of visitors for that page. The VISITORS array contains a timestamp, the unique ID we passed to the function and the user agent data. The reason I added a timestamp to each entry is because on some occasions the the onUnload event doesn't seem to fire. So by plassing a timestamp into each entry, we can check to see if there are any "hanging" entries available that we can purge after a certain amount of time. I chose to use 15 minutes, but this value could realistically be anything. We check this value each time we perform an onLoad event.

The ColdFusion Tracker Engine

We use a ColdFusion component to handle the AJAX calls from our page script. I'm not going to break down everyhing in this script put I'll list out what I'm doing and if you have any questions, just let me know. The only thing you will have to change are the two variables up top. These need to point to where you want to store your sitemap.js and visisor.js files. If you move these to a different location or rename the files, be sure you update the Processing.js script to point to the correct files.

doVisitorTracking

This function will take a URL location string argument passed from the jQuery tracker script and store it in the visitor.js file.

doSitemap

This function will take a URL location string argument passed from the jQuery tracker script and store it in the sitemap.js file.

doLocToArray

This utility function is used to break down the URL location into a heiarchal array. It's used by the two other functions to add each level of the URL. i.e. If you pass the location of "http://www.cjboco.com/projects.cfm/project/cj-website-visitor-tracking/0.0.5" it will convert it into an array, like so:

doLocToArray Example

I've also added some cjboco.com site specific clean-up. These are used mainly to control which links get added to the sitempa.js file. I personally don't want every single link to go in there, but your usage may very. You can add or remove to this code to fit your needs.

Processing.js

To display the data that we've been collecting, I've choosen to use processing.js. By no means am I some kind of expert at using this thing. This project was my excuse to start playing around with it. I really wish I had some better math skills, because what I'm trying to do and what actually happening is not exactly on the same page. I wanted the sitemap to automatically resize and reposition itself depending on the data in the sitemap.js file. As you can tell from the image above, it's not perfect. I'm planning on playing around with this some more, when I have some more time. In the meantime, download the files and take a look. If your some kind of math wizard, do something cool and come back here and let me see what your doing.

Conclusion

This is still in beta mode as I play around with a few of the settings, but I figure I would release it now to start getting some feedback. More information should follow later on this week. I'll upload the zipped files tomorrow. In the mean time, check out the demo and let me know what you think. I've installed the tracker on the website, so the data you are seeing is live visitors.