How To Add A Meta Box To WordPress

I needed to add a meta box to the WordPress editor for my pages.

Something that I could use to pull data from the post meta for that page, change it and update the post meta.

In its most basic form, I needed something like this:

Arrow pointing to basic WordPress meta box under the editor

How to add a meta box to WordPress

To add a WordPress meta box, you need to:

  1. Register your meta box
  2. Add an action connecting "add_meta_boxes" to your registration function
  3. Create a function connected to the registration function that renders the meta box

How to save and pull post meta data into your meta box

To save and pull the post meta data into the meta box you created, you need to:

  1. create a save function that checks for data in your meta box, sanitizes the data and pushes it to the post meta with update_post_meta
  2. hook that save function in with add_action to "save_post"

This is the code that does all of that:

add_action( 'add_meta_boxes', 'register_iw_meta_box' );
function register_iw_meta_box() {
  add_meta_box( 
    'iw_meta_box', 
    'Intelliwolf Meta Box', 
    'render_iw_meta_box',
	'page', 
    'normal',
    'low', 
    array( '__block_editor_compatible_meta_box' => true ) 
  );
}

function render_iw_meta_box( $post ) {
  $iw_meta = get_post_meta( $post->ID, 'iw_meta', true );
  echo "<p>Add Your Info</p>
    <input type='text' name='iw_meta_data' value='$iw_meta'>";
}

add_action( 'save_post', 'save_iw_meta_box' );
function save_iw_meta_box() {
  if (!isset($_POST['iw_meta_data'])) {
    return;
  }
  global $post;
  update_post_meta( 
    $post->ID, 
    'iw_meta',
    sanitize_text_field( $_POST['iw_meta_data'] ) 
  );
}

Just a word on the code style - many people put the hook that calls the function below the function. I prefer to put it above, so it's all right there. You don't notice it in small functions like here, but if you have something longer, it makes a big difference doing it this way.

Let's break the code down.

Register your meta box

function register_iw_meta_box() {
  add_meta_box( 
    'iw_meta_box', 
    'Intelliwolf Meta Box', 
    'render_iw_meta_box',
    'page', 
    'normal',
    'low', 
    array( '__block_editor_compatible_meta_box' => true ) 
  );
}

When called, this function will add a meta box with these arguments:

  1. iw_meta_box
  2. Intelliwolf Meta Box
  3. render_iw_meta_box
  4. page
  5. normal
  6. low
  7. array ( '__block_editor_compatible_meta_box' => true )

These have the following meanings:

  1. The id of the meta box. This needs to be unique because it will be the div ID upon render.
  2. The title that you'll see rendered as a H2 in the meta box
  3. This tells the meta box which function to use to output the contents of the meta box.
  4. Which screen to display the meta box on. In most cases, you're going to put 'post' or 'page' here. If you wanted both, you'd do it as array( 'post', 'page' ). You could also do comments or custom post types here.
  5. The position around the WordPress editor. Use 'normal' for below the editor like I have in the screenshot above, or 'side' to put it in the sidebar.
  6. The priority or ordering among the meta boxes. 'low' puts it below everything else. You could also do 'high', 'core' or 'default'. Just play with this to get it where you want it to display.
  7. The final one in this form says it's ok to use it on the normal block editor. You can also set it to only display on the classic editor if you need. You can use this array to pass other variables, if needed.

Hook into the registered meta box

We need to tell WordPress to run our registration function.

We add an add_action so that our registration function is called when WordPress runs the "add_meta_boxes" hook.

Make sure the second parameter here is the same as the registration function name.

add_action( 'add_meta_boxes', 'register_iw_meta_box' );

Render the meta box HTML

Now we need to output the HTML that will appear in the meta box.

function render_iw_meta_box( $post ) {
  $iw_meta = get_post_meta( $post->ID, 'iw_meta', true );
  echo "<p>Add Your Info</p>
    <input type='text' name='iw_meta_data' value='$iw_meta'>";
}

The function name here must match the third argument in the registration function.

If you just want to output a notice in your meta box, you don't need to add $post to the function argument.

Calling $post will bring in the full $post object, so you have full access to things like the post title, ID, etc.

In this example, we're getting the contents of the post meta that we save in a later function.

$iw_meta = get_post_meta( $post->ID, 'iw_meta', true );

The second argument in get_post_meta() is the meta key of the post meta that we save to the database.

Setting the third argument in get_post_meta() to true means we get just the post meta, rather than getting it in an array, which is the default. In 16+ years of building WordPress, I've never used anything but true here.

The rest of the code in this function is what goes into your meta box.

Note that in:

echo "<input type='text' name='iw_meta_data' value='$iw_meta'>";

I'm setting the value of the input to be what we've saved to the post meta for the current post.

If we've never saved anything in this field for this post, or it's blank, the value will just be blank, so you shouldn't run into any issues with error output here.

Because I'm only saving one field as a string, I don't need to do any further processing to make $iw_meta usable as a value in this input.

You'll have to split out the data from the array if you're saving multiple fields.

Next we move on to saving the data when the user inputs it.

Sanitize and save the post meta

function save_iw_meta_box() {
  if (!isset($_POST['iw_meta_data'])) {
    return;
  }
  global $post;
  update_post_meta( 
    $post->ID, 
    'iw_meta',
    sanitize_text_field( $_POST['iw_meta_data'] ) 
  );
}

First, we check if there is any post meta data to save, with

if (!isset($_POST['iw_meta_data']))

This conditional says "if there's no data to save..." then we immediately exit the function without doing further processing.

We use global $post; to get the data about the current post. We'll only usually need the post ID.

If you have more than just a simple text field like I've used in this example, you should go through the array and sanitize each field according to its type at this point.

Sanitizing is extremely important when saving anything to the database. Not doing so opens your database up to being hacked or corrupted.

We save the data to the database with update_post_meta().

The arguments are

  1. the post ID,
  2. the meta key (make sure it matches the key from rendering the HTML)
  3. the data we want to save to the post meta.

Add the save function to WordPress Hook

add_action( 'save_post', 'save_iw_meta_box' );

The final step is to connect the save function into the 'save_post' hook, so that it gets processed whenever the post or page is saved.

With all of that code, you should have a meta box with a bit of text and an input field below the editor when you edit a page.

WordPress meta box with winning in the input field

If you add anything to the input field and save the post, you will see that information be saved to the _postmeta table in your database for that post, listed under the meta key you set.

wp_postmeta table with row highlighted showing meta key iw_meta and meta value winning
Mike Haydon

Thanks for checking out my WordPress and coding tutorials. If you've found these tutorials useful, why not consider supporting my work?

Buy me a coffee

Leave a Comment