Two years ago, three colleagues and I decided to create Nelio Software, a company focused on offering WordPress-centered services. The only thing that we had back then was a business idea and, for some reason, the goal of implementing that idea on top of WordPress. Surprisingly, though, we had little to no experience in WordPress! So, if we wanted to build a business on top of WordPress, we sure as hell needed to learn how to properly code WordPress plugins! We read a lot of books, online articles, and tutorials on the subject, and we read and wrote a lot of code. We used to be green and naive, but we were passionate. Two years later not only are we still passionate about what we do, but we’re also WordPress experts eager to help others reach success faster.
In this post I’d like to share my experience in writing WordPress plugins, as well as to point out some tips and tricks I wish someone had told me before. Shall we start?
Writing a Simple WordPress Plugin
Creating a WordPress Plugin is extremely easy. In essence, you only need to create one folder (for example, nelio-nice-title
) in wp-content/plugins/
and add one file within that folder (nelio-nice-title.php
) with the following content:
After that, if you go to your WordPress Dashboard » Plugins, you’ll see the plugin we just created in the list of available plugins. Activate the plugin, go to your blog, and… voilà! All your post titles now tell your visitors how cool they are!

WordPress APIs
So, you’ve already created your first plugin, even if you don’t fully understand what you’ve just done. Don’t worry about it, we’ll get there shortly. For now, just remember the following: WordPress offers different APIs for extending its core functionality. Each API is no more than a set of functions involved in and used of a certain functionality. Examples of these APIs are:
- Plugins API. It’s probably the most basic API you need to know for creating a plugin.
- Settings API. It offers a set of functions for creating a Settings page.
- Options API. With this API, you can save and retrieve the configuration options of your plugin.
- Widgets API. This API allows you to create new widgets and widget areas.
- And many, many more.
Plugins API – Hooks, Actions, and Filters
As detailed in the Codex, “Hooks are provided by WordPress to allow your plugin to ‘hook into’ the rest of WordPress; that is, to call functions in your plugin at specific times, and thereby set your plugin in motion”. There are two types of hooks:
- Actions. An action is a PHP function that’s triggered when certain events take place in WordPress, such as saving a post or printing the
head
section of an HTML file. - Filters. A filter is a PHP function that receives some data at certain points in the WordPress execution, processes it somehow, and returns the modified data.
In the previous example, we’ve defined one filter that modifies the titles of our posts. The filter event (the_title
) is triggered each time a post’s title is about to be printed in the screen. When that occurs, the function we linked to that event (nelio_change_title
) is executed and appends the string “You’re cool!” to the title.
Writing a not-that-simple WordPress plugin
Let’s write a slightly more complex example, where we use both actions and filters, and where we modify both the WordPress Dashboard and the front-end. In particular, we want to create a plugin that adds a new meta box in the post editor, where we can modify the text that has to be appended to a post’s title. This is what we want:

Adding a Meta-Box
First of all, we need to add the meta box. If we take a look at the Codex, we’ll see that there’s a function called add_meta_box
. According to the documentation, this function has to be called from the add_meta_boxes
action, so let’s do it:
The third parameter of add_meta_box
is the name of a new function that will print the content of the meta box. If the function is empty (see line 12), so is the meta box:

But if the function prints out some content:
then the meta box is populated:

Saving the meta value
The meta box we just created allows the users of our plugin to specify the text that will be shown along with their posts’ titles. In order to do that, however, we need to save the value of the field:
As you can see, saving said value is quite easy! We simply need to hook into the save_post
action, recover the value from the $_REQUEST
array, and save it as a post meta using the update_post_meta
function.
Using the value in the front-end and in the Dashboard
Right after you saved the post, the meta box field will be empty again. That’s weird, because just a few moments ago you specified a value, but it’s completely normal. Each time you print the field, you print an “empty” field:
See? The field does not include any value
… Before printing the field, you need to recover its value from the database and include it in the HTML:
Finally, if you want to use that text in the front end, you have to follow a similar approach. In this particular case, we need to modify nelio_change_title
as follows:
As you can see, we simply recover the value of the meta field from the database and, if it’s not empty, we append it to the post’s title.

