Editors can’t fill in data they can’t see. If your site stores an ISBN, a price, or a project deadline on each post, that field needs a place on the edit screen. That’s what add_meta_box() is for. It adds a custom panel to the post editor, and it has been part of WordPress since version 2.5.0.
In this guide, you’ll learn the function’s parameters and how to register, render, and save a meta box safely. The examples use a custom book post type with an ISBN field.
What Is add_meta_box()?
A meta box is a panel in the post editor that holds fields. WordPress uses them for Categories, Tags, and Featured Image. add_meta_box() registers your own panel. It doesn’t output HTML or save data, so you write those parts in separate functions.
The function accepts seven parameters:
<?php
add_meta_box(
$id,
$title,
$callback,
$screen = null,
$context = 'advanced',
$priority = 'default',
$callback_args = null
);| Parameter | Required | Purpose |
|---|---|---|
| $id | Yes | Unique HTML ID for the box wrapper. |
| $title | Yes | Heading shown above the box. |
| $callback | Yes | Function that outputs the box HTML. |
| $screen | No | Post type slug, or an array of slugs since WordPress 4.4.0. Defaults to the current screen. |
| $context | No | Where the box appears: normal, advanced, or side. |
| $priority | No | Order within the context: high, core, default, or low. |
| $callback_args | No | Extra data passed to the callback in $box['args']. |
How to Add a Meta Box
Every meta box has three parts: a registration function, a render callback, and a save function. Put all three in a plugin or in your child theme’s functions.php.
Step 1: Register the Meta Box
Hook into add_meta_boxes, which fires only on edit screens. Pass the post type slug as $screen, then attach your function with add_action().
<?php
function andriy_add_book_meta_box() {
add_meta_box(
'andriy_book_details',
'Book Details',
'andriy_render_book_meta_box',
'book',
'side',
'default'
);
}
add_action( 'add_meta_boxes', 'andriy_add_book_meta_box' );Step 2: Build the Callback
WordPress passes the current $post object to the callback. Output a nonce field so the save step can confirm the request came from your form. Then print the input with its saved value.
<?php
function andriy_render_book_meta_box( $post ) {
wp_nonce_field( 'andriy_save_book_details', 'andriy_book_nonce' );
$isbn = get_post_meta( $post->ID, 'andriy_isbn', true );
echo '<p><label for="andriy_isbn">ISBN</label></p>';
echo '<input type="text" id="andriy_isbn" name="andriy_isbn" value="' . esc_attr( $isbn ) . '" class="widefat">';
}Step 3: Save the Data
Hook save_post_book so the function runs only when a book is saved. Before writing anything, verify the nonce, skip autosaves, and confirm the user can edit the post. Then sanitize the input and store it with update_post_meta(). For more on nonces, read our WordPress nonce guide.
<?php
function andriy_save_book_details( $post_id ) {
if ( ! isset( $_POST['andriy_book_nonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['andriy_book_nonce'] ) ), 'andriy_save_book_details' ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['andriy_isbn'] ) ) {
update_post_meta( $post_id, 'andriy_isbn', sanitize_text_field( wp_unslash( $_POST['andriy_isbn'] ) ) );
}
}
add_action( 'save_post_book', 'andriy_save_book_details' );Choose the Context and Priority
The context controls where the box appears in the classic editor. normal places it in the main column below the content, advanced sits below the normal boxes, and side places it in the right-hand column. Use side for short fields like an ISBN or a status. Use normal for longer inputs such as a description.
Priority orders boxes within the same context. Leave it at default unless your box needs to sit above or below another one.
Common Mistakes With add_meta_box()
- Registering on init. Use the
add_meta_boxeshook instead.initruns on every request, including the front end, which adds needless work. - Skipping the nonce. Without
wp_verify_nonce(), a form submitted from another page can overwrite your data. - Missing capability check.
current_user_can( 'edit_post', $post_id )stops users without edit rights from changing the value. - Saving on autosave. Autosaves trigger
save_posttoo. CheckDOING_AUTOSAVEso you don’t write partial data. - Printing raw values. Escape output with
esc_attr()so a stored quote can’t break the HTML.
Tip: Use
add_meta_boxes_bookinstead ofadd_meta_boxeswhen the box should appear for one post type only. WordPress fires it only for that type, so you don’t need a check inside the function.
FAQs About add_meta_box()
Can I add a meta box to a custom post type?
Yes. Pass the post type slug as $screen, as in Step 1, and hook save_post_{post_type} to save the data, as in Step 3.
Do meta boxes work in the block editor?
Yes. Classic meta boxes still render in the block editor. For fields that should be native to the block editor, register them with register_post_meta() and set show_in_rest to true.
How do I remove a meta box?
Call remove_meta_box() with the same ID, screen, and context you used to register the box. Hook it to add_meta_boxes too, so it runs after the box is added.
Why isn’t my meta box showing?
Check three things: the function is hooked to add_meta_boxes, the $screen value matches the post type slug exactly, and the box isn’t hidden in the Screen Options panel at the top of the editor.
Conclusion
The add_meta_box() function is the foundation of custom admin fields in WordPress. Register the box on add_meta_boxes, render it with a nonce, and save with a nonce check, a capability check, and sanitized input. Those three steps cover most real projects.
If you need custom fields across a larger plugin, or a data-entry workflow for your team, explore my WordPress plugin development services or reach out to me directly.

