How to store billing address information from the s2member plugin

s2member logos2member, the membership plugin we use on Smart Insights, doesn’t store the billing address entered when people purchase memberships or products. I needed a way to be able to get access to that information, and here’s the solution I figured out.

Why doesn’t s2member store billing address information?

Storing cardholder data such as billing address and credit card number is not secure, and puts you in a tricky situation in terms of your site’s PCI Compliance. To avoid this, s2member just passes this information straight onto your payment gateway of choice (in our case this is PayPal) and does not store it locally. It goes without saying that you should NEVER store any credit card details in the WordPress database.

Why would you need to store billing address information from the s2member plugin?

For us, there are two reasons to have access to this information;

1) We want to be able to send billing address (not credit card details) to our CRM/marketing automation platform

We have a marketing automation platform called Office Auto Pilot which runs our email and other marketing activities. It also acts as our customer relationship management (CRM) platform. Not having a member’s address and country details in this is a pain – we’re unable to segment our communications on geographical area, which is lousy when we have members in 50 different countries paying different prices in different currencies.

2) We want our members to be able to see what they’ve purchased previously, and print invoices

s2member doesn’t currently provide any functionality for generating invoices from within WordPress, or allowing members to see what they’ve paid in the past. Relying on PayPal to send receipts to our members isn’t sufficient – many require tax invoices with a letterhead, and at present that means we have to manually create an invoice. As we grow and the volumes increase, this is taking too much time.

How do we store billing address information in the s2member plugin?

s2member comes complete with hundreds of hooks and filters which allow you to attach your custom code to its functionality. Unfortunately (and sorry for saying this s2 guys as the plugin is otherwise exceptional) the documentation is practically non-existent. So you’re left with visiting the API reference and trying to figure out what does what, where and when by trial and error.

After a lot of messing around, I discovered that the action ws_plugin__s2member_during_configure_user_registration_front_side_paid is fired just after someone submits the PayPal payment form, which of course contains the billing address fields.

In order to access this information, you must first create a MU (must-use) plugin in your WordPress installation. These are plugins that WordPress will load automatically. There’s good documentation on creating an s2member MU plugin on the s2member site, so I’ll assume you’ve gone and done that and are now ready to continue.

In order to grab the billing information from the payment form, use the following function and action:


// This function will grab the user street, city, state, country and zip billing address fields and save them as user meta.

add_action('ws_plugin__s2member_during_configure_user_registration_front_side_paid', 's2_grab_fields_from_form');
function s2_grab_fields_from_form($vars = array()) {

update_user_meta( $vars['user_id'], 'billing_street', $_POST['s2member_pro_paypal_checkout']['street'] );
update_user_meta( $vars['user_id'], 'billing_city', $_POST['s2member_pro_paypal_checkout']['city'] );
update_user_meta( $vars['user_id'], 'billing_state', $_POST['s2member_pro_paypal_checkout']['state'] );
update_user_meta( $vars['user_id'], 'billing_country', $_POST['s2member_pro_paypal_checkout']['country'] );
update_user_meta( $vars['user_id'], 'billing_zip', $_POST['s2member_pro_paypal_checkout']['zip'] );

}

Now, I put the example above to show you how the $vars parameter also contains the WordPress user_id of the person who just purchased a membership, which allows you to store this (and indeed any other information in either the $vars or $_POST arrays) as user_meta. But I stress here that just because you can, doesn’t mean you should. In my case I send the billing address information straight off to our CRM system via an API call, and do not store them locally at all. I would strongly recommend you do the same.

Hope that helps someone else save some time instead of trawling the internet for hours looking for a way of storing billing address information from s2member.

Implementing Google Universal Analytics Measurement Protocol in PHP and WordPress

Google Universal AnalyticsI’ve had some historic difficulty in being able to track ecommerce transactions in Google Analytics that happen ‘behind the scenes’ of the Smart Insights site – typically when PayPal sends an IPN message, server to server, for a subscription renewal in our case. Since those messages don’t touch the browser, you can’t use the Google Analytics javascript to track them. So I started looking to see how/if I could send data directly to Google Analytics from a backend script running on our WordPress install.

I found several custom PHP classes that seemed, initially, to do the trick;

Problem is, they’re both pretty old and seem to be no longer developed, so I figured there must be something better. My colleague Dave Chaffey then pointed me in the direction of the Google Measurement Protocol, which I hadn’t heard of before.

What is the Google Measurement Protocol and why should I care?

The Measurement Protocol is an addition to the latest version of , which is called ‘Universal Analytics’. From the explainer documentation;

The Google Analytics Measurement Protocol allows developers to make HTTP requests to send raw user interaction data directly to Google Analytics servers. This allows developers to measure how users interact with their business from almost any environment.

More at ‘‘

Google allows you to form and send any of the following types of Analytics request via this API;

  • Page Tracking
  • Event Tracking
  • Ecommerce Tracking
  • Social Interactions
  • Exception Tracking
  • User Timing Tracking
  • App tracking

