Creating Custom Post Meta Boxes in WordPress

Meta boxes are a useful feature in WordPress that allow you to add completely custom data to a post or page in WordPress.

Say, for example, you’re creating a website for a client that needs to display nutritional information alongside products in a store (as we’ll be exploring in this post). You can add any number of custom meta boxes to the post and page editing screens in the backend of WordPress, for both posts and custom post types.

Usually, custom meta boxes contain data and form fields, which allow admins to add/edit/delete posts meta data (i.e. custom fields, overcoming the limitations of the ugly and poor built-in custom field box.

In this tutorial, I’ll show you how to add your own custom meta boxes to a post edit screen. We’ll explore how to add and manage text fields, and radio buttons and checkboxes that will give users more advanced control over post meta data.

Note: Scroll down to the bottom of the page to download the free plugin from the example in this tutorial.

What is a Meta Box?

A meta box is a draggable box displayed in the post editing screen in the backend of WordPress. Users can select or enter extra information in meta boxes addition to the content in the main post editing area.

There are two types of data you can enter in meta boxes: metadata (i.e. custom fields), and taxonomy terms.

Adding a Meta Box

WordPress provides a add_meta_box function with the specific purpose to add a new Custom Meta Box. add_meta_box has to be called from inside a callback function that should be executed when the current page’s meta boxes are loaded. This task can be performed hooking the callback to the add_meta_box_{custom-post-type} action hook, as suggested in the Codex.

That being said, let’s add the following code to the main file of a plugin or a theme’s function.php file (keeping in mind that it’s always best to create a child theme instead of altering a functions.php file):

This is our first custom meta box. In the code above, we’re passing six arguments to the add_meta_box function: an ID for the meta box, a title, a callback function, the slug of a custom post type (food), context (side) and priority (low).

The callback function will print the HTML markup into the meta box, and we’ll define it as follows:

No HTML is printed yet, but the meta box is in its place. So, let’s go through this example in more detail.

empty custom meta box
An empty custom meta box

First of all, we should consider keeping things safe. We need to call the function wp_nonce_field, which produces a nonce field, the goal being to ensure that the form request comes from the current website. So, let’s add the following line of code to the callback function:

Here, we’ve passed the function just two of the four admitted arguments. The first one is the action name, here set to the basename of the current file, while the second argument is the name attribute of the hidden field. Even if the nonce field does not guarantee absolute protection, it’s good practice to always include it into any custom meta box (check the WordPress Codex for a more thorough explanation).

Once we’re done with security, we have to retrieve from the database the custom field values to be managed through the meta box fields. This is where the get_post_meta function comes in handy.

In our example plugin (or functions file, depending on how you want to implement the example in this tutorial) we make use of three single custom fields, two strings, and an array. The code below shows how to grab their values from the database:

In this example, the custom field slugs are preceeded by underscores, meaning that we are dealing with hidden custom fields. This way, they won’t be shown to the admin user in the built-in custom fields’ meta box, but will be editable just from the Custom Meta Box.

Finally, it’s time to print the markup.

Printing the Form Fields

Now we have to produce the output. Let’s begin by adding a simple text field, which will allow the admin user to store the value of a single custom field, in this case carbohydrates:

In the code above, the custom field itself provides the value of the current input element. The next custom field will be handled with a pair of radio buttons:

Here things become a little tricky. The checked function compares the two strings we’ve passed as arguments. If the strings share the same value, the function sets the current field to checked.

Finally, we’ll add a group of checkboxes to the meta box:

The value of the name attribute corresponds to the element of an array, and later this will allow us to store data more efficiently.

Now, consider the first argument of the checked function:

It’s a ternary operator that checks whether the current value of the checkbox is the same as the value of $current_vitamins. If the condition is verified, then it returns the same value, otherwise it returns an empty string.

Now that the logic should be clear; we can shorten the code with an array and a foreach cycle:

And now we can put it all together:

And here’s what the finished meta box looks like in the post editing screen with all its form fields:

Food meta box
A Custom Meta Box for food post type

Storing Data

The meta box is ready, but it’s not possible to save data just yet. To accomplish this task, we have to define a new callback function to be called when saving a post:

The save_post_{$post_type} hook runs whenever a new $post_type is saved or updated.

Now let’s see what’s going on inside the function. First, we have to check the nonce field value:

If the nonce field is not set or its value in not correct or has expired, the execution is interrupted (check the WordPress Codex for more information about wp_verify_nonce).

If you would prefer to skip the function in case of autosaving, we can add the following condition:

Then, we need to check the user capabilities:

Finally, we can store data:

If at least one element of the 'vitamins' array exists, then the $vitamins variable will store the corresponding values.Later, the PHP

Later, the PHP array_map function applies the WordPress sanitize_text_field function to each array item. Finally, the update_post_meta function stores the posted values.If no checkbox has been checked, the array

If no checkbox has been checked, the array $_POST['vitamins'] does not exist, and we can delete data by calling delete_post_meta (check the Codex documentation for more details).

And here is the full code:

I’ve put together the code in a plugin, which you can download from Github and test on your own website or localhost install.

Wrapping Up

Now that you’ve seen how custom meta boxes work, you can add any type of form field to the post editing screen in the backend of your WordPress site. HTML5 introduced a good number of input types we can play with, from date fields to the color picker.

You could have even more fun with jQuery UI tools, or mashing up data from several web services, like the Google Maps API, and storing them as custom fields. The example in this tutorial only scratches the surface of how you can customize the post editing experience.

Have you added any advanced form fields or controls to the custom meta boxes yet? Are you working on any website right now where this kind of functionality would be useful? Let us know in the comments below if you have any questions about this tutorial or ideas for how you would extend it.