WordPress Development for Intermediate Users: Custom Fields and Metadata
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.
Missed a tutorial in our WordPress Development for Intermediate Users series? You can catch up on all seven posts here:
- WordPress Development for Intermediate Users: Theme Development in Detail
- WordPress Development for Intermediate Users: Making Your Themes Customizer-Ready
- WordPress Development for Intermediate Users: Building Plugins
- WordPress Development for Intermediate Users: Custom Post Types and Taxonomies
- WordPress Development for Intermediate Users: Queries and Loops
- WordPress Development for Intermediate Users: Custom Fields and Metadata
- WordPress Development for Intermediate Users: Internationalization
That’s right, tons of WordPress knowledge, peer review, instructor feedback and certification, for free for WPMU DEV members
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:
- 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:
- Next, add the
the_meta()
function inside a div:
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:
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:
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:
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:
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.
Outputting Metadata with More Control
To add more control to the output of metadata, we replace the_meta()
with some more content using the get_the_meta()
function.
Let’s add this to our plugin and then activate it via the wpmu_after_content
hook in our theme. If your theme doesn’t have an action hook after the content, add one. You learned how to do this in part one of the series.
In your plugin, add this function:
Here’s what the function does:
- It checks if we’re on a single post.
- If so, it defines the
$weather
valuable usingget_post_meta()
. Note that to fetch the ID of the current post I’ve usedget_the_ID()
because we’re not in the loop. - It then creates a div and an unordered list, and in the first list item outputs a span followed by the value of the
$weather
variable. - It attaches the function to the
wpmu_after_content
hook. I’ve used a priority of5
so that this is displayed before anything else I’ve attached to that hook.
Because I’ve used the same classes as WordPress does with the the_meta()
function, the styling works fine. If you prefer, you can add this styling to your plugin. The demo plugin in the source files has an empty stylesheet that I’ve enqueued following the technique you learned earlier in this series – feel free to add your own styling to it.
Here’s my metabox on the site:

Right now there are two boxes with metadata – I’ll comment out the code for the first one in the theme so it’s still there for reference but doesn’t output anything. You might want to delete yours.
Hiding the Custom Fields Interface
We noticed earlier that our new custom metadata field was showing up twice on the post editing screen – in our new metabaox and in the custom field interface. Let’s hide the custom field interface to fix this problem.
In your plugin, add this:
Now if you visit your post editing screen, all you can see is the metabox you added:

That gives us more control – users will only have access to the metadata field we’ve created.
Displaying Other Kinds of Metadata
So far we’ve focused on post metadata (or custom fields). But WordPress also stores metadata for other content types, namely users, comments and taxonomy terms.
You’ve already learned how to output some term metadata in part four of this series, when you output the term description on its archive page, using the term_description()
function. Here’s what this looks like:

Let’s take a look at user metadata. This is metadata about all your site’s users, whatever their role, but the most common use for it is in providing information about authors. Each author on your site will have their own author archive, and by adding user metadata to this you can give your readers information about authors. You can also add author metadata to single posts.
Let’s add some author metadata to our loop-single.php template file, along with some post metadata with information about the date the post was written.
- In your theme, open the loop-single.php file.
- Find the
<h1>
element. - Below it, add this:
- Save the file.
This displays the author’s name and the date on which the post is written. Because I’ve included a conditional tag, it only does this on posts, not projects.
Note: You may have noticed that there are now two conditional tags in our loop-single.php file. You might prefer to create a different version of this file for each post type. You should be able to work out how to do this using what you learned in part one of this series about the template hierarchy.
The author and date are now displayed on my site:

Let’s make it a bit more helpful, by including a link to the author’s archive page. You do that by replacing the the_author()
tag with the_author_posts_link()
.
Edit your code so it reads like this:
Now the author’s name is displayed with a link:

Extra Challenge: Displaying Taxonomy Terms
You can also display metadata relating to taxonomy terms – you should remember learning about that earlier in this series. Why not try applying what you’ve learned in the previous part on working with custom taxonomies to your loop-single.php file, and adding the taxonomy terms for the post to the single post page.
I’m not going to work through this in detail but I will give you some hints:
- For taxonomy terms, you’ll need to use
get_the_term_list()
which you used in the previous part of this series. - For categories, you can use
get_the_category_list()
– although I prefer to useget_the_term_list()
as it’s easier to work with. - For tags, use
get_the_tag_list()
orget_the_term_list()
.
If you get stuck doing this, check out the source code. I’ve also added some styling to my metadata. Here it is:

Feel free to add whatever metadata you want to your post and style it more imaginatively than I have!
Metadata Adds an Extra Layer to Your Data
Metadata is another way to get even more control over your data in WordPress. Use it for extra information about users, comments, taxonomy terms and posts themselves, and you can then puppet it in your theme or plugin however you want.
In this part of the series, you’ve learned what metadata is and how to create a metabox for adding it to posts. You’ve also learned how to display other kinds of metadata about a post.
Why not try experimenting with more metadata in your theme?