Using the Google Measurement Protocol in PHP and WordPress

NOTE:  You can only use the Measurement Protocol if you have the Universal Analytics tracking code set up on your site. It will not work with the standard tracking code. If you need help with this, there’s a fantastic introduction at the KissMetrics site: Universal Analytics: Switching to the Next Version of Google Analytics

As is typical with Google and ‘beta’ products (as the Universal Analytics code is still in beta) they give pretty sparse examples and no specific code, so it’s up to you to work things out yourself.

In my case I wanted to be able to fire two types of requests to Google – an ecommerce transaction when a membership renewal occurs, and a custom pageview which is used as a ‘‘ on Analytics.

As I wanted the code to be reusable throughout the WordPress install, I came up with a set of functions (mine lives in a function file of its own, yours could live in your standard theme functions.php file if you wish).

There are two steps needed to make a request to the Measurement Protocol.

1. Obtain the current user’s unique identifier (CID) from the Google Analytics cookie (if it exists!)

Very vital, this, and something I ended up banging my head on the desk about. When a user lands on your site, the Google Analytics code assigns them a unique identifer. This lives in a cookie, and follows them across all requests they make on your site. If you fire a server side request and make up your own unique identifier, the Analytics service has no way of matching the two up.

Obviously this isn’t a problem in my original use case – a behind the scenes ecommerce renewal won’t have a browser cookie to get anything from, and it doesn’t matter that you assign it a unique identifier all of its own. But – if you decide to use the Measurement Protocol for other things, front of site (and I did within 10 minutes of finishing my first code), then you do need to check for the existence of that cookie first. If you don’t, a user that has logged page history will suddenly become anonymous when you fire your Measurement Protocol request. This means that things like conversion funnels won’t work, which is not good.

So, here’s how we parse the GA cookie;

// Handle the parsing of the _ga cookie or setting it to a unique identifier
function gaParseCookie() {
  if (isset($_COOKIE['_ga'])) {
    list($version,$domainDepth, $cid1, $cid2) = split('[\.]', $_COOKIE["_ga"],4);
    $contents = array('version' => $version, 'domainDepth' => $domainDepth, 'cid' => $cid1.'.'.$cid2);
    $cid = $contents['cid'];
  }
  else $cid = gaGenUUID();
  return $cid;
}

This code will pluck the CID value from the cookie if it exists. If not, it runs another function to generate one – gaGenUUID(). The Measurement Protocol documents say that the CID must “be a random UUID (version 4) as described in http://www.ietf.org/rfc/rfc4122.txt“. Ah, okay. So let’s create one of those, then;

// Generate UUID v4 function - needed to generate a CID when one isn't available
function gaGenUUID() {
  return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
    // 32 bits for "time_low"
    mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),

    // 16 bits for "time_mid"
    mt_rand( 0, 0xffff ),

    // 16 bits for "time_hi_and_version",
    // four most significant bits holds version number 4
    mt_rand( 0, 0x0fff ) | 0x4000,

    // 16 bits, 8 bits for "clk_seq_hi_res",
    // 8 bits for "clk_seq_low",
    // two most significant bits holds zero and one for variant DCE1.1
    mt_rand( 0, 0x3fff ) | 0x8000,

    // 48 bits for "node"
    mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
  );
}

So, we now have a CID that we can use.

2. Build and send our Measurement Protocol request

There are two functions used here – one to build the request, the other to send it. In both cases you call gaBuildHit() with two parameters – the method (which in my example is either ‘pageview’ or ‘ecommerce’) and an array of data that is needed by the Measurement Protocol. This differs depending on the method you’re using, so let’s jump into the code and I’ll explain more afterward.

function gaBuildHit( $method = null, $info = null ) {
  if ( $method && $info) {

  // Standard params
  $v = 1;
  $tid = "UA-XXXXXXX"; // Put your own Analytics ID in here
  $cid = gaParseCookie();

  // Register a PAGEVIEW
  if ($method === 'pageview') {

    // Send PageView hit
    $data = array(
      'v' => $v,
      'tid' => $tid,
      'cid' => $cid,
      't' => 'pageview',
      'dt' => $info['title'],
      'dp' => $info['slug']
    );

    gaFireHit($data);

  } // end pageview method

  // Register an ECOMMERCE TRANSACTION (and an associated ITEM)
  else if ($method === 'ecommerce') {

    // Set up Transaction params
    $ti = uniqid(); // Transaction ID
    $ta = 'SI';
    $tr = $info['price']; // transaction value (native currency)
    $cu = $info['cc']; // currency code

    // Send Transaction hit
    $data = array(
      'v' => $v,
      'tid' => $tid,
      'cid' => $cid,
      't' => 'transaction',
      'ti' => $ti,
      'ta' => $ta,
      'tr' => $tr,
      'cu' => $cu
    );
    gaFireHit($data);

    // Set up Item params
    $in = urlencode($info['info']->product_name); // item name;
    $ip = $tr;
    $iq = 1;
    $ic = urlencode($info['info']->product_id); // item SKU
    $iv = urlencode('SI'); // Product Category - we use 'SI' in all cases, you may not want to

    // Send Item hit
    $data = array(
      'v' => $v,
      'tid' => $tid,
      'cid' => $cid,
      't' => 'item',
      'ti' => $ti,
      'in' => $in,
      'ip' => $ip,
      'iq' => $iq,
      'ic' => $ic,
      'iv' => $iv,
      'cu' => $cu
    );
    gaFireHit($data);

  } // end ecommerce method
 }
}

