
Learning how to create custom WordPress meta boxes allow you to make professional UI elements for yourself and your clients. This WordPress meta box tutorial will show you how to add admin UI elements to the edit post/page screens.
Important Before you begin reading, you might want to read Take Your WordPress Meta Box to the Next Level. This PHP class will let you create meta boxes fast with the flexibility you need as a developer. Full documentation walks you step-by-step. Create custom WordPress Meta Box UI elements for your projects with ease.
Creating a custom WordPress meta box lets you make clean UI elements for you and your clients. The default WordPress custom fields are functional, but IMHO, and if you can pull it off, using a WordPress meta box is the way to go. It will give your project that professional touch.
This WordPress meta box tutorial will show you how to quickly add a clean UI for some custom fields. You will even learn how you can hide these fields and prevent them from appearing in the custom fields area.
Getting Started with WordPress Meta Boxes
The code for your meta box will pretty much go in one of two places: in a plugin file or in your functions.php file. This tutorial will cover the latter (for those of you creating plugins, you will be able to adapt the code for your use as well). I like tutorials with code examples and lots of comments, with that said, lets dive right in:
I recommend that you download the sample files or cut + paste the code and markup below in the appropriate places as indicated. There are three sample files (you will also need to create a folder and name it custom):
/current_theme_folder/functions.php /current_theme_folder/custom/meta.php /current_theme_folder/custom/meta.css
/current_theme_folder/functions.php file:
<?php
define('MY_WORDPRESS_FOLDER',$_SERVER['DOCUMENT_ROOT']);
define('MY_THEME_FOLDER',str_replace("\\",'/',dirname(__FILE__)));
define('MY_THEME_PATH','/' . substr(MY_THEME_FOLDER,stripos(MY_THEME_FOLDER,'wp-content')));
add_action('admin_init','my_meta_init');
function my_meta_init()
{
// review the function reference for parameter details
// http://codex.wordpress.org/Function_Reference/wp_enqueue_script
// http://codex.wordpress.org/Function_Reference/wp_enqueue_style
//wp_enqueue_script('my_meta_js', MY_THEME_PATH . '/custom/meta.js', array('jquery'));
wp_enqueue_style('my_meta_css', MY_THEME_PATH . '/custom/meta.css');
// review the function reference for parameter details
// http://codex.wordpress.org/Function_Reference/add_meta_box
// add a meta box for each of the wordpress page types: posts and pages
foreach (array('post','page') as $type)
{
add_meta_box('my_all_meta', 'My Custom Meta Box', 'my_meta_setup', $type, 'normal', 'high');
}
// add a callback function to save any data a user enters in
add_action('save_post','my_meta_save');
}
function my_meta_setup()
{
global $post;
// using an underscore, prevents the meta variable
// from showing up in the custom fields section
$meta = get_post_meta($post->ID,'_my_meta',TRUE);
// instead of writing HTML here, lets do an include
include(MY_THEME_FOLDER . '/custom/meta.php');
// create a custom nonce for submit verification later
echo '<input type="hidden" name="my_meta_noncename" value="' . wp_create_nonce(__FILE__) . '" />';
}
function my_meta_save($post_id)
{
// authentication checks
// make sure data came from our meta box
if (!wp_verify_nonce($_POST['my_meta_noncename'],__FILE__)) return $post_id;
// check user permissions
if ($_POST['post_type'] == 'page')
{
if (!current_user_can('edit_page', $post_id)) return $post_id;
}
else
{
if (!current_user_can('edit_post', $post_id)) return $post_id;
}
// authentication passed, save data
// var types
// single: _my_meta[var]
// array: _my_meta[var][]
// grouped array: _my_meta[var_group][0][var_1], _my_meta[var_group][0][var_2]
$current_data = get_post_meta($post_id, '_my_meta', TRUE);
$new_data = $_POST['_my_meta'];
my_meta_clean($new_data);
if ($current_data)
{
if (is_null($new_data)) delete_post_meta($post_id,'_my_meta');
else update_post_meta($post_id,'_my_meta',$new_data);
}
elseif (!is_null($new_data))
{
add_post_meta($post_id,'_my_meta',$new_data,TRUE);
}
return $post_id;
}
function my_meta_clean(&$arr)
{
if (is_array($arr))
{
foreach ($arr as $i => $v)
{
if (is_array($arr[$i]))
{
my_meta_clean($arr[$i]);
if (!count($arr[$i]))
{
unset($arr[$i]);
}
}
else
{
if (trim($arr[$i]) == '')
{
unset($arr[$i]);
}
}
}
if (!count($arr))
{
$arr = NULL;
}
}
}
?>
/current_theme_folder/custom/meta.php file:
<div class="my_meta_control"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras orci lorem, bibendum in pharetra ac, luctus ut mauris. Phasellus dapibus elit et justo malesuada eget <code>functions.php</code>.</p> <label>Name</label> <p> <input type="text" name="_my_meta[name]" value="<?php if(!empty($meta['name'])) echo $meta['name']; ?>"/> <span>Enter in a name</span> </p> <label>Description <span>(optional)</span></label> <p> <textarea name="_my_meta[description]" rows="3"><?php if(!empty($meta['description'])) echo $meta['description']; ?></textarea> <span>Enter in a description</span> </p> </div>
/current_theme_folder/custom/meta.css file:
.my_meta_control .description
{ display:none; }
.my_meta_control label
{ display:block; font-weight:bold; margin:6px; margin-bottom:0; margin-top:12px; }
.my_meta_control label span
{ display:inline; font-weight:normal; }
.my_meta_control span
{ color:#999; display:block; }
.my_meta_control textarea, .my_meta_control input[type='text']
{ margin-bottom:3px; width:99%; }
.my_meta_control h4
{ color:#999; font-size:1em; margin:15px 6px; text-transform:uppercase; }
If you’ve set everything up correctly you should see the following meta box in a edit post or edit page screen:

Using The Meta Box Values In Your Template
Being able to create the values is just the first part, now you need to do something with those values. Most likely you will be displaying the values in your post or page templates.
Remember the example above uses a single variable (_my_meta) to store values as an array, so when you get the meta value back from WordPress it will be an array and you will have to access the values using array syntax. Doing this is pretty straight forward:
$my_meta = get_post_meta($post->ID,'_my_meta',TRUE); echo $my_meta['name']; echo $my_meta['description'];
The global $post variable should always be available, but here are some other methods you can use to get the current post or page ID which you will need to use with get_post_meta():
// using $post global variable
echo $post->ID;
// get a page by its path (recommended over using a page ID)
$page = get_page_by_path('company/contact-us');
echo $page->ID;
// if you are working in the loop
echo get_the_ID();
The above code and markup will help you produce clean UI elements for your next WordPress project. Like any tutorial, consider this a starting point for you to do great things. I hope you’ve enjoyed!

I got an problem with the “function save_details(){
global $post;
update_post_meta($post->ID, “example”, $_POST["example"]);”.
Sometimes it just don’t save it, after I click “Update post”, it gone.
Any ideia?
Does the custom meta box appear for all posts and page dashboards in the admin? Can I have the meta box(es) appear in only certain type of pages?
Hello,
Thanks for a great tutorial. Everything is work for me. But there is one problem… how I add a select box in meta.php ? I add like:
Current Status
<option value="Pending">Pending
<option value="In Process">In Process
<option value="Shipped">Shipped
<option value="Delivereds">Delivered
Choose Status
but its not work. Please tell me how I add select, radio & checkbox ?
Thanks again.
Hello!
Thank you very much for this tutorial, you have just saved med allot of time on a project Im working on.
Wish you a great day and thank you again for your time and making your knowledge available to the rest of us.
Best regards Victor