ASP.NET - how to track if email is opened or read!

During our web application development, we often get requirement to track the email being sent from application has been read by receiver or not. It can be achieved in html emails by sending a small image called beacon or web bug in email body. Here is how it works:

  1. We'll have a dynamic page (beacon.aspx), which outputs a single pixel gif image (Response Content type = "image/gif")
  2. Application will inject <img /> tag in html email body with source image as the above page. (<img src="http://www.yoursite.com/beacon.aspx?emailId=xxx")
  3. When receiver opens the email, the email client will render image in the body which sends request to above url to get byte content of image
  4. In beacon.aspx page, we'll read the querystring of the request, which let us know which email was opened.

Code for Web Form (beacon.aspx)

protected void Page_Load(object sender, EventArgs e)
{
    // check if-modified-since header to determine if receiver has requested the image in last 24 hours
    if (checkIfRequested(this.Context.Request))
    {
        //receiver had already requested the image, hence send back a not modified result
        Response.StatusCode = 304;
        Response.SuppressContent = true;
    }
    else
    {                
        int emailId = 0;
        if (!string.IsNullOrEmpty(Request.QueryString["emailId"]) && int.TryParse(Request.QueryString["emailId"], out emailId))
        {
            //The email with emailId has been opened, so log that in database
        }

        //Send the single pixel gif image as response
        byte[] imgbytes = Convert.FromBase64String("R0lGODlhAQABAIAAANvf7wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==");
        Response.ContentType = "image/gif";
        Response.AppendHeader("Content-Length", imgbytes.Length.ToString());
        Response.Cache.SetLastModified(DateTime.Now);
        Response.Cache.SetCacheability(HttpCacheability.Public);
        Response.BinaryWrite(imgbytes);
    }
}

private bool checkIfRequested(HttpRequest req)
{
    // check if-modified-since header to check if receiver has already requested the image in last 24 hours
    return req.Headers["If-Modified-Since"] == null ? false : DateTime.Parse(req.Headers["If-Modified-Since"]).AddHours(24) >= DateTime.Now;
}

 

Append following html in html email body

Make sure to use full website+page url in src and xxx has to be replaced by unique identifier of each email.

<img src="http://www.yoursite.com/beacon.aspx?emailId=xxx" width=1 height=1>

Comments (1) -

Loading