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.