Running on-page A/B testing in-house with Google Analytics

While I’m aware of tools like Optimizely, I wanted to run A/B tests on my site without having to use an external tool to run the modifications. The main reason for not using Optimizely or another off-the-shelf software was because I didn’t want to load their javascript on my site. Besides, I wanted complete control over how I wanted to render those variations. I then came across Google’s guide to running content experiments using google analytics with Javascript to create on-page variations.

Check if PHP session has already been started

One of the challenges I came across is trying to figure out if a PHP session has already been started. I have an admin section on my site which operates using a PHP session. For the rest of the site, I wanted to display an “admin toolbar” if an admin was logged in. However, I did not want to call start_session on every page because that would initialize unnecessary sessions (hence using up resources on my server every time someone viewed a page). I only wanted to call session_start if a session was started/initialized in the admin portion of the site.

Turns out the solution is very simple. A typical setup of PHP sessions uses cookies to store the session ID on the person’s computer. All we need to do is check to see if this cookie is set on someone’s computer. If it is, call session_start () and check to see if the person has a successful login in the admin.

if (isset ($_COOKIE[session_name ()])) {
    session_start ();
    if (isset ($_SESSION['logged_in'])) {
        echo "You are an admin!";
    }
}

Of course in our admin section, we’d set the session variable $_SESSION[‘logged_in’] if there was a successful admin login.

Using MySQL with mod_rewrite

I recently wrote a custom program to handle URL rewrites and used the RewriteMap directive to make mod_rewrite use my program. I wrote it in PHP and use MySQL as a back-end to store rules. I just wanted to share one of the problems I had: MySQL drops the connection to my program and therefore a default URL is returned every time. Here is the gist of my code:

#!/usr/bin/php
<?php
    // start the code...
    // connect to MySQL...

    // open standard input and get URLs
    $fd = fopen ("php://stdin", "r");
    while (!feof ($fd)) {
        $input_url = trim (fgets ($fd));    // get a line from STDIN
        // ... construct query and send it to mysql ...
        mysql_query (... your query here ...);
        // ... get result and send back rewritten URL
        print $rewritten_url . "n";
        flush ();
    }

    // ... end mysql connection, and program ...
?>

The above code worked well, except there was one problem: it would work for a while, and after a long period of inactivity, it’d stop working. Keep in mind that I was developing this under a test server, which was not live to the public. So inactivity here was due to the fact that I’d only work daytime and at night no one would be accessing the server, and when I use the site the next day, the URL re-writer would stop working (i.e. my program would return a default, not-found URL).

At first I thought there was a problem with mod_rewrite, but then I realized that when the server is inactive, MySQL drop the connection to my program so all the SQL queries fail the next day after that inactivity, forcing me to reload the httpd server. This happens because mod_rewrite opens a persistent connection to the program and every time it gets a URL matching your parameters, it send it to the STDIN of the program and gets a URL out. So at night when the server is inactive, there are no queries run against MySQL and therefore that MySQL connection is dropped (I have my MySQL server drop connections after 3600 seconds of inactivity).

To fix this problem, I added a couple extra lines of code inside the main while loop. I’m basically checking to see if my connection with MySQL is still alive, and if it isn’t, then re-connect.

while (!feof ($fd)) {
    $input_url = trim (fgets ($fd));    // get a line from STDIN
    if (!mysql_ping ($mysql_link)) {
        // ... reconnect to mysql server ...
        $mysql_link = mysql_connect (... parameters ...);
    }
    // ... now we can run our query knowing that we have a connection to mysql,
    // even after long periods of inactivity ...
}

Keep in mind that if you have a busy website, or if your MySQL server keeps connections open for a long time, then you don’t need to worry about reconnecting. But if you’re working on a development or test site, or just don’t get a lot of visitors, this is something you need to considering coding into your program. Lastly, don’t forget to reload your httpd server after modifying your program.