// See https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
function gaFireHit( $data = null ) {
  if ( $data ) {
    $getString = 'https://ssl.google-analytics.com/collect';
    $getString .= '?payload_data&';
    $getString .= http_build_query($data);
    $result = wp_remote_get( $getString );

    #$sendlog = error_log($getString, 1, ""); // comment this in and change your email to get an log sent to your email

    return $result;
  }
  return false;
}

Registering a pageview

Details on the parameters needed .

You need to send the code in the following way:

$data = array(
  'title' => 'Any page title you want to send',
  'slug' => '/please/change/me/to-whatever-you-want/'
);
gaBuildHit( 'pageview', $data);

Registering an ecommerce transaction

You have to send a minimum of two requests here – the first is the initial transaction, and the second is for the specific item, They’re bound together on the same ‘transaction ID’ so Analytics can match them up. Details on the parameters needed .

Please note – if you have multiple line items, my code doesn’t accommodate that as we only ever have one. You’ll need to amend the code to loop over the items and send them all.

You need to send the code in the following way:

$data = array(
  'info' => array ('product_id' => 102, 'product_name' => 'Smart Insights membership' ), // we already have these details in an array so send that, you may want to amend
  'cc' => 'GBP', // the currency code
  'price' => 209.00, // the price
  'country' => GB // the country ISO code
);
gaBuildHit( 'ecommerce', $data);

Some things to be aware of

  1. If you choose to take a peek at what is returned from the API after a request, you’ll be surprised to learn that you only ever get a 200 response, regardless whether your request has succeeded or failed. So it’s a bit pointless, really, you can’t debug it that way
  2. If you use the Real Time view on Analytics, you will be able to see your ‘pageview’ requests appear within seconds, so you know it works!
  3. If you use the ‘ecommerce’ method, you’ll probably have to wait for 2-3 hours (like I did) before data appears, or not. Not helpful, but the code should work – at least you don’t have to start from scratch like I did! 🙂
  4. The code above is written for our site – you will more than likely have to tweak and change it to make it work for yours.

And that’s that – though it could do with some tidying (which I’ll do when I extend it further), it should be easy to add any of the other methods available on the Measurement Protocol API to these functions. Running within your WordPress install it should give a good starting point to using the server side Google Analytics Measurement Protocol in PHP and WordPress.

I’d love to hear how other WordPress developers are using the new Google Universal Analytics Measurement Protocol within their WordPress sites – let me know in the comments!

How to monitor and reduce WordPress memory usage by plugins

WordPress memory

One of the best things about WordPress is that it’s so easy to extend your site’s functionality with the many (mostly) free plugins available on the plugin repository. But loading your site with too many plugins can cause your site to consume too many resources on your server, slowing your site down. So how do you find out what resources your plugins are consuming to help you reduce WordPress memory usage and speed up your site?

Reduce WordPress memory usage by plugins

In a WordPress page request, the point at which plugins are loaded depends on how they’ve been coded. WordPress runs through a series of typical actions on every request. You can see these actions here, including the order in which they are run. A plugin developer decided where in this their plugin is needed, depending on the functionality the plugin offers, and ‘hooks’ into one of these actions, overiding or extending the default WordPress functionality with their custom code. More general information on the basics of plugin writing is available at the WordPress Codex.

So, as an example you’ve got a site that has 10 (or more!) plugins. These are firing at different times during a page request, hooking into different actions, all over the place. So how do you go about monitoring which plugins are most intensive?

As standard, there isn’t an easy way to monitor what WordPress memory usage is as it loads all of the plugins you’ve got installed on your site. But there are three plugins that in tandem, can really help you to find out what’s causing your site to slow down. Let’s look at them.

1) P3 (Plugin Performance Profiler)

Created by the in-house team at GoDaddy, the P3 (Plugin Performance Profiler) plugin allows you to run a scan over your site to determine what resources your plugins are using, and when, during a standard page request. This allows you to see the worst offenders and reduce WordPress memory usage by removing them or finding alternatives.

Once you’ve installed the plugin running a scan is easy and quick, even on a large site. Once the scan is complete you’ll see a comprehensive results report such as this;

P3 (Plugin Performance Profiler) Report
P3 (Plugin Performance Profiler) Report

