Friday, October 2, 2015

Tracking Visitors from Ads with Express Middleware

I'm getting ready to run another month of promotion for Amphibian.com. This time I'll be running an ad on TopWebcomics.com, a webcomics list and voting site.

The best list of active web comics, including mine!
Unlike before, when I ran ads on Facebook, I'd like to get a better idea about how people interact with the site after coming from an ad banner. This is sometimes called conversion tracking, but since I'm not really trying to convert any clicks to purchases I'm not sure the term applies. I am trying to convert people to regular readers of the comic, so maybe it does. In any case, I added a piece of middleware to my Express web app in order to track visitors from ads.

Amphibian.com is built using Node with the Express framework. I use various Express middlewares to add features to the site, such as access control, logging, multipart uploads, etc. I've written quite a bit about these in the past (here, here, and here, for example). I wrote a custom middleware and modified my logging middleware in order to create this ad tracking feature.

Here's how it should work... I create my ad banner and give it to a site to display, along with a URL. Instead of just plain http://amphibian.com, I assign each ad its own unique code and append that to the URL as part of the query string. For example, I tell TopWebcomics that I want my ad banner to link to http://amphibian.com/?s=abcdefg. When I see a value for s (I use "s" for "source") on the query string of any comic access, I add the value (abcdefg in this example) to the request object in a special field. Then in my logger, I look for a value in that field and write it to the database along with the rest of the request data. Now I'll be able to query my database later and determine which accesses originated with a user clicking on the banner. If I ran more than one banner at a time, I could just give them each a different code and compare their performances.

My tracker middleware looks like this:

module.exports = function() {

    var tracker = function(req, res, next) {

        var src = null;

        if (req.query.s) {

            src = req.query.s;
            res.cookie("s", src, { maxAge: 2629746000 });

        } else if (req.cookies.s) {

            src = req.cookies.s;

        }

        if (src !== null) {
            req["click-source"] = src;
        }

        next();

    };

    return function(req, res, next) {
        tracker(req, res, next);
    };

};

The code is fairly simple. First I check the query string for an s field (line 7). If present, I set the source code variable to its value and set a cookie with the same value. The cookie has an expiry time one month in the future. If the request does not have a s value in the query string but does have the cookie value, I set the source code variable from the cookie. This is how I know if you come back to the site later without clicking on the ad - you'll have the cookie. As long as you clicked on the ad once, I count the ad as being the source of all your visits for the next month.

The source code gets put on the request object in a field called "click-source" there on line 19. This is the field that I check in the logger middleware and, if found, write to the database.

One final note about using this middleware. Since it relies on the cookie-parser middleware to populate the request's cookies field, I have to make sure that I set my Express app to use the cookie-parser first. Express chains the middlewares together in the order they are declared.

var cookieParser = require('cookie-parser');
var adTrack = require('./sourceTracker');
var logging = require('./logger');

// ... other stuff ...

app.use(cookieParser()); // required before source tracker
app.use(adTrack());
app.use(logging());

// ... other stuff ...

So my plan for tracking conversions is simple, and only took a few minutes to implement. After I run this ad for a month I'll be sure to write up my results and what, if any, improvements I want to make for the next time I try a promotion. Until then, keep reading the comics by clicking on the link below.

Amphibian.com comic for 2 October 2015