Isomorphic JavaScript, WordCamps, WordPress Plugins

NodeifyWP and Twenty Sixteen React Debut at WordCamp Denpasar

Today, I am speaking at the inaugural WordCamp Denpasar. I will be giving a talk on NodeifyWP and Twenty Sixteen React, giving the debut demo of the framework.

NodeifyWP is a framework, created by 10up, for creating isomorphic JavaScript applications within PHP and WordPress. Twenty Sixteen React is an example theme using the framework along with React.js and Redux.

Here are the slides for my talk:

WordPress Plugins

Simple Cache Plugin

I released a new plugin called Simple Cache.

In my blog post Comparison of Popular WordPress Caching Solutions, I rated a number of popular caching plugins pointing out what I like and dislike about each. After writing the post, I decided to create my own plugin that embodies all the characteristics that I think are best for users based on my research and years of experience in WordPress.

Simple Cache is built on the notion of “two paths”: simple and advanced. The plugin defaults to simple mode which simply allows you to turn caching on and off. It “just works” and makes your site run fast.

Advanced mode let’s you set up page caching and object caching using either Memcached or Redis. The plugin uses forked code from WP Redis, Memcached, and Batcache – all plugins that are used on enterprise WordPress websites serving millions of page views.

The plugin is developer friendly with hooks and filters. It also provides very simple and user friendly instructions, notices, field explanations, and warnings.

Give it a try and let me know what you think in the comments below.

WordPress Plugins

Comparison of Popular WordPress Caching Solutions

WordPress has gotten a reputation of being, among other things, "slow". Is that true? Well, yes and no. One of the most important factors in website performance is "caching".  Caching is the act of saving things that are computed often in easy to access places. For example, rather than running a tough database query every time a web page is loaded, save the results of that database query the first time it's run. When that same query is about to be run later, use the previously saved version and skip the query. WordPress does not cache "out of the box" but provides a powerful underlying API (or interface) for plugins to accomplish this. This is a dramatic oversimplification of caching and website performance but is enough for my post.

Having a properly setup caching solution in WordPress is extremely important for providing fast page loads. This post will investigate some of the popular caching solutions for standard WordPress users. I’ll make a recommendation at the end of the post to aid in choosing the right plugin for you.

Note that I am only judging basic caching functionality – page, database, and object caching. I believe, and my extensive experience working with client shows, that cramming a ton of extra features into a plugin usually results in a less effective and harder to use plugin. I recommend finding separate, more focused, plugins for CDNs, file compression, minification, etc.

All plugins have been tested with WordPress 4.4.2, nginx 1.9.9, PHP-FPM 5.5.9, MySQL 5.5.46, and Ubuntu 14.04.

I am rating each plugin on the following categories:

  • Ease of Use – How easy is the plugin to use and configure for the average user?
  • Clutter and Upsell Free Dashboard – Is the plugin settings page filled with links to irrelevant websites? Does it contain upsells or ads? Is the plugin settings page logically organized?
  • Page Caching – How effectively does the plugin provide page caching? Page caching is the act of caching entire pages so subsequent requests receive cached versions.
  • In-memory Object Caching – How effectively does the plugin provide in-memory object caching? In-memory object caching is the act of caching arbitrary chunks of data for use later in something like Memcached or Redis.
  • Free Support Quality – How effective is free support being provided?
  • Uninstall Clean Up – How effectively does the plugin clean up after itself? Many caching plugins add and/or modify a number of files in WordPress. These modifications and additions can cause problems if not cleaned up properly.
  • Security – How secure is the plugin to run?

W3 Total Cache

Ease of Use 2/10
Clutter and Upsell Free Dashboard 2/10
Page Caching 4/10
In-memory Object Caching 8/10
Free Support Quality 4/10
Uninstall Clean Up 3/5
Security 9/10
Overall 4.9/10

W3 Total Cache does a LOT of stuff besides standard caching e.g. CDN support, Varnish, Google Page Speed, minification, site monitoring via New Relic, and more. There are a ton of options; 99% of which are not useful for most people. This makes the plugin more complicated to use.

The dashboard is cluttered with up-sells.

Disk and Memcached based page caching still resulted in MySQL queries being run according to my tests. Disk and Memcached based database query caching also still resulted in MySQL queries being run. These are either bugs or poorly explained functionality. Once I enabled the object cache, no more MySQL queries were ran.

After removing the plugin, all the cache files are left in my wp-content folder. The plugin did clean up important functional files.

A plugin audit revealed a good use of important code level security techniques such as escaping, nonces, permission checks, and sanitization. This plugin is safe to run on your website and does not make you vulnerable to hackers.

Regarding support, WP Tavern has reported some serious support concerns.