The Runtime by Plugin report shows you a simple pie breakdown of which plugins are causing the most load on your site during a page request. Very useful, and a very quick way for you to identify and reduce WordPress memory usage by removing plugins that you don’t need.

Even more useful is the Detailed Timeline, which shows when the plugins are being loaded during the page request, so you can see if any particular one is causing a problem at a particular point.

Detailed Timeline of plugin load
Detailed Timeline of plugin load

Using the P3 (Plugin Performance Profiler) is a great start, but how do we get more information about what’s causing our site to slow down?

2) Memory Viewer

As the developer of the Memory Viewer plugin says;

Memory Viewer is a WordPress plugin that allows you to view WordPress’ memory utilization at several hooks during WordPress’ execution. It also shows a summary of MySQL Queries that have ran as well as CPU time.

Once installed, administrative users will see a new panel at the bottom of every page;

Memory Monitor output
Memory Monitor output

The report shows the memory usage at every major action hook, along with statistics on time and MySQL usage. You can also choose to show the queries that are happening at each hook, and output allows gives you an idea as to what code is responsible, which allows you to pinpoint exactly which ones are causing excessive load.

Generally a good indicator is when you see the ‘Current Memory Usage’ column leap up significantly from one action to the next. Any large jumps are worthy of investigation, as there could be plugins running that are the cause, or custom scripts in your theme that need optimisation. By removing or optimising these blockages, you can reduce WordPress memory usage significantly and then retest to see the effect of your changes on page load speed.

3) Debug Bar

Finally, the Debug Bar plugin offers similar functionality to Memory Monitor, but installs a panel into the WordPress admin bar. It is also extendable via other plugins to track and monitor other data such as the errors and warnings that PHP may record when you have the WordPress debug, WP_DEBUG, switched on.

Personally I prefere the ease and simplicity of Memory Monitor, but there’s no doubt that Debug Bar is extremely powerful.

Debug Bar output
Debug Bar output

So that’s three different, easy ways to monitor your WordPress site and find out which plugins and scripts you need to consider removing or tweaking to reduce WordPress memory usage and speed up your site.

I’d be really interested to hear what other WordPress developers use to monitor and optimise their sites.

Increasing the PHP timeout on NGINX for WordPress

wordpress-nginxI’ve been using a Vagrant development set up for a while now, which has introduced me to NGINX after always using Apache in the past. The transition has been fine in the main, though I had an issue yesterday with PHP scripts timing out on me, so needed to figure out how to extend the script execution time.

I’ve started using the excellent WP Migrate DB plugin to synch my local development environment database with the live staging server. It’s well worth spending $19 on the Pro version, by the way – it offers a lot of extra features for the small outlay.

The plugin works by you installing it on both your local and staging sites, and then authorising them to ‘see’ each other using private API keys – it’ll then push (or pull) and overwrite the database from whichever site you choose.

The problem I experienced was that the Smart Insights database is pretty large by WordPress standards – a good couple of hundred MB, and when attempting to pull this down to my local development environment I kept getting “504 Gateway Time-out” errors. Guessing it was more than likely a local timeout issue, I looked around on increasing the PHP timeout on NGINX for WordPress.

Depending on how you’re using NGINX, the answer is that you may have to change a few different things.

NB: I’m using Jeremy Felt’s ‘Varying Vagrant Vagrants’ setup here, so the instructions are specific to that, though I’ll include the default locations too.

Increasing the PHP timeout in the php.ini file

If using ‘Varying Vagrant Vagrants’;

  1. Open your vagrant-local folder root
  2. Open config/php5-fpm-config/php.ini
  3. Change the following line to the length of time you want (in seconds)
max_execution_time = 500

If using a standard server setup the instructions are the same, but the path will generally be /etc/php5/fpm/php.ini.

Increasing the PHP timeout in PHP-FPM

If using ‘Varying Vagrant Vagrants’ without changes, you don’t need this step, but best to check;

  1. Open your vagrant-local folder root
  2. Open config/php5-fpm-config/www.conf
  3. Change/add the following line to the length of time you want (in seconds)
request_terminate_timeout = 500

If using a standard server setup the instructions are the same, but the path will generally be /etc/php5/fpm/pool.d/www.conf.

Increasing the PHP timeout on NGINX config

If using ‘Varying Vagrant Vagrants’ without changes, you shouldn’t need this step either;

  1. Open your vagrant-local folder root
  2. Open config/nginx-config/nginx.conf
  3. Change/add the following line inside the existing http{} section, to the length of time you want (in seconds)
http {
#...
fastcgi_read_timeout 500;
#...
}

If using a standard server setup the instructions are the same, but the path will generally be /etc/nginx/nginx.conf.

Restarting PHP and NGINX

Don’t forget to restart both PHP and NGINX so your changes take affect! You can do this on the command line with the following;

service php5-fpm reload
service nginx reload

After restarting, WP Migrate DB successfully migrated the database from the live staging server to my local copy – way easier than manually exporting/tranferring/importing databases manually!

