This is a quickie post explaining how to use ASP.NET in order to collect visitor statistics on a page which does not allow JavaScript. The idea is simple – you place a 1×1px transparent GIF onto the image, with the GIF’s address being on your server.

The GIF actually points to a typical ASPX page, i.e., you write something like the following:

<img src="http://mysite/stats/default.aspx"/>

The page default.aspx is a basic WebForms page. Its statistical tracking is done in the Page_Load() method, the contents of the ASPX file being completely irrelevant for our purposes.

Three things happen in Page_Load(). First, since we don’t want our service abused, we check that the page that sent the request is ‘legit’. If you don’t do this, people will figure out that you have a service, and might even try to DDoS you just for the fun of it. I also check that the IP isn’t mine, so that my own visits to the page do not count.

private static readonly string[] permittedURLs = new[]
{
  "http://site.com/page/"
};
protected void Page_Load(object sender, EventArgs e)
{
  if (Request.UrlReferrer == null ||
    Array.IndexOf(permittedURLs, Request.UrlReferrer.AbsoluteUri) == -1 ||
    Request.UserHostAddress == "1.2.3.4"// my IP address
    return;
}

If any of the checks fail, we return from the page, yielding the ASPX content instead of the image. If they succeed, we add an entry to the database. The example below uses LINQ2SQL in order to add an entry concerning the time the page was accessed, the IP of whoever accessed it, and the page it was accessed from.

using (var dc = new VisitsDataContext())
{
  Visit v = new Visit();
  v.DateAndTime = DateTime.Now;
  v.IPAddress = Request.UserHostAddress;
  v.ReferrerURL = Request.UrlReferrer != null ? Request.UrlReferrer.AbsoluteUri : null;
  dc.Visits.InsertOnSubmit(v);
  dc.SubmitChanges();
}

For safety, I check referrer for null, which helps with debugging. Now, with that done, I load up a 1-pixel GIF (which I keep in the same folder) and serve it. Then, I end the response so that the ASPX doesn’t get sent after the image data.

using (Bitmap bmp = (Bitmap)Bitmap.FromFile(Server.MapPath("OnePixel.gif")))
{
  Response.ContentType = "image/gif";
  bmp.Save(Response.OutputStream, ImageFormat.Gif);
}
Response.End();

Using the code shown, you can easily and discreetly collect usage statistics from any web-resource which you do not own but can post images on.