WP Super Cache

Ease of Use 7/10
Clutter and Upsell Free Dashboard 8/10
Page Caching 9/10
In-memory Object Caching 0/10
Free Support Quality 6/10
Uninstall Clean Up 5/5
Security 9/10
Overall 6.7/10

WP Super Cache keeps things pretty simple with standard functionality. I really like how it has “easy” and “advanced” tabs. Besides basic caching, it supports CDNs and a number of advanced options.

The plugin dashboard is clean and uncluttered. There are no upsells.

Static file page caching works perfectly out of the box. No MySQL queries were ran in my testing of page caching. In-memory object caching on the other hand is not supported by the plugin at all. This is a huge disadvantage as the object cache API is very powerful allowing us to cache complex queries and utilize in memory caches such as Memcached.

The plugin authors (Automattic) seem to be responding to threads in the support forum.

The plugin is well-written. There are no obvious security flaws.

Uninstalling the plugin cleaned up all necessary files.

WP Fastest Cache

Ease of Use 5/10
Clutter and Upsell Free Dashboard 0/10
Page Caching 7/10
In-memory Object Caching 0/10
Free Support Quality 8/10
Uninstall Clean Up 5/5
Security 0/10
Overall 3.8/10 

WP Fastest Cache is somewhat easy to use. All of it’s important features are easily visible. It could be made much clearer what is needed to be done to turn on basic caching.

The plugin has filled with upsells. About half the functionality requires a premium license. However, basic caching functionality is provided for free.

Enabling caching immediately threw a PHP warning. It isn’t exactly clear the type of caching the plugin enables. Is it disk based? Is it page caching? It’s not very clear. The plugin performs disk based page caching. An option must be read in the database before static output can occur. No in-memory object caching is provided.

The plugin author seem to be responding to threads in the support forum.

The plugin uses nonces properly. However, it has some sanitization issues. This plugin is not completely safe for use.

Uninstalling the plugin cleaned up all necessary files.

Hyper Cache

Ease of Use 4/10
Clutter and Upsell Free Dashboard 5/10
Page Caching 7/10
In-memory Object Caching 0/10
Free Support Quality 3/10
Uninstall Clean Up 3/5
Security 0/10
Overall 3.3/10 

Hyper Cache is confusing to use. There is no option to enable caching. Instead you have to click save in the settings page without changing anything. Very strange. The first option shown on the settings page is “Disable Translations” which seems pretty unimportant.

There is some clutter in the dashboard for other plugins by the author, but there are no upsells.

Up front, it isn’t exactly clear the type of caching the plugin employs. Is it disk based? Is it page caching? After testing, I found out the plugin performs disk based page caching. No MySQL queries were ran when the cached page was served. There is no in-memory object caching unfortunately.

Regarding support, the plugin author does not seem to be actively responding to support threads. There also does not seem to be community members providing support.

The plugin has serious sanitization issues and poses a security threat when installed.

Uninstalling the plugin cleaned up important functional files but did not remove everything properly.

Comet Cache

Ease of Use 4/10
Clutter and Upsell Free Dashboard 2/10
Page Caching 7/10
In-memory Object Caching 0/10
Free Support Quality 7/10
Uninstall Clean Up 4/5
Security 0/10
Overall 3.7/10 

Comet Cache makes it very clear how to enable caching. This is a huge plus. Enabling caching gives me an error message to update my nginx configuration. However, after looking at the configuration updates, they are not necessary for basic caching. The plugin has a lot of useful help text. The plugin is not compatible with PHP 5.2; there fore it is not compatible with all versions of WordPress.

The plugin dashboard is cluttered with plugin author promotions as well as upsells. The clutter makes the plugin harder to navigate.

Like many caching plugins, it isn’t 100% clear what type of caching the plugin employs. After testing, I found out the plugin performs disk based page caching. No MySQL queries were run when the page cache was served. There is no in-memory object caching unfortunately.

Regarding support, the plugin authors seem to be actively involved in the support forums. There are also people volunteering their time for assisting others.

The plugin seems to properly sanitize and escape data. However, it is doing some slightly scary things with direct database queries.

The plugin has an option for uninstall method. You can either just delete the plugin or delete the plugin and all it’s data.


If you are looking for easy to use caching that “just works”, WP Super Cache is for you. The plugin provides disk based page caching that will dramatically speed up the vast majority of websites. The support community is vibrant, and the plugin is well maintained.

If you want in-memory object caching and don’t mind getting your hands dirty, install the Memcached and Batcache drop in plugins. Both of those plugins require manually moving files into your wp-content folder. Neither plugin has a settings page as they are both plug and play. They can be somewhat unforgiving if you run into an issue. If you want in-memory object caching but want something easier, I recommend W3 Total Cache.