Hope that helps someone save a bit of time – I’d be interested in knowing what other people think of NGINX in comparison to Apache – let me know!

Sending your own output to the WordPress debug log

Every WordPress developer knows how to use WP_DEBUG in the wp-config.php file to enable the WordPress debug log. But how do you go about sending output to the WordPress debug log, so you can debug your own code while developing a theme or plugin?

Every developer is familiar with using the old print_r($my_stuff); die; trick to print the contents of an array (or object) to the screen so you can make sure that your code is doing what you expect. A better way to do this is write to your own custom log file, of course, and until this week I’ve maintained a separate PHP log file and using the PHP error log function to write to this;


error_log($my_stuff, 3, "/var/tmp/my-errors.log");

I then use Console on my mac to watch this log:

Mac Console
Mac Console

While this is completely fine, in the background WordPress is busy sending output to the WordPress debug log file, which (providing you’ve enabled WP_DEBUG) lives in wp-content/debug.log. I got fed up with having two separate Console windows open to monitor these, and looked into how I could write my own output directly to the WordPress debug log. And it turns out it’s pretty easy.

Add the following code to your theme’s functions.php file;


if (!function_exists('write_log')) {
    function write_log ( $log )  {
        if ( true === WP_DEBUG ) {
            if ( is_array( $log ) || is_object( $log ) ) {
                error_log( print_r( $log, true ) );
            } else {
                error_log( $log );
            }
        }
    }
}

What this does is create a custom logging function that you can call within your code – this first checks to see if WP_DEBUG is set to true (notice the yoda condition here, you will – it’s part of the WordPress coding standards). If WP_DEBUG is switched on, the function prints the contents of $log to the WordPress error log. It doesn’t matter if you’ve populated $log with a variable, array or object – the function checks and handles those.

Whenever you need to be sending output to the WordPress debug log file in your code, simply call the new function as follows;


write_log('THIS IS THE START OF MY CUSTOM DEBUG');

write_log($whatever_you_want_to_log);

Note that I always use two lines here – the first so I can search for my custom output in Console, and the second the actual data I want to log.

Now you can simply monitor the wp-content/debug.log file  for both WordPress errors and your custom ones. Hope someone else finds that useful!

Getting the WordPress current template name in posts and pages

ManHoldingQuestionMarkYesterday I needed to selectively hide breadcrumbs for particular WordPress templates, but had some issues with getting the WordPress current template name when needed, so I thought I’d share how I went about it.

First things first – the way you go about it depends on whether you’re working with pages or posts – these are not seen as the same thing by WordPress, and it can cause some confusion. Posts include any custom post types that you may have created, by the way.

Getting the WordPress current template name for PAGES

Ordinarily when targeting a specific page, you can use is_page();

