Custom Meta Box in WordPress: Classic & Gutenberg
This guide shows you how to create a custom meta box that works in both the Classic Editor and Gutenberg (block editor) in WordPress. You’ll learn to add a simple text field to a post edit screen, save the data safely, and display it on the front end. You’ll need a basic understanding of PHP and a WordPress site where you can add code (e.g., a child theme’s functions.php or a custom plugin).
What You’ll Need
- A WordPress site (self-hosted) with admin access.
- A code editor (like VS Code, Sublime Text, or Notepad++).
- FTP or file manager access to your theme files, or the ability to create a custom plugin.
- Basic knowledge of PHP and WordPress hooks.
Step-by-Step
- Decide where to put the code. The safest method is to create a custom plugin. If you prefer a theme, use a child theme so updates don’t erase your code. For this guide, we’ll assume a custom plugin file called
custom-meta-box.php. - Create the plugin file (if using a plugin). Add a header to the file:
<?php /* Plugin Name: Custom Meta Box */ ?>. This makes WordPress recognize it as a plugin. - Hook into
add_meta_boxes. This action registers your meta box. Add this code:add_action('add_meta_boxes', 'my_custom_meta_box'); function my_custom_meta_box() { add_meta_box( 'my_meta_box_id', // Unique ID 'Custom Meta Box', // Title shown in editor 'my_meta_box_callback', // Callback function that renders the box 'post', // Screen: 'post', 'page', or custom post type 'side', // Context: 'normal', 'side', 'advanced' 'default' // Priority: 'high', 'core', 'default', 'low' ); } - Render the meta box fields. Create the callback function that outputs the HTML. It should include a nonce field for security. Example:
function my_meta_box_callback($post) { wp_nonce_field('my_meta_box_nonce', 'my_meta_box_nonce_field'); $value = get_post_meta($post->ID, '_my_meta_value', true); echo '<label for="my_meta_field">Enter something:</label>'; echo '<input type="text" id="my_meta_field" name="my_meta_field" value="' . esc_attr($value) . '" style="width:100%" />'; } - Save the data. Hook into
save_post. Verify the nonce, check autosave, and check user permissions before saving. Example:add_action('save_post', 'my_save_meta_box_data'); function my_save_meta_box_data($post_id) { // Check nonce if (!isset($_POST['my_meta_box_nonce_field']) || !wp_verify_nonce($_POST['my_meta_box_nonce_field'], 'my_meta_box_nonce')) { return; } // Check autosave if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // Check permissions if (!current_user_can('edit_post', $post_id)) { return; } // Sanitize and save if (isset($_POST['my_meta_field'])) { $data = sanitize_text_field($_POST['my_meta_field']); update_post_meta($post_id, '_my_meta_value', $data); } } - Test in Classic Editor. Go to Posts → Add New. You should see your meta box in the sidebar (if you chose ‘side’) or below the content. Enter a value, publish, and check that it saves (edit the post again to see the value).
- Test in Gutenberg. The same meta box appears in the block editor’s sidebar under the ‘Post’ tab, usually in the ‘Meta Boxes’ section. It works the same way. If you don’t see it, click the three-dot menu in the top right → ‘Options’ → make sure ‘Meta Boxes’ is checked.
- Display the value on the front end. In your theme template (e.g., single.php), use
get_post_meta()to retrieve and display the value. Example:<?php $meta_value = get_post_meta(get_the_ID(), '_my_meta_value', true); if ($meta_value) { echo '<p>' . esc_html($meta_value) . '</p>'; } ?>
Common Mistakes
- Forgetting the nonce – This leaves your site vulnerable to CSRF. Always include and verify a nonce.
- Not checking autosave – Without it, your data might be overwritten with empty values during autosave.
- Not sanitizing input – Always sanitize data before saving to prevent security issues.
- Using the same meta key for different post types – This can cause conflicts. Use a unique prefix.
- Outputting unsanitized data – When displaying, use
esc_html()oresc_attr()to prevent XSS.
Tips
- Use a prefix for meta keys – e.g.,
_my_meta_value(leading underscore hides it from the custom fields dropdown). - Make it reusable – Create a class or functions that can be easily extended for multiple meta boxes.
- Use
add_meta_boxfor custom post types – You can pass the post type slug instead of ‘post’ to show it only there. - Consider using the
rest_api_inithook if you need the meta box to work with the REST API (e.g., for Gutenberg’s block editor). - Test with both editors – Even though Gutenberg is the default, many users still use Classic Editor via plugin.
Troubleshooting
- Meta box doesn’t appear – Check that you’ve used the correct hook and screen. For Gutenberg, ensure the meta box is enabled in the options. Also, clear any caching plugins.
- Data not saving – Verify that the nonce field name matches in the form and the save function. Also check that the
save_posthook is firing (add a temporary error_log to debug). - Value disappears after update – This usually means the autosave check is failing or the data is being overwritten. Make sure you’re using
update_post_metaonly when the field is set. - Meta box shows in Classic but not Gutenberg – In Gutenberg, meta boxes are rendered in a separate section. Click the three-dot menu → ‘Options’ → ensure ‘Meta Boxes’ is checked. Also, some plugins might conflict; try disabling them temporarily.
- White screen after adding code – This is a PHP error. Check your site’s error log or enable WP_DEBUG to see the error. Common issues: missing semicolons, incorrect function names.
Frequently Asked Questions
Do meta boxes work in the block editor (Gutenberg)?
Yes, they work, but they appear in a separate ‘Meta Boxes’ panel in the sidebar. The functionality is the same, but the layout is different.
How do I add a meta box to a custom post type?
In the add_meta_box call, replace ‘post’ with your custom post type’s slug, e.g., ‘book’ or ‘product’.
Can I use meta boxes for pages?
Yes, just change the screen parameter to ‘page’ or use an array like array('post', 'page').
How do I remove a meta box?
Use remove_meta_box() inside a function hooked to add_meta_boxes. For example, remove_meta_box('my_meta_box_id', 'post', 'side');
Is it safe to use meta boxes with Gutenberg’s REST API?
Yes, but you need to register the meta field with register_post_meta() and set show_in_rest to true to make it available in the API.
Can I create a meta box with multiple fields?
Absolutely. In the callback function, output multiple input fields with different names. In the save function, handle each field separately.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.