Track your visitors using an HttpModule

by Mads Kristensen 31. October 2008 02:53

I’ve been thinking about how to solve a very simple problem on a website: visitor behaviour tracking. In a sense it is what Google Analytics does, but there are problems with conventional JavaScript based trackers.

They are good at tracking page views, but very bad at tracking actions or behaviour around a website. Some products like Headlight are actually pretty good at tracking actions such as button clicks etc, but at the level I’m interested in tracking, I would have to add JavaScript all over my page. I don’t want to do that.

Also, there are some very good server-side logging products like log4net out there. The problem is that they are not really meant for tracking website behaviour with URLs, user agents and other important metadata.

What I want is a combination of the traditional JavaScript- and server-side methods. So, I’ve played around with a custom HttpModule that logs all page views and custom actions. You add the custom actions yourself by calling VistorLog.AddAction("message", "type"). That way you have page views and actions in a chronologically correct order.

A neat thing is that all page views and actions are kept in session and only when the session expires does it write to the database. That way it can do a batch insert which is much faster than hitting the database constantly. Another neat thing is that the HttpModule is only 100 lines of code.

The code

Basically, three things are going on. The session starts and we add a Visit object to it. 

void session_Start(object sender, EventArgs e)

{

  HttpContext context = HttpContext.Current;

  Visit visit = new Visit();

  visit.UserAgent = context.Request.UserAgent;

  visit.IpAddress = context.Request.UserHostAddress;

  context.Session.Add("visit", visit);

}

Then every page view is registered after an .aspx page is served.

void context_PostRequestHandlerExecute(object sender, EventArgs e)

{

  HttpContext context = ((HttpApplication)sender).Context;

 

  if (context.CurrentHandler is Page)

  {

    Visit visit = context.Session["visit"] as Visit;

    if (visit != null)

    {

      Action action = new Action();

      action.Url = context.Request.Url;

      action.Type = "pageview";

      visit.Action.Add(action);

    }

  }

}

Then the session ends and we need to store the visitor log.

void session_End(object sender, EventArgs e)

{

  HttpContext context = HttpContext.Current;

  Visit visit = context.Session["visit"] as Visit;

  if (visit != null)

  {

    // Log the Visit object to a database

  }

}

Implementation

When you have registered the HttpModule in the web.config, then it starts collection page views in the session. To store them in a database you must add your own code to the session_End method of the module. Now you are also able to store actions just by calling a static method on the VisitorLog module:

VisitorLog.AddAction("Profile picture deleted", "deletion");

Keep in mind that this code is just me playing around in my sandbox. It has never been in a production environment.

Download

VisitorLog.zip (1,11 kb)

* Only $4.95/month ASP.NET & Windows 2008 + IIS 7 Hosting! FREE SQL Included

Tags: , ,

ASP.NET

Comments

10/31/2008 5:53:43 AM #

Omer van Kloeten

Or you could simply use a free product that already exists which is much more powerful, and also happens to be where I work ;)

http://www.nuconomy.com/

Omer van Kloeten Israel |

10/31/2008 2:45:31 PM #

Bradvin

Can you rely on the session_end event? I have read many posts on forums complaining about the reliability of the end event. Have you had similar problems? I have not tried anything similar before, but have always wondered about this...

Bradvin South Africa |

10/31/2008 7:46:37 PM #

Miron

You will want to rename your 'Action' class to something else since 'Action' is part of the 'System' namespace

Miron Israel |

11/1/2008 2:12:10 PM #

Alex Tafoya

Nice addition!

Alex Tafoya United States |

11/1/2008 5:47:48 PM #

Mads Kristensen

@Omer

I've never seen that product before. From what I can tell from the website, it might be exactly what I'm looking for. Thanks

Mads Kristensen Denmark |

11/1/2008 7:18:26 PM #

trackback

Best of the web - my pick for October 2008

Best of the web - my pick for October 2008

Janko At Warp Speed |

11/1/2008 8:16:36 PM #

trackback

Best of the web - my pick for October 2008

There were a lot of high quality articles dawned in my Google Reader last month. Chris Spooner (Blog

Morning Break |

11/4/2008 4:45:09 PM #

mdma

this will work only if Session_End is triggered while in most of cases it is not.
Please read when Session_End is triggered before you implement it giving it a trust more than to Google's or anyone else's JS files.

quite useless October 2008 pick imho

mdma Israel |

11/5/2008 4:25:16 PM #

Dusan

Dear Mads, you said : "I would have to add JavaScript all over my page. I don’t want to do that." ... Well, this is exactly what seems to be happening all over the pages everywhere else? I think there might be some better reason for this than just a fashionable kind of a development.

Very often it is necessary to take the step back and see the full picture.

Kepp up a good work ;o)

Dusan

Dusan United Kingdom |

11/5/2008 4:26:15 PM #

Dusan


This above ic certainly NOT my gravatar picture ?

Dusan

Dusan United Kingdom |

11/7/2008 8:28:23 AM #

Josh Berke

Interesting idea, but this will not work if your using out of process session state as people posted the Session_End event is not fired. Also I'm not sure how large your site is but what would be the memory requirements for a high traffic site with lots of page hits?

The only other concern is that I assume your using inproc session state, since your Session_End event is working, in this case if your server goes down you've lost your data which if your only doing trend analysis isn't a big deal.

Just some thoughts but anyways interesting idea.

Josh Berke |

11/15/2008 7:44:50 PM #

Romi

Hi Mads,
How to use to redirect users using the ip to some pages. I searching to get the country and redirect the user to this or that pages.thanks.

Romi |

11/15/2008 9:59:06 PM #

pingback

Pingback from gearhed.com

gearhed.com  » Blog Archive   » Best of the web - my pick for October 2008

gearhed.com |

11/20/2008 6:04:12 PM #

trackback

Track your visitors using an HttpModule

Tracking the visitor actions is a common issue for web applications. You want to get statistics such

Guy kolbis |

12/2/2008 3:05:36 AM #

Yoann. B

Hi,

Great article

Here is my personnal approach : blog.sb2.fr/.../...ount-and-Infos-with-ASPNET.aspx

Thanks!

Yoann. B France |

12/5/2008 7:19:18 AM #

Speed Dating

This is one of the coolest things I have heard about. I am using ASP.net as that is what my programmer codes with. I will give him this post. Your blog is full of all these cool things. You are a genius.

Speed Dating United States |

12/13/2008 7:29:47 AM #

pingback

Pingback from mefeozer.wordpress.com

My Visitor Map Example Using Virtual Earth and MaxMind’s GeoIP API « M.Efe Ozer’s Weblog

mefeozer.wordpress.com |

1/2/2009 2:06:22 AM #

pingback

Pingback from zbstudio.net

Best of the web - my pick for October 2008 | zbStudio.net

zbstudio.net |

1/11/2009 5:35:34 AM #

cheap electric guitars

Nice idea. If Session_End is triggered that this should work.

cheap electric guitars United States |

1/11/2009 9:07:30 AM #

WII System Bundle

This tracking system is interesting. Hope see more soon!

WII System Bundle United States |

Comments are closed

About the slave

Mads Kristensen Mads Kristensen
Web developer at ZYB and founder of BlogEngine.NET. More...

LinkedIn ZYB Facebook Last.fm Twitter View Mads Kristensen's profile on Technorati

The Lounge

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008