if ( is_page(*put_your_id_here*) ) {
  // Returns true when the current page is *put_your_id_here* }
else {
  // Returns false when the current page is *put_your_id_here*
}

The problem is, this requires you to put in a specific page_id. What happens if you use the same page template for multiple pages, though? You don’t want to be adding to a never ending list of IDs when you add a new page with that template, so it’s necessary to find a solution that applies to all.

A quick browse through some other code I remembered working with before brought me to the is_page_template() function;

if ( is_page_template('about.php') ) {
  // Returns true when 'about.php' is being used.
} else {
  // Returns false when 'about.php' is not being used.
}

Perfect – simply put your page template file name (including the .php) into the above, and if the function returns true, I don’t output the breadcrumbs.

Getting the WordPress current template name for POSTS

As mentioned above  – don’t forget that this includes custom post types you create – they’re all classed as posts by WordPress.

The post version of is_page() is is_single();

if ( is_single(*put_your_id_here*) ) {
  // Returns true when the current post is *put_your_id_here*
} else {
  // Returns false when the current post is *put_your_id_here*
}

Update: you can also use is_singular() to target a specific custom post type single post.

Again, though, this relies on you targeting a specific post_id. Fine if you only want to target a single post, but useless if you want to target all posts that use the same WordPress template.

In my case, I had a custom post type – Guides, and didn’t want to show the breadcrumbs on any single posts for this post type. As a result, I knew that I needed to target every post that was using the PHP template file single-guide.php – this being the template file I’ve created to override the standard WordPress single post template single.php. If you’re not sure on this – have a read of the WordPress template hierarchy – it explains how you can easily override templates depending on a range of criteria – post types, categories, taxonomies and more.

As it turns out, there’s no easy in-built function to get WordPress to know what template it’s using for posts. The solution I found on StackExchange is to put the following in your theme’s functions.php file:

// Grabbing current page template
add_filter( 'template_include', 'var_template_include', 1000 );
function var_template_include( $t ){
  $GLOBALS['current_theme_template'] = basename($t);
  return $t;
}
function get_current_template( $echo = false ) {
  if( !isset( $GLOBALS['current_theme_template'] ) ) return false;
  if( $echo ) echo $GLOBALS['current_theme_template']; else  return $GLOBALS['current_theme_template'];
}

What this does is;

  • grab the WordPress current template name when WordPress pre-processes it before outputting to the screen
  • drops this template into a global variable so you can use it throughout the site

All you need to do now is call your new get_current_template() function to  your check to see if the current template matches the one you’re looking for, in my case to exclude the breadcrumbs in my theme’s header.php file;

if ( !get_current_template() === 'single-guide.php' ) {
output_breadcrumbs(); // don't show crumbs here on guide pages
}

Hope that helps someone – if anyone knows of a better way, let me know!

Simple A/B testing in WordPress with Google Analytics site experiments

As we’re about to make some significant tweaks and changes to the main product pages on the Smart Insights site, I’ve looked at a lightweight way to do simple A/B testing in WordPress.

What is A/B testing?

You’ll probably be aware of the concept, I’m sure!

A/B testing, also called split testing or multivariate testing, involves your site randomly selecting one of several versions of a page to show to a site visitor. The aim is to find out which one is most successful at converting your visitors.

AB-Testing
What is A/B Testing?

Why do you need it?

Put simply, how do you know if the changes you made to a page are working better than the earlier version unless you can compare them side by side?

A/B testing allows you to make changes from a position of intelligence – knowing the impact of the changes you make allows you to learn what works and what doesn’t, and make sure that you repeat the successes and not the failures.

A/B testing in WordPress

After doing the usual Google searches, I discovered several A/B testing WordPress plugins, the best of which seemed to be MaxA/B. It’s a comprehensive plugin, and as a result pretty complicated.

The problem – MaxA/B seemed to me to duplicate a lot of the metrics and data capture that is really the job of an analytics tool and the fact is, mostly all of us already have a system installed on our sites that is specifically geared around telling us how our site performs – Google Analytics.

It just didn’t seem to make much sense to install something else that duplicates something I already have – so I wanted to see if there was a simpler method to allow us to use Google Analytics and without installing a plugin. I discovered that there is – and it’s provided directly within Google Analytics.

Introducing Google Site Experiments

I use Google Analytics a lot, but this particular feature has completely passed me by. Apparently it used to be a separate system called Google Content Experiments but has been merged into Google Analytics back in August 2012.

Content Experiments is a somewhat different approach from either standard A/B or multivariate testing. Content Experiments is more A/B/N. You’re not testing just two versions of a page as in A/B testing, and you’re not testing various combinations of components on a single page as in multivariate testing. Instead, you are testing up to five full versions of a single page, each delivered to visitors from a separate URL.

More at the

Great – perfect for what we wanted to do, and easy enough to make it work with WordPress on the surface. It recognises that a user is on the page that you’re wanted to experiment with, and then randomly sends them off to one of the other pages you’ve got in the experiment. As a result we can set each version of the page up as a separate page within WordPress, and add each URL to the experiment within Google Analytics.

When you set up your experiment (full instructions ) you get some javascript code that you have to add to the <head> tag of the original page of your experiment;

Create a new experiment Google Analytics
Creating a new experiment in Google Analytics

The problem is that the <head> section of every page in WordPress is served from a single PHP file – header.php. Adding the Google experiments javascript code to this means it will fire on every page, and break your site as a result. So how do we use experiments with WordPress pages? There’s an easy solution.

Outputting the experiments code on your original page only

Firstly, log in to your WordPress site as an administrator and browse to the edit screen for the original page. Once there, look in your browser’s URL bar to get the page ID from the URL.

Getting the WordPress page ID
Getting the WordPress page ID

Now fire up your favourite code editor and open the header.php file in your active theme directory. Below the first <head> line add the following code, substituting your page ID instead of ***PAGEID***, and the experiment javascript code provided by Google Analytics in place of ***GOOGLECODE***;


<?php if (is_page(***PAGE ID***) ):?>

***GOOGLECODE***

<?php endif; ?>

Simple as that! Using the is_page function allows us to surround the output of our experiment code in a conditional statement – if the current page ID matches the ID of your original experiment page, the javascript will fire and the Google experiment will work.

Once installed on your site, Google will automatically randomise which of your test pages your users see and start to measure the success of each, and depending on the length and configuration of the experiment will eventually declare a ‘winner’.

I’m keen to hear what other WordPress developers are using for doing simple A/B testing in WordPress – are you using a plugin such as MaxA/B or have you had any experience of Google content experiments?

Disable WordPress notifications email for users and admins

Stop emailI’ve just had two separate issues in two days which needed me to try to disable WordPress notifications email. WordPress sends a lot of automated email, and it’s not so easy to see how to change or suppress it.

So I thought I’d share the solutions I found in case it saves anyone else time, or indeed if I forget how I managed it the next time I come across the problem.

1) Disable the automatic welcome email sent to users

WordPress always sends users an automated welcome email, which has their username and password, in plain text. This is bad – you really shouldn’t be receiving login details in plain text emails. The reason it does this is that on most WordPress sites, the user doesn’t get the chance to put in their own password, it’s generally created by WordPress and then – you guessed it – emailed to them.

