facebook  linkedin  Twitter  skype  Rss googlePlus

Building an Email Tracking System

Jan 21 2004

The Task

For many portal websites, they always host one or two newsletters for their users. Oftentimes, when they send out their newsletter, they want to be able know how many users have opened and read the newsletter and where they are from.

The Solution

To accomplish this task, we embed an image call into the newsletter’s HTML so that every time when the user opens the newsletter, an image call is made and the server is notified. On the server side, we set up an HttpHandler to parse the image call in order to collect the information from the user as well as to end the call by generating a transparent beacon image.

Step 1. Decide What to Embed In the Image Call

In our example we will embed the NewsletterID and UserID into the image call, and a typical beacon image call in our example will be like:

So if we have NewsletterID as 234 and UserID as 123, the image tag will be:

If you notice, here we use the extension ‘.open’. This is to make ourselves convenient when setting up server-side URL mapping (see step 5).

Step 2. Create an Http Handler by Implementing IHttpHandler Interface

The IHttpHandler interface defines the contract that ASP.NET implements to synchronously process HTTP Web requests using custom HTTP handlers. By implementing the IHTTPHandler interface, our custom handler will be able to process the incoming request just like ISAPI extension filters but with a simpler programming model.

using System;
using System.Web;
namespace EmailTracking { /// /// Summary description for OpenHandler. /// public class OpenHandler : IHttpHandler { // Specify the location of the beacon image private string pixelFile = "~/Images/pixel.gif"; // Constructor public OpenHandler() {} // Process the request public void ProcessRequest(HttpContext context) { OpenURIParser.Process( context.Request.Path, context.Request["REMOTE_ADDR"]); // Output image context.Response.ContentType = "image/gif"; context.Response.WriteFile( context.Request.MapPath( pixelFile ) ); context.Response.End(); }
// This property is used to determine whether an instance // of the handler can be reused across multiple requests. public bool IsReusable {
get { return true; } } } }
Step 3. Create a URL Parser Class

This is just a simple parsing class to get the NewsletterID, UserID and IP information from the request. We can then pass the information along to the next layer (database or file processing to record the information).
using System;
using System.IO;

namespace EmailTracking { /// /// Summary description for OpenURIParser. /// public class OpenURIParser { // Constructor public OpenURIParser() {} // Do the parsing public static void Process( string pUri, string pIP) { string[] arrIDs; string country; // Create a CountryLookUp instance by specifying // the location of the GeoIP database file CountryLookUp countryLookUp = new CountryLookUp(@"C:\winnt\system32\GeoIP.dat"); try { // a valid call will be like: // "/NewsletterID.UserID.open" arrIDs = GetReqeustedFileName(pUri).Split('.'); if (arrIDs.Length == 2) { // Get the NewsletterID int newsletterID = Convert.ToInt32(arrIDs[0]); // Get the UserID int userID = Convert.ToInt32(arrIDs[1]); // Get the user’s origin by his IP country = CountryLookUp. lookupCountryCode(pIP); // Write open stats either to database or file // You need to write your own Stats class Stats.UpdateOpenStats( newsletterID, userID, countryByIP); } } catch (Exception) { // Failure in parsing request // You can write your error handling here } } // Get the file name from the request url private static string GetReqeustedFileName(string pUri) { return Path.GetFileNameWithoutExtension(pUri); } } }
Step 4. Create a CountryLookUp Class

By utilizing MaxMind’s GeoIP database, we can obtain the Country (as mentioned on their site, they can obtain Region, City, Latitude, and Longitude as well) of any IP address. This will be very helpful if we want to geo-target newsletters.

The C# API which I have ported can be downloaded at http://www.maxmind.com/app/csharp.

using System;
using System.IO;
using System.Net;

namespace EmailTracking { /// /// Summary description for CountryLookup. /// public class CountryLookup {
private FileStream fileInput; private static long COUNTRY_BEGIN = 16776960; ....
public CountryLookup(string fileName) { fileInput = new FileStream( fileName, FileMode.Open, FileAccess.Read); }
public string lookupCountryCode(string str) { IPAddress addr; try {
addr = IPAddress.Parse(str); }
catch (FormatException e) {
return "--"; }
return lookupCountryCode(addr);
public string lookupCountryCode(IPAddress addr) { ....

} }
Step 5. Register Your Custom Http Handler

Once you have your custom handler application compiled, all you are left to do is to register your handler with IIS and ASP.NET runtime.

First, add the following entries to your appplication’s web.config file:

This configuration tells the ASP.NET to handle requests with extension .open using our custom http handler.

The next step is to map the .open extension on IIS. Because IIS is the first place the user’s request will go, we need to config IIS to pass the request with .open extension to ASP.NET so then the request can reach our http handler.
Open the IIS snap-in and go to the application where you set up to host the tracking system and open the properties of this application. On the Directory tab, click the Configuration.

You can add the new extension to ‘.open’ as following:


You can see by utilizing a custom built http handler, it is so easy to build an email tracking system without much hassle. And these classes can be further extended to handle click tracking and user profiling. And as to my experience with a million-impression tracking system built on top of these classes and SQL Server, the http handler handles requests very efficiently with a very low CPU and memory usage.

Download the code!

About the Author:
Ting Huang, a senior programmer for a fast growing Minnesota based online marketing company and spends most of his time deep in system architect, ASP.NET and SQL Server.


About the Author, Staff

You can write for Santry.com, just email us at [email protected] for more information.

blog comments powered by Disqus


Thank you for visiting our site, before you leave, please visit some of the areas or information you may have missed.

Popular Articles