One well-known hack to pull a bit more ROI out of your campaigns, particularly mobile and pops, is to remove your tracking once you have the campaign dialled in, and just run traffic straight to the lander.
That means that you get a faster response time from your campaign, which reliably increases ROI, often by quite a lot. But on the downside, you can't optimise very effectively if at all - you're running blind.
What if you could get all the data you'd normally expect from tracking, keep split-testing landers, but also get the speed of just running traffic straight to the lander with no redirects or other code?
Well, you can. And this post shows you how.
What You'll Need To Use This Technique
You know how my tutorials tend to say "don't worry, anyone can follow this!"?
Well, this post ain't like that. This is definitely an advanced tutorial, and I'd expect that experienced affiliates with reasonably large-scale campaigns will be the ones who will get the most out of this technique.
If you're just starting out, I strongly recommend that you do not mess with this stuff unless you're already extremely techie. You have bigger fish to fry and rolling your own complex non-standard tracking systems at an early stage is a really big distraction.
On the other hand, if you're experienced and looking for an edge, and particularly if you have a profitable campaign or five that you'd like to maximise ROI on, this post is for you.
You will need to have or be a sysadmin to implement this approach, and there's a certain amount of programming and/or database work involved. Experienced affs should be able to hire someone on oDesk to implement most of this in a couple of days. Porting the stats into your tracker of choice is likely to be the hard bit.
This technique is currently only usable on a single server, not a CDN. There's probably a way to get it working with at least some CDNs, but I haven't got there yet.
You're also going to need a new server or an existing server dedicated to just one set of campaigns for this trick, because it involves recompiling your Web serving software.
Finally, your traffic source must be able to send a unique parameter with each click. On Decisive, this would be Bidhash. On Zeropark, it would be cid. Etc, etc. If you can't get a unique parameter from your traffic source, this approach won't work without some additional hacking.
So How Does This Miracle Work?
Web servers log all the pages that they serve to "log files". This data can be set to be comparable to the data that your tracker collects, albeit in a much less useful form. However, because your web server isn't written in a slow language like PHP and isn't talking to a database, the log file writing process is much, MUCH faster than tracking.
When you remove tracking and use just an "untracked" server, that server is almost certainly still writing these log files.
Back in the day before Google Analytics all web analytics was done by having programs go through those files, extract the relevant data and present it in a usable form. What we're doing here is going back to that approach.
Specifically, we're going to use the web server "nginx". Nginx is well-known for being incredibly fast and stable at serving "static" files (no PHP, just Javascript and HTML). It's no exaggeration to say that a 512Mb server running nginx can happily cope with a million clicks a day with double-digit millisecond response times.
We're also going to use a couple of little-known features of nginx to allow us to continue split-testing landing pages, as well as allow us to redirect to offers much faster than we usually can with tracking.
Technical Summary Of My Approach
We recompile nginx to allow us to use the Random Index function ( http://nginx.org/en/docs/http/ngx_ht...ex_module.html ), enable this, and also enable Server-Side Includes ( http://nginx.org/en/docs/http/ngx_http_ssi_module.html ) on our server.
Nginx SSIs are way more powerful than most people realise, and are key to doing this efficiently.
We put all the landers we want to split-test in a single subdirectory under our web directory. The Random Index function will rotate between them randomly whenever someone arrives at the URL of that subdirectory.
Then we set up a custom log file format for nginx, which takes all the GET parameters from the incoming URL and stores them as comma-seperated values - IP,date,placement,device,carrier,os,unique_click_i d,lander, for example. We use nginx's $uri variable to pull the lander filename so that we know which of the landers that we're split-testing was used.
We add the unique click ID to the end of our offer URL as a GET parameter in the landing page by using nginx SSI variable echoing ( http://nginx.org/en/docs/http/ngx_ht....html#commands ) and send clicks to /offer/ on our server.
Then we set up an nginx rewrite redirect ( http://nginx.org/en/docs/http/ngx_ht...te_module.html ) to redirect /offer/ to our offer URL. That means that clicks to the offer are logged, with the unique click ID we added above, to our custom tracking log.
We add our URL to our traffic source, using the GET arguments we've already set up in the custom log format, and direct it at the subdirectory where our landers are stored.
Now we're capturing all the information we need for tracking. All that remains is to take our tracking log and load it into our tracker of choice. I demonstrate a simple way to load it into a SQLite database and query it for basic tracking info below, but it wouldn't be much harder to load the data into Prosper, CPVLab,
Visitors click through our ad and are sent directly to a randomly-chosen landing page. Meanwhile, nginx logs all their details including their unique click ID. When they click through to the offer, that clickthrough is registered as a click on the /offer/ page, again with their unique ID, and they're sent off to the offer page. Finally, when they convert, their unique ID is registered on the affiliate network as their subid, and we can load that data into our database at a later date.
Step-by-step How To Do It
If you're hiring someone, this is the bit to tell them to follow!
Step 1: Compile Nginx
On your server, compile nginx from the latest source with the --with-http_random_index_module flag set. Here's the guide I follow when I'm compiling nginx on Ubuntu: https://www.rackspace.com/knowledge_...nx-from-source . Note that you'll need to install a whole pile of dependencies if you're doing this on a fresh server, particularly given you're using http_random_index_module - I started with apt-get update and upgrade, then installed make, build-essentials, PCRE and zlib1g-dev . After that it successfully compiled.
Step 2: Configure Nginx
You'll need to enable random-index and ssi in your location section of your nginx config:
ssi on; random_index on;
log_format tracking '$remote_addr,$time_local,$arg_placement,$arg_model,$arg_carrier,$arg_OS,$arg_bidhash,$uri,';
access_log logs/access.log combined; access_log logs/tracking.log tracking;
rewrite ^/offer/ OFFERURL;
/offer/?uid=<!--# echo var="arg_UID_ARG_NAME" -->
CREATE TABLE tracking(ip text, time text, placement text, moodel text, carrier text, os text, bidhash text, lp text, clickthrough bool, converted bool);
.separator "," ..import tracking.log tracking
update tracking set clickthrough="true" where bidhash in (select bidhash from tracking where lp="/offer/");
select count(*) from tracking where lp="/index2.html" and clickthrough="true";
Another epic thread Caurmen! Will you EVER run out of these brilliant thread ideas?
Thanks so much for this! Bookmarked!
Amy
I've been using something similar because there weren't any mobile trackers back in the day.
By this time it has evolved into a monstrous beast that laughs in the face of tracking URLs.
@vortex - Can't speak for "brilliant", but I've got a good list - many requested by STM users - to be going on with
Thanks - glad it's useful!
@homp - cooool. Would you be up for sharing any of the evolutions and improvements it's gone through from this basic idea? I'd be very interested to hear them!
Running a campaign without tracking is like driving a car blindfolded - sooner or later you'll crash. Seeing the results of your campaign is absolutely necessary to drive ROI, optimize the campaign and scale it up. I would always recommend to fully track any campaign before launching it
@h0mp - that's seriously fascinating - thanks. The peasant advertiser detector is a particularly good idea, and one I might have to look into coding myself...
@katim777 - Ouch! Yeah, that's definitely too slow, particularly for pops. I'd recommend looking into some different CDNs or hosting on a single server there.
If you reduce loading time, I almost guarantee that your CTR will go up, probably by quite a bit. Here's a case study I did a while ago on loading times for pops: http://stmforum.com/forum/showthread...hlight=loading
Nice Caurmen,
Have read conversation about this and adding on my whishlist
but you already brought it here!
Thanks
Amazing guide!
I did a lot of tests with different redirects, and the amount of clicks lost on mobile through redirects is incredible. (and I'm not only talking about those you're in control of)
@h0mp : Wow thanks for the details , looks great - have you tried any split-tests to see how better your systems performs compared to for example
@katim777 - hmm, that's a serious issue. Could you start a separate thread on it so we can go into more depth?
@h0mp - YIKES. Oh, advertisers, why do you try us so? Nothing more annoying than working to get a super-slick, super-fast lander and then have the advertiser make a design change that adds 15s to their offer load time...
This is some silicon valley shit right here...