I’ll put to one side that it really shouldn’t do this on this occasion and get to the point. On Smart Insights we allow our users to create their own password on sign-up using the s2member plugin that forms the backbone of our membership (more on that here). We also use a marketing automation platform called Office Auto Pilot (which is fantastic and highly recommended) which handles the bulk of our email.

Our users were getting confused by receiving two emails when they signed up – the (poor, text only) one from WordPress containing their username and password which they already knew, and then a minute later another (proper, formatted HTML) welcome from Office Auto Pilot.

So, I found out how to switch the WordPress notification off.

The function that handles new user notification is called, surprisingly, wp_new_user_notification. And upon inspection, this function is pluggable, which means you can override it entirely via a plugin. Note – a plugin – not your theme. This code will not work in your functions.php file – it must be run from a plugin. The codex shows the following code to override the email;


// Redefine user notification function
if ( !function_exists('wp_new_user_notification') ) {

function wp_new_user_notification( $user_id, $plaintext_pass = '' ) {

$user = new WP_User( $user_id );

$user_login = stripslashes( $user->user_login );
 $user_email = stripslashes( $user->user_email );

$message = sprintf( __('New user registration on %s:'), get_option('blogname') ) . "\r\n\r\n";
 $message .= sprintf( __('Username: %s'), $user_login ) . "\r\n\r\n";
 $message .= sprintf( __('E-mail: %s'), $user_email ) . "\r\n";

@wp_mail(
 get_option('admin_email'),
 sprintf(__('[%s] New User Registration'), get_option('blogname') ),
 $message
 );

if ( empty( $plaintext_pass ) )
 return;

$message = __('Hi there,') . "\r\n\r\n";
 $message .= sprintf( __("Welcome to %s! Here's how to log in:"), get_option('blogname')) . "\r\n\r\n";
 $message .= wp_login_url() . "\r\n";
 $message .= sprintf( __('Username: %s'), $user_login ) . "\r\n";
 $message .= sprintf( __('Password: %s'), $plaintext_pass ) . "\r\n\r\n";
 $message .= sprintf( __('If you have any problems, please contact me at %s.'), get_option('admin_email') ) . "\r\n\r\n";
 $message .= __('Adios!');

wp_mail(
 $user_email,
 sprintf( __('[%s] Your username and password'), get_option('blogname') ),
 $message
 );
 }
}

Using that would allow you to tweak the welcome message to something a bit more detailed and ‘on-brand’ than the default one, which is useful info in itself. In my case though, all I wanted to do is stop it from sending the email at all. So, this did it for me;


if ( !function_exists('wp_new_user_notification') ) {

function wp_new_user_notification( ) {}

}

2) Disable the ‘user x has changed their password’ emails to the admin account

We use Help Scout for handling all of our user support, it’s simple and cheap (unlike Zendesk which from experience is neither of those) and does the job perfectly.  All emails sent by WordPress to the admin account are forwarded to Help Scout which handles them and assigns them out to support representatives. We use some of the notifications – comments and pingbacks, but we get lots of the ‘user x has changed their password’ emails, and we have to delete each support case generated by Help Scout manually. It’s annoying.

Another pluggable function to the rescue – wp_password_change_notification, which we can suppress be adding the following to a plugin – you can add this to the same plugin file you created for 1) if you like – it’ll work fine;

if ( !function_exists( 'wp_password_change_notification' ) ) {
    function wp_password_change_notification() {}
}

What about other automated emails?

Chances are there’s a pluggable function that allows you to suppress it – here’s a few more;

  • wp_notify_moderator – notifies the moderator of the blog about a new comment that is awaiting approval.
  • wp_notify_postauthor – responsible for sending comment notification emails to the post author when a reader leaves a comment

Take a look at the full list of pluggable functions at the Codex.

A WordPress local development environment with Vagrant

VagrantI’ve used XAMPP as my WordPress local development environment for the last couple of years, but as I’ve done a lot of development on the Smart Insights site recently, it’s been frustrating me that my development environment doesn’t match with the live server. So I started looking into alternative solutions.

I’ve recently migrated Smart Insights to Synthesis after considering most of the premium WordPress managed hosting companies such as WPEngine and Pagely. Synthesis run their platform on virtualized server instances running NGINX with a configuration tailored specifically toward speeding up WordPress. It’s fast – blindingly so if you use the custom W3 Total Cache rules they give.

Meanwhile, XAMPP is standard PHP/mySQL running on Apache. No optimisation for WordPress. No specific configuration for caching or anything else.

What this means is that I’m developing locally on a system that’s completely different to the live server, which isn’t a great idea. Chances are at some point, something that seems to work completely fine on my WordPress local development environment will fail to work on the live server when I launch. Not often, of course – WordPress pretty much runs on anything. But if you can negate the risk of it happening by mirroring the live server on your local development environment, it makes sense that you should!