Nelio A/B Testing
Native Tests for WordPress
Use your WordPress page editor to create variants and run powerful tests with just a few clicks. No coding skills required.
The Importance of a Strong Foundation—The Plugin Boilerplate
Let’s take a quick look at the plugin we just wrote. It’s an extremely simple plugin and, yet, it’s quite a mess already! The plugin consists of one file only and its content is, as I said, messy:
- we modify the front-end and the Dashboard indistinctly,
- there’s a block for adding a meta box in the post editor, which mixes the user interface (lines 48-51) with the PHP code that validates the user input (lines 36+) and saves the field in the database (lines 60+).
As you can imagine, this will be far from maintainable once the plugin integrates more functionalities. We need to organize the code somehow, and make sure that we stick to that organization.
A few months ago, I stumbled upon The WordPress Plugin Boilerplate. This plugin is “a standardized, organized, object-oriented foundation for building high-quality WordPress plugins“. The project was originally started by Tom McFarlin and it’s now maintained by Devin Vinson, even though a lot of people has contributed to the project somehow.
This Plugin Boilerplate includes the following features:
- File Organization. The boilerplate ships JavaScript and CSS files for both the front-end and the Dashboard views. There’s a place for every type of file and the project leaves no guesswork as to what goes where:
plugin-name/includes
is where functionality shared between the admin area and the public-facing parts of the site resideplugin-name/admin
is for all admin-specific functionalityplugin-name/public
is for all public-facing functionality
- Documented Code. All the files and functions are properly documented. This is something that I really appreciate. This is one mistake I make every now and then: it’s easier to write code than writing comments, but in the long run having comments really pays off. Therefore, using a boilerplate that includes these comments from the very beginning is really helpful!
- Object Oriented. As stated in its own website, “if you’re looking for an object-oriented approach, then the Boilerplate has you covered. Separated by responsibility, it’s easy to find where to place your dashboard code, your public code, your shared code, and more”.
I really, really like how all the pieces fall together when using the WordPress Plugin Boilerplate. In fact, I like it so much that I’m currently rewriting Nelio A/B Testing from scratch with it!
Rewriting our plugin…
Let’s see how we could rewrite the previous plugin using the WordPress Plugin Boilerplate. In order to do that, download the plugin and replace/rename the following strings (and files):
- plugin-name » nelio-nice-title. For instance, the files
plugin-name.php
orpublic/class-plugin-name-public.php
will now benelio-nice-title.php
andpublic/class-nelio-nice-title-public.php
. Allinclude
andrequire
directives in the plugin have to be properly changed, so that they point out to the new files. - Plugin_Name » Nelio_Nice_Title. Classes in the Boilerplate have the prefix
Plugin_Name
, which needs to be changed to our plugin‘s name. Thus, for example,class Plugin_Name_Public
becomesclass Nelio_Nice_Title_Public
. - plugin_name » nelio_nice_title. The same applies to variables (and other strings) named
plugin_name
, which must be renamed tonelio_nice_title
.
Once you’re done, you’ll have the foundation for your new plugin (you can download it from here). Now it’s time to move the contents in the appropriate places.
First of all, move the function nelio_change_title
to the class Nelio_Nice_Title_Public
, name it to change_title
(there’s no need for using the prefix anymore):
and add the hook in Nelio_Nice_Title::define_public_hooks:
Then, you have to create a new file in the admin/
directory named class-nice-title-meta-box.php
with the following content:
Note that the method display
loads a template from admin/partials/
. Create a file named nice-title-meta-box.templ.php
with the following content there:
Finally, add the admin hooks in Nelio_Nice_Title::define_public_hooks
so that the functions defined in class-nice-title-meta-box.php
can be executed when required.
As you can see, all the code is now properly organized. The front-end code and the admin code are no longer mixed, and we’ve split the meta box in two different files: one for managing all the logic (that is, retrieving the appropriate value, displaying the meta boxes content, and saving the new value) and another with the HTML contents of the meta box. If you’ve applied all the changes properly, you’ll have a project that looks like this one.
Finally, you simply need to get rid of all the files that your plugin does not need, so that the plugin is “as small as possible”. In real projects you’ll probably need almost all files included in the Boilerplate, but it’s worth taking a look at unnecessary files and removing them. For instance, in our example the plugin is so simple that the vast majority of files are unnecessary: internationalization files, activation and deactivation hooks and files, JavaScript and CSS files…
5 Tips for Producing Better Plugins
As you can see, there’s a lot of things involved in plugin creation. But if you try to apply the following tips (which I had to learn the hard way), and as long as you’re familiar with the WordPress API and you base your work on a solid foundation, your work will be great!
Tip #1. Follow WordPress Guidelines
What do you prefer? This:
or this?
Simple stuff like spacing, indentation, or proper name variables can have a huge impact on the final quality (and maintainability) of your work. WordPress has excellent coding standards for PHP, HTML, JavaScript, and CSS files. Make sure you’re familiar with them before coding anything.
Tip #2. Be Organized and Clever
The Plugin Boilerplate I introduced above is a great example of how you should do things. Just apply the following rules and you should be good:
- Keep the directory structure in mind and commit to it: front-end functionality in the
public/
dir, all Dashboard views and functionality inadmin/
, and everything else inincludes/
. - Don’t be afraid of using sub-folders to better organize your code.
- Each class has to be defined in its own file.
- Each class should be responsible of one thing only (for instance, in our example we defined a class responsible of a meta box management).
- Never mix the presentation layer (HTML code) with the logic (the PHP code that retrieves, process, and possibly saves data).
- Load stuff when you need to. In other words, if a functionality is only needed in the front-end, do not load it whilst you’re on the Dashboard (
is_admin()
check).
Tip #3. Take Security Seriously
Making my plugins secure was not the first thing I used to consider, but it’s crucial! Security can be guaranteed (up to a certain level) by following these three rules:
- Whenever you’re about to print data on screen, make sure you escape it properly. In order to do that, you should be become familiar with functions such as
esc_url
,esc_attr
, oresc_html.
- Always sanitize user’s input. For example, if you expect a number, make sure you cast the user’s input into a number; if you expect a string with no HTML tags, get rid of all the HTML tags using
strip_tags
. - Use Nonces for Form and URL Verification. When collecting data from a submitted form, you should always check that the data was really collected from your form and not from a malicious third-party agent. To take care of this aspect of security, we use nonces. A nonce is a number used once. Read more about them in the Codex and learn how to use them.
Tip #4. Comment Your Code
Our projects are driven by code, not comments. Therefore, it’s much faster to only focus on writing clear code and completely forgetting about comments. I’ve been there—I’ve written a lot of code without comments. And it worked. So why should you comment your code? I mean, if you’re writing clean and understandable code, are comments really necessary?
In my opinion, comments capture the developer’s (i.e. our) intention. When you’re writing code, you’re trying to solve a problem. Describing the problem and how you’re trying to solve it is the nature of commenting. The classes you create are supposed to solve smaller parts of a given problem, and each method in those classes contributes somehow to the final solution. Comments don’t necessarily tell you what the commented code does, but what the the developer was trying to solve and what concrete solution he envisioned. If my code is properly commented, I can look at it at any time and I’ll be able to understand why things are the way they are, why they exist, and puts me back in context. And that’s pretty awesome, isn’t it?
When writing comments, try to express your intent. Move away from these comments:
and write things like this:
Tip #5. Create and Add Your Own Hooks
In this post we’ve seen how you can use WordPress filters and actions. But did you know you can define your own filters and actions? In other words, you can allow third-party plugins to extend your own plugin by simply defining some extension points at certain locations in your code (for example, when the plugin is about to be activated or when you’re about to modify something in the front-end). If you use this mechanism, you’ll be able to add new functionalities to your plugin easily, either by adding new code in the plugin itself and hooking in the appropriate areas, or by implementing new plugins that extend the original one.
Your Turn
I hoped you enjoyed this entry! Now, it’s time you apply all these tips and tricks 😀 And, of course, if you have any of your own, please share!
Featured image by james j8246.
Leave a Reply