DIY A/B Split Testing Using PHP and MYSQL

I was recently working on a landing page for a client that prompted visitors to fill out a quick survey. The page looked pretty nice and invited visitors to click a button that launched the survey inside of a modal box. That seemed good enough, but the next day, I couldn't get the idea out of my head to just embed the survey right on the page without the need for another click or the need to scroll inside of the modal box. After consulting with my art director. It was obvious that the modal box method was more aesthetic, but... Which way actually worked better to get the survey filled out? I immediately thought of doing an A/B split test to find out. The trouble was, I needed it for free. A quick Google search revealed a couple free services but, they proved to be unusable for me. One service seemed like they weren't done building it yet and needed javascript files included and I didn't really want that and couldn't get it to work anyway. Google's method seemed fairly straightforward but, Google needed unique URL's to work properly. My page needed to swap content without using alternate URL's because 1.) I only want to track traffic on one page. 2.) I have tools to share the page on Twitter and Facebook and don't want two URL's floating around the social universe. So I made my own way to do it and I'm going to share that with you. And go easy on me. This is the first tutorial I've ever tried to make.

The Tutorial

You will need:

  • PHP
  • MYSQL
  • Cookies (for tracking)
  • Chocolate Chip Cookies (for noms)

The database

I tried to keep it as simple as possible because I didn't plan on distributing it, but oh well. There are three tables. One for tracking which option was served last and the campaign. One for tracking the amount of visitors and which option they saw. And one for tracking conversions and which option converted.

CREATE TABLE `ab_tests` (
`test_id` int( 10 ) NOT NULL AUTO_INCREMENT ,
`title` varchar( 100 ) NOT NULL ,
`last_option` varchar( 100 ) NOT NULL ,
PRIMARY KEY ( `test_id` )
);

CREATE TABLE `ab_tests_visitors` (
`visitor_id` int(10) NOT NULL AUTO_INCREMENT,
`test_id` int(10) NOT NULL,
`option` varchar(100) NOT NULL,
`visits` int(10) NOT NULL DEFAULT '1',
PRIMARY KEY (`visitor_id`)
);

CREATE TABLE `ab_tests_conversions` (
`conversion_id` int(10) NOT NULL AUTO_INCREMENT,
`test_id` int(10) NOT NULL,
`option` varchar(100) NOT NULL,
PRIMARY KEY (`conversion_id`)
);

Important: You'll need to manually enter in the first row of the ab_tests table because you'll have to reference the test_id and the last_option field values in your PHP to follow.

The PHP

Now for the fun part. Let's pretend that the file you're running the test on is named ab_test.php. The conversion form could be on the same page if you needed it to be, but I had it on a second file so that's what we're doing. Let's call it conversion.php. That's fitting. I'm going to assume you're already connected to your database by whatever method and skip writing all that code out. Just don't forget to do it if you're not. Let's say that you want to test an image just to keep the tutorial simple. So, the first thing is to define your content options.

<?php
$content
['a'] = '/images/image_1.png';
$content['b'] = '/images/image_2.png';
?>

Next, we process how to choose which option gets served. This is block1.

<?php
// this is from the row you made in ab_tests
$test_id = 1;

$switch = mysql_fetch_assoc(mysql_query("SELECT * FROM ab_tests WHERE test_id = '$test_id' "));

// set which option to display
if ($switch['last_option'] == 'b' ) {
   
$option = 'a';
} else {
   
$option = 'b';
}

// update the database to switch the option for the next visitor
mysql_query("UPDATE ab_tests SET last_option='$option' WHERE test_id = '$test_id' ");

// record the current visitor
mysql_query("INSERT INTO ab_tests_visitors VALUES ('NULL', '1', '$option', '1')");
$visitorID = mysql_insert_id();

// set a cookie with the option served and the visitor id that expires in 30 days
$cookie_name = 'ab_test_image';
$cookie_value = $option.'-'.$visitorID;
$cookie_expire = time()+60*60*24*30;
setcookie($cookie_name, $cookie_value, $cookie_expire, '/', '.example.com');
?>

That works pretty good but, we don't want visitors to see a different option every time they come back to our page. So, using that cookie we set, we can find out which option they looked at and make sure they get the same one again. This also gives us a chance to track returning visitors separate from repeat visitors.

<?php
if (isset($_COOKIE['ab_test_image'])) {
   
// break up the information in the cookie
   
$cookie_info = explode('-', $_COOKIE['ab_test_image']);

   
// retreive the number of times visited and add this time to it
   
$visits = mysql_fetch_assoc(mysql_query("SELECT visits FROM ab_tests_visitors WHERE visitor_id = '$cookie_info[1]' "));
   
$visits = $visits['visits'] + 1;

    if (
$cookie_info[1] &gt; 0) {
        @
mysql_query("UPDATE ab_tests_visitors SET visits='$visits' WHERE visitor_id = '$cookie_info[1]' ");
    }

   
// set which option should be displayed
   
if ($cookie_info[0] == 'a' ) {
       
$option = 'a';
    } else {
       
$option = 'b';
    }
} else {
   
// block1 goes here
}
?>

The last thing is to echo the option into the HTML. That should look something like this;

<img src="<?php echo $content[$option]; ?>" />

or this;

<?php
echo '<img src="' . $content[$option] . '" />';
?>

Finally, we need to know which option converted the best. In the other file I mentioned, conversion.php, we'll need to retrieve that cookie we set while the visitor was at ab_test.php.

<?php
// don't forget the test id
$test_id = 1;

if (isset(
$_COOKIE['ab_test_image'])) {
   
// break up the information in the cookie
   
$cookie_info = explode('-', $_COOKIE['ab_test_image']);
   
$option = $cookie_info[0];
   
   
// insert the option converted on into the database
   
mysql_query("INSERT INTO ab_tests_conversions VALUES ('NULL', '$test_id', '$option') ");
}
?>

That should do it! I hope this tutorial was helpful. I've been experimenting with tracking the date visitors hit the page but, I left that out to keep things simple. With the information gathered by this script, it should be fairly easy to build analytic reports. I'd like to build it into a function at some point to make implementation easier. If you have suggestions to make this even easier or better. I'd love to hear them.