A better solution for WordPress local development environments

A few months ago another developer introduced me to Vagrant;

Vagrant provides easy to configure, reproducible, and portable work environments built on top of industry-standard technology and controlled by a single consistent workflow to help maximize the productivity and flexibility of you and your team.

To do its magic, Vagrant stands on the shoulders of giants. Machines are provisioned on top of VirtualBox, VMware, AWS, or any other provider. Then, industry-standard provisioning tools such as shell scripts, Chef, or Puppet, can be used to automatically install and configure software on the machine.

Virtualization is nothing new, of course, it’s been around for many years. What’s great about Vagrant is that once you’ve created your environment, you can package it up in such a way that it can be fully scripted and becomes portable. If you want to create a certain development server configuration that pulls a fresh copy of your client site from GitHub and sets it up every time you fire up the server, you can. If you want to import the latest version of the live database at the same time, you can do that too.

It changes the way you think about working locally. Instead of your own LAMP environment that you maintain separately to your development code, the two become entwined. When you need to work on a client site, just fire up the instance of their server on your local machine and get working straight away. If you want to bring another developer in to work with you, just give them a copy of the instance and they’re good to go immediately – no messing around with set up and configuration and dealing with inconsistencies between their local environment and yours.

The issue? Getting Vagrant set up and tweaked in the way you want it takes a lot of time.

Varying Vagrant Vagrants

Thankfully, after searching around to see if anybody in the WordPress community had considered using Vagrant for local WordPress development environments, I found that Jeremy Felt had not only considered it, he’d created a Vagrant configuration that was pretty much exactly what I needed – a development environment that included Ubuntu 12.0.4 with Nginx, PHP-FPM, MySQL and Memcached out of the box. This is exactly why I love the WordPress community so much!

Varying Vagrant Vagrants is an exploration into the world of of Vagrant and how it can help to make development efficient and in sync with production systems. It replaces the common MAMP or XAMPP setups that we have become familiar with and ensures that all members of the team can develop in the same environment for a project without worrying about the operating system on their local machine.

More at Evolving WordPress development with Vagrant

After setting it up and spending an hour tweaking, I now have a Smart Insights development instance that I can fire up within two minutes that pretty closely matches the live server environment.

Jeremy’s next step is to try and push the managed WordPress hosting companies to give a configuration for their hosting, so us developers can truly match the live server set up. Really hope he’s successful with this!

What’s next

I’m still figuring out the detail of tweaking the Vagrant config Jeremy provides. I’d ideally like the instance to pull a fresh copy of the Smart Insights database every time it’s started – as this is one of the biggest issues with WordPress development – how to keep your local development synchronised. Getting this to work would mean you don’t have to worry about it, and it’d save a lot of time.

I’d love to hear from anyone else using Vagrant for their WordPress local development environment – how are you finding it and what benefits has it brought you over MAMP/XAMPP?

Does WordPress delete expired transients from the database?

Just the other day in Caching using the WordPress Transient API, I explained about using the WordPress Transient API to cache data in the database temporarily, the idea being that you set an expiry date and time against each, and WordPress automatically expires them when this is reached.

So far so good, right? Not entirely. When I was checking to make sure that the expired transients were being cleared properly from the  Smart Insights database, I discovered that the wp_options table was now 130,000 records larger than it was when I launched the transient functionality back on Monday. A little more digging showed that every transient record created since Monday was still in the DB, including all those with an expiry date in the past.

WordPress does not seem to be deleting expired transients from the database.

So why are transients not being deleted automatically?

A little googling brought me to a post from WPEngine on the subject;

But with the WordPress Transients, you get different but still very undesirable behavior. Because the values are written to the database, not a fixed-sized block of RAM, they all stick around. Which means even with the heavily-loaded site, you still have your session data. Awesome!

Or so you thought. Because what isn’t said in the Transient API is what happens when you use unique keys like sessions. And what happens in with the built-in method is that the options table fills up indefinitely! Because: WordPress’s “old data clean up” only operates when you request the key (as we covered earlier). If you just leave the key, it’s left in the options table, forever. There’s no separate process that cleans these up!

More at A Technical Transients Treatise at WPEngine

In my case, since I’m appending the visitor’s PHP session ID to set or check for transients, that rarely happens. So my database gets filled up with lots of expired and redundant data.

What’s the solution to removing transients automatically?

Put simply, you have to remove them yourself – but never fear – the wonderful plugin community comes to the rescue in the form of a plugin to handle this for you. Grab the plugin Purge Transients from Github, put it in your plugins folder and activate it in your WordPress admin. Now any expired transients will be deleted from your database after 7 days.

If you want to force WordPress delete expired transients sooner (like me), open up the purge-transients.php file in a text editor and change the following line to your desired timeframe;

function purge_transients($older_than = '7 days', $safemode = true) {

Hooray! No more unnecessary redundant data clogging up the wp_options table.