The default Page and Post content types in WordPress are enough for many websites, but if you really want to harness the powers of WordPress as a CMS it’s time to start learning about custom fields and metadata.
This is the sixth post in our WordPress Development for Intermediate Users series. This series follows on from our popular WordPress Development for Beginners tutorials, which introduced you to the fundamentals of developing websites with WordPress, how to get started coding with PHP, and building themes and plugins.
In this part of the series, we’ll focus on how to create and display metadata in WordPress, including post metadata or custom fields as they’re often known. You’ll learn:
- What metadata is and how it’s used in WordPress.
- How to add custom fields to your posts and display them.
- How to create a custom metabox for post metadata/custom fields.
- How to display other kinds of metadata in your theme including user metadata.
Let’s get stuck in.
What is Metadata in WordPress?
Let’s start by defining metadata. What exactly is it?
Wikipedia defines metadata as:
“… data that provide information about other data.”
In WordPress this means that metadata is data about the core content, which includes posts (of all types), comments, users and taxonomy terms. An easy way to identify this is by looking at the database structure, which you can see in the diagram below:

There are four database tables for data:
- wp_posts: for posts of all types (including pages, attachments and custom post types)
- wp_comments: for comments
- wp_users: for users
- wp_terms: for taxonomy terms
Each of these has a corresponding table for metadata about the relevant type of data:
- wp_postmeta for post metadata (or custom fields)
- wp_commentmeta for comment metadata (e.g. data added by comment plugins such as Akismet)
- wp_usermeta for user metadata (e.g. roles and dashboard settings)
- wp_termmeta for taxonomy terms metadata (e.g. the term description).
You don’t need to worry about all this too much at this stage – the database will be covered in more depth in our upcoming Academy course WordPress Development for Advanced Users. All you need to know is that metadata exists and how to access it, which you’ll find out about if you read on.
Adding and Displaying Custom Fields
Adding custom fields is very simple but displaying them involves writing some code in your theme or hooking it in via a plugin. Let’s take a look at both.
Adding Custom Fields
The simplest way to add post metadata is by using the built-in custom field interface in the post editing screen. Here is one of the posts in the demo site I’ve been using with this series:

Adding a custom field is as simple as typing in its name (stored as a key in the database) and value (stored as a value):

Once you’ve added one, you can use that name again for additional custom fields on that post and others.
Displaying Custom Fields
If you want to display the values of your custom fields, you’ll need to add some code to your theme. Alternatively if you have hooks in your theme, you can insert it using those via a plugin, which you’ve already learned to do in this series.
Let’s add custom field display to the single post template in our theme.
Start by opening the template file in your theme that displays the loop for single posts. In the theme we’ve been working on in this series it’s loop-single.php. If you haven’t been working along, you can download the Part 5 version of the theme via the series source files on GitHub.
Note: If you’re working with your own theme, you may need to work in a different template file. Adapt what I’m doing here for your theme.
- In your loop-single.php file, find this code:
.gist table { margin-bottom: 0; } - We need to include the post metadata in a new conditional tag. First, let’s add the extra tag. Edit the code so it reads like this:
.gist table { margin-bottom: 0; } - Next, add the
the_meta()
function inside a div:
.gist table { margin-bottom: 0; }
Save your file and take a look at a post for which you’ve added a custom field. It won’t look perfect now, but by using the post-meta
class you’ve accessed styling we already set up for a custom post type in an earlier part of the series. I want to remove the bullet points and tweak the margins and padding, so I’ll make some changes to the stylesheet. You can find them in the source files for this part of the series.
Here’s my final version:

You can add whatever styling you need. Note that I’ve taken advantage of the span
tags that WordPress automatically puts around the name of the custom field to add bold styling.
If you want to have more control over the way your post meta data is displayed in each post, you can use the get_post_meta()
function instead and then echo out its results. You can see this in action in our post on working with custom fields and I’ll also cover it later in this part of the series.
Creating a Custom Metabox for Post Meta
Using the custom fields interface is all well and good, but it doesn’t give you much control and it can result in your users making mistakes. What if you want to limit the values for a post meta field to a few options and not let users type in their own? Or you want to predefine some post meta fields for consistency?
The way you do this is by creating a metabox in the post editing screen, using the add_meta_box()
function. This function has no less than seven parameters:
.gist table { margin-bottom: 0; }
The parameters are:
- $id: adds a CSS ID to the div containing your meta box
- $title: the name of the meta box as displayed on the post editing page
- $callback: the name of the function containing the HTML for your meta box
- $post-type: the type of content for which this meta box will be available (leave it blank for all)
- $context: where in the editing page the meta box should be displayed –
'normal'
,'advanced'
or'side'
- $priority: the priority level for displaying your meta box—
'high'
, ‘core’, ‘default’ or ‘low’. The default is (unsurprisingly)'default'
; use'high'
to move it above other meta boxes. - $callback_args: arguments to pass into your callback function. This is needed if your function requires arguments other than
$post
, which is automatically passed to the callback function.
Let’s create our own function to do this, which will help all of these parameters make more sense. I’m going to create a new plugin that will both add the meta box and output what’s added to it via a hook in my theme.
So start by creating a new plugin and adding the usual commented out text at the top.
Creating the Metabox
The first step is to write the function that creates the metabox. In your plugin, add this:
.gist table { margin-bottom: 0; }
This sets up the metabox, with the following parameters:
- an ID of
wpmu_metabox
- a title of ‘Add More’
- a callback function called
wpmu_metabox_callback
- it will be displayed on the post post type
- a position of
normal
(i.e. on the left and high (just below the main editing pane).
Don’t try saving your plugin just yet: you need to create a callback function or WordPress will throw up an error.
Creating the Callback Function
The callback function defines what will be displayed on the post editing screen, which is a form. You need to use the get_post_meta()
function to display the value of a particular meta key.
Add this to your plugin:
.gist table { margin-bottom: 0; }
Let’s take a look at what this does:
- It opens up a
form
element. - It adds a nonce field, which won’t be visible to your users but which helps with security: the nonce field will be checked before the metadata is saved, to be sure that users have used this metabox to add metadata and not done it any other way.
- It uses
get_post_meta()
to retrieve the value of a newwpmu_weather
field and assigns that value to the$weather
variable. - It creates a table for our field.
- It creates a field whose value is that
$weather
variable. - It closes the
form
element
Now save your plugin and take a look at the post editing screen on your site (making sure you’ve activated your plugin first).
Here’s mine:

You’ll notice that the wpmu_weather
field has also been added to the custom fields below. That could be confusing so we’ll fix it shortly.
If you type something into that metabox it won’t save. That’s because we still need to add a function for that.
Adding a Function to Save the Metadata
Now add a third function:
.gist table { margin-bottom: 0; }
Let’s walk though that function:
- It checks that the nonce has been set, which will only be the case if the user has input the new value using that metabox.
- It checks that the current user has the
edit_post
capability, in other words, that they’re authorized to do this. - It checks if a new value has been added to our field.
- If so, it replaces the old value with the new value and saves it to the database.
Now try adding a value to your field and saving your post:

That works. Now let’s see how it looks on the site:

That doesn’t look so good. Because we used a name for the field of wpmu_weather
and not something more user-friendly, it’s not very nice to read. We could fix that by changing that name, but I’d rather not as it’s good practice to use a unique name with a suffix. So let’s change the way the metadata is output.