Spirited comments around these recommendations as well as new ones are welcome 🙂



EDIT: Lot’s of people recommended I review WP Rocket which is a premium file based page caching plugin. Overall, WP Rocket is a solid plugin. It’s written well and “just works”. However, it is not free and only offers file based page caching. It does not support object caching. I also think the plugin’s UI could be a bit simpler.

Based on my experience with all these plugins, I wrote my own called Simple Cache. Simple Cache offers file based page caching. The plugin literally only has one setting “on or off” unless you turn on advanced mode. Advanced mode let’s you do object caching and in-memory page caching. The plugin is written securely and is extremely performant. Anyone looking for a caching plugin should give Simple Cache a try and leave me some feedback below 🙂

WordPress Plugins

JSON REST API Subscriptions Plugin

This week I released the JSON REST API Subscriptions plugin for WordPress. The plugin requires the JSON REST API plugin.

The JSON REST API plugin creates endpoints like so

Obviously the /posts endpoint returns all posts and the posts/253 returns the post with ID 253.

The JSON REST API Subscriptions plugin adds webhooks style subscriptions to those endpoints like so:

By sending an HTTP request to like so:

"target": ""
"events": ["create", "update", "delete"]
} would be sent a notification HTTP request every time a post is created, updated, or deleted. All subscription routes, requests, and notifications are explained in detail on Github.

Using this plugin gives websites digesting your content an alternative to parsing feeds.

WordPress Plugins

Custom Contact Forms 7.1 – Advanced Notifications

Custom Contact Forms 7.1 has been released. The new version contains some bug fixes for sitemap SEO, non-American date formats, and advanced notifications. Specifically, I wanted to highly the advanced notifications feature which is very powerful.

In the new version, you can create an unlimited amount of notifications which allows you to send different notifications to administrators, editors, the form submitter, etc. Here is a screenshot of the new notification editing experience:



For each of your forms, you can view notifications in list view giving you an easy way to see all your notifications:


Advanced notifications will continue to be improved in newer versions as we believe notification functionality is extremely important to web forms.

Download Custom Contact Forms

Database Theory, Elasticsearch, Search, WordCamps, WordPress Plugins

ElasticPress at WordCamp Paris

This weekend I presented at WordCamp Paris 2015. My session was titled “Modernizing WordPress Search with Elasticsearch”. The talk ran through issues with WordPress search, what Elasticsearch is, setting up an Elasticsearch cluster, and configuring ElasticPress.

Elasticsearch is a very exciting technology and I am thrilled at the chance to spread information about it. I (and 10up in general) am very proud of the work we have done on ElasticPress. My hope is that more people will install the plugin and give us feedback as a result of the talk.

Here are my slides for the talk:

Don’t forget that comprehensive documentation for ElasticPress lives on Github.

Publishing Experience, WordPress Plugins, WP API

Custom Contact Forms Redux

In 2009-2010 Custom Contact Forms was one of the first WordPress plugins I wrote. The purpose of the plugin was to solve a simple problem: easy contact form building on the web.

As I was building the plugin, WordPress 3.0 had not yet been released, and therefore custom post types and other useful API’s did not yet exist. I wrote the plugin the best I could using custom database tables (ouch!). The plugin become decently popular. I continued development on the plugin for the next year or so. In the process I learned a lot about writing code for WordPress. Also in the process I landed a job at 10up where I learned (and continue to learn) more than I ever thought I would.

Years later in 2015, here I am an experienced WordPress developer and an avid open source contributor. I have used most of the popular WordPress form plugins: Gravity Forms, Ninja Forms, Formidable, etc. Using all these plugins, despite lots of great functionality, have left me with the nagging feeling that something is missing.

That something was the WordPress experience. With the release of the media manager in WordPress 3.5, we have all grown accustomed to a high quality media management experience through smooth JavaScript interactions. Form management should be no different; they should be built within a media manager-esque modal, no page reloads should be necessary, and we should get live previews of what we are building. Simple task right? 8 months later… 🙂

Detailed installation and usage instructions are on Github. Download the plugin from

For Users

Within the post edit screen, a simple “Add Form” button next to the “Add Media” button brings up the form manager modal:


Within the form management modal, you can also see your existing forms and edit them if you choose:

View all your forms within the form management modal for easy access.

After inserting a form into a post, you see a nice preview within TinyMCE:

Form previews even show within TinyMCE.

While the meat of the plugin lies within the form manager, single form views exist. Within a single form view you can see a live form preview:

Live previews of your forms are generated on the fly. No more guess and test.

Also within the single form view lives the form submissions table. You can easily paginate through results and add/remove columns as you please:

