Download today

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.

That’s right, tons of WordPress knowledge, peer review, instructor feedback and certification, for free for WPMU DEV membersStart Learning

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:

database structure diagram

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:

A post with no metadata added - editing screen

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):

A custom field added to the post editing screen

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.

  1. In your loop-single.php file, find this code:
    .gist table { margin-bottom: 0; }
  2. 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; }
  3. 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:

post metadata displayed below the post using the_meta()

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:

  1. It opens up a form element.
  2. 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.
  3. It uses get_post_meta() to retrieve the value of a new wpmu_weather field and assigns that value to the $weather variable.
  4. It creates a table for our field.
  5. It creates a field whose value is that $weather variable.
  6. 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:

A metabaox on the post editing screen - no value added yet

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:

  1. 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.
  2. It checks that the current user has the edit_post capability, in other words, that they’re authorized to do this.
  3. It checks if a new value has been added to our field.
  4. 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:

Post metabox with a value added

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

Post metadata from the metabox on the front end of 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.


WP Academy – WordPress Wisdom, Bitesized.

Structured e-learning to expand your WordPress and general business horizons. Learn from people like our very own CEO James Farmer with more than a decade’s experience running a WordPress Business!.


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:

.gist table { margin-bottom: 0; }

Here’s what the function does:

  1. It checks if we’re on a single post.
  2. If so, it defines the $weather valuable using get_post_meta(). Note that to fetch the ID of the current post I’ve used get_the_ID() because we’re not in the loop.
  3. 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.
  4. It attaches the function to the wpmu_after_content hook. I’ve used a priority of 5 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:

Post metadata displayed on the front end with more control

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:

.gist table { margin-bottom: 0; }

Now if you visit your post editing screen, all you can see is the metabox you added:

Post editing screen without the custom fields interface

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:

The term description on the term archive page

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.

  1. In your theme, open the loop-single.php file.
  2. Find the <h1> element.
  3. Below it, add this:
    .gist table { margin-bottom: 0; }
  4. 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:

The author name displayed below the post title

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:

.gist table { margin-bottom: 0; }

Now the author’s name is displayed with a link:

The author's name displayed below the post title with a link to the author archive page

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 use get_the_term_list() as it’s easier to work with.
  • For tags, use get_the_tag_list() or get_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:

The post author and categories displayed after the post title

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?

Related Posts


Submit a Comment

Your email address will not be published. Required fields are marked *