Easily scroll through form submissions in tabular format. You can configure columns you would like to see to ensure an uncluttered view.

For Developers

Most of the plugin is written in JavaScript. Custom Backbone views, models, and collections are written to emulate and display forms and fields. The plugin is extremely extensible. You can easily hook in to modify existing fields and views as well as create your own.

The plugin includes the new JSON REST API for WordPress. Right now, it is included as a Composer dependency for various reasons until the API is added to WordPress core.

Note: While the plugin is suitable for production environments, version 6 is still somewhat in beta. Please let me know on Github if you experience any problems.

Elasticsearch, Search, WordPress Plugins

Valuable Lessons Learned in ElasticPress

ElasticPress is a 10up WordPress plugin project that integrates Elasticsearch with WordPress. As we all know search in WordPress is not a great experience. Why? Well, MySQL is not a database optimized for search. Thus ElasticPress was born.

1. Search result relevancy scores on sites with high post to shard ratios can vary depending on order of indexing.

We first noticed this in our integration testing suite. We were using three shards across 1 primary node. Depending on the order that posts were indexed, different relevancy scores were returned for the same search.

Elasticsearch relevancy scores are calculated as term frequency / inverse document frequency. Term frequency is the number of times a term appears in the query field of the current document (or post). Inverse document frequency measures how often the term appears in all query fields across all documents in the index of the current shard. Notice I said shard NOT index. The shard a post lives on is determined by the number of shards and the size of the index. We can’t exactly predict relevancy scores for a search on an index across more than one shard. The Elasticsearch documentation has a great article on this.

The solution for testing purposes is to only use one shard. In the real world, this shouldn’t matter as inconsistencies plateau as index sizes grow larger. However, this is still something to be aware of.

2. There is no right search algorithm for WordPress. Fine tuning algorithms is an on-going, collaborative process.

As of ElasticPress 1.1, the meat of our default search query looked like this:

  "query": {
    "bool": {
      "must": {
        "fuzzy_like_this": {
          "fields": [
          "like_text": "search phrase",
          "min_similarity": 0.75

fuzzy_like_this is great. It combines fuzzy and more_like_this queries. fuzzy searches against a set of fuzzified terms (using the levenshtein distance algorithm). more_like_this selects “interesting” terms based on a number of factors like document frequency and checks each document against those terms.

The problem we encountered was that in certain established indexes exact matches were not getting boosted to the very top of results. This was due to the way the fuzzy_like_this algorithm works. We added an extra query to our search algorithm in 1.2 to boost exact matches:

  "query": {
    "bool": {
      "should": [
          "multi_match": {
            "query": "search phrase",
            "boost": 2,
            "fields": ["post_title", "post_content", "post_excerpt"]
          "fuzzy_like_this": {
            "fields": ["post_title", "post_excerpt", "post_content"],
            "like_text": "search phrase",
            "min_similarity": 0.75

The should query tells Elasticsearch that one of the multi_match or fuzzy_like_this queries must be true for a document to match. It then boosts anything found multi_match x2.

This solved our immediate problem but is not the perfect algorithm. We expect to continually optimize this for WordPress over time. (Note that ElasticPress allows you to filter the search query entirely if you want to customize it.)

3. Disable indexing during imports.

By default ElasticPress indexes when a post is created. This is great until you try to import a few thousand posts, and your Elasticsearch instance gets overloaded. This bit us pretty hard. As of newer versions, ElasticPress disables syncing during WordPress imports big or small.

Publishing Experience, WordPress Core, WordPress Plugins

Given the unmet need to allow users only access to edit specific pieces of content, I created a simple plugin called Editorial Access Manager.

By default in WordPress, we can create users and assign them to roles. Roles are automatically assigned certain capabilities. However, sometimes default roles are not enough, and we have one-off situations. Editorial Access Manager lets you set which users or roles have access to specific posts (as well as pages and custom post types).

Only the Administrator and Editor role have access to manage pages by default in WordPress. Making a user an Editor gives them a lot of power. I ran into the situation where we wanted a Contributor (less power than an Editor) to be able to edit only a few pages hence the need for this plugin.

My plan is to eventually integrate this plugin with EditFlow allowing people to assign User Groups to have access to specific pieces of content.

Any development help on this project would be much appreciated! Fork the Github repo.

Command Line WordPress, WordCamps, WordPress Plugins

WordCamp Ottawa

This weekend I was lucky enough to present at the 2nd annual WordCamp Ottawa. My talk was titled “Saving Time with WP-CLI”. WP-CLI is a plugin that lets you interact with your WordPress installations via the command line. My talk runs through some cool built-in WP-CLI commands as well as creating custom commands. My slides for the talk are here: