How to use Wordpress Metaboxes at own plugins
codestyling | 22. February 2009 | 02:38
Starting with WordPress Version 2.7 a new kind of metabox handling has been occured at Backend. You are now able to drag/drop or hide this Boxes. This makes daily work easier.
But there is currently insufficient documentation available, how this metaboxes can be used at your own plugin pages. I try here to explain the needed functions and have written a demo-plugin for download based on this articles information. Feel free to inspect it after reading the article, it may help you understand the concept.
Requirements
At the following article i will explicitely write about WordPress version 2.7 and higher. Older versions of WordPress are unsuitable for this because they lack of available functions. Some have been first introduced with 2.7 so i didn’t spend the time creating this backward compatible even it would be possible with a lot of costs.
I also skipped the gettext functionality for this demo because the plugin is a how to example and showcase. It’s much easier to understand, if it only contains the nessessary metabox stuff.
Function Description
As first step into this topic i will briefly show the available WordPress functions, here they are:
| PHP | |
1 2 3 4 5 | function add_meta_box($id, $title, $callback, $page, $context = 'advanced', $priority = 'default') function do_meta_boxes($page, $context, $object) |
| timing: 0.035s | |
Function: add_meta_box
Using the function add_meta_box(…) you will register a new metabox at WordPress can be used by any page that matches with the given parameters.
The parameter $id is the unique identification for this registered metabox.
With the $title parameter you specifiy, what should be shown at the header of metabox. It is recommended that you use gettext based text here to permit a translation of your box title with language files.
The value $callback expects a callback function. It will be called by WordPress whever the content of this box has to be shown and should directly output the markup needed.
With the parameter $page you define the page, where this metabox is intended to be appearing. This implies also that your metabox can be shown at other plugin or core pages, if you know the exact parameter therefor.
The value $context will be used to define the context in which the box is intended to be appearing. In most cases this will be used to separate between content boxes and sidebar boxes.
Using $priority gives you the limited control in what order the boxes at the same context will be shown. Available values are: ‘high’, ‘core’, ‘default’, ‘low’.
Function: do_meta_boxes
If you call the function do_meta_boxes(…) the WordPress core generates and outputs all parameter matching metaboxes have been prior registered.
The value $object if free for use and intendend for programmers to handover additional informations into the metabox callbacks they may need to generate their content.
Metabox - content generation callback function
| PHP | |
1 2 3 4 5 6 7 8 9 10 11 | <?php function on_contentbox_1_content($data) { sort($data); ?> <p> The given parameter at <b>sorted</b> order are: <em><?php echo implode(' | ', $data); ?></em> </p> <?php } ?> |
| timing: 0.034s | |
At this example you will find the parameter $object as Array of strings ($data parameter) passed over to be used inside content generation. You can freely pass any kind ob object into the callbacks, it’s mostly the choise of programmer.
If you think about the admin center page “Write Post” the passed object is there the post object itself ($post).
Metabox Registration - importance of when to execute
You can register our own metabox at 2 different points in time:
- WordPress tells you, that it is currently loading your plugins page
- during the output of your own plugin page
This difference of point in time determines if this box can be hidden using the Screen Options menu or not. Boxes that have been registered during load indication call of this plugin page can be hidden using the checkboxes. If you register your metabox during output of your plugin page content but prior to your call to do_meta_boxes(…), you can’t hide this box at this page it is always visible and no checkbox appears therefor.
You don’t have to deal with the mechanism how to get the checkboxes for hiding in place, the WordPress core does this automatical for you and provides the boxes at tab Screen Options without any further programming.
Javascript is nessessary to get show/hide and drag/drop
If you have implemented all your stuff until this point you may wonder, why the boxes can’t be dragged , why WordPress not remembers which have been switched off (hidden) and why it ignores the collapsed state. This is related to some Javascript Magic we have to introduce as next.
| PHP | |
1 2 3 4 | wp_enqueue_script('common'); wp_enqueue_script('wp-lists'); wp_enqueue_script('postbox'); |
| timing: 0.034s | |
This named scripts have to be used inside your plugin page to get the effects and capabilities working. But the scripts do nothing, if they haven’t been initialized. This mostly will be done by inline javascript code like this:
| Javascript | |
1 2 3 4 5 6 7 8 9 10 11 | <script type="text/javascript"> //<![CDATA[ jQuery(document).ready( function($) { // close postboxes that should be closed $('.if-js-closed').removeClass('if-js-closed').addClass('closed'); // postboxes setup postboxes.add_postbox_toggles('<?php echo $this->pagehook; ?>'); }); //]]> </script> |
| timing: 0.005s | |
Example Screenshots of Demo-Plugin
Pictures are better than text. I have created 2 screenshots to illustrate what you can expect from this demo plugin, one as overview and an other with expanded Screen Options configuration:

Update: Modification for WordPress 2.8 new Metabox Model
The upcomming WordPress version 2.8 will change the handling of meta boxes while new column relations will be introduced. The following screenshot illustrates, what can be found now additionally at the settings tab slider:

That’s why it is necessary to handle this new behavoir. If this would not be changed, WordPress 2.8 versions won’t show any right sidebar for metabox content! It requires as first and new filter to be registered:
| PHP | |
1 2 3 4 5 6 7 8 9 | add_filter('screen_layout_columns', array(&$this, 'on_screen_layout_columns'), 10, 2); ... //for WordPress 2.8 we have to tell, that we support 2 columns ! function on_screen_layout_columns($columns, $screen) { if ($screen == $this->pagehook) { $columns[$this->pagehook] = 2; } return $columns; } |
| timing: 0.036s | |
Inside the filter method the array must be modified to stored the ammount of columns will be supported by this admin page (in this case 2 - content and right sidebar). But that’s not enough. While rendering (output) the metaboxes, we have to respect the current user choosen number of columns. Dependend on that number we must extend a HTML element with an additional class name:
| PHP | |
1 2 3 | global $screen_layout_columns; ... <div id="poststuff" class="metabox-holder<?php echo 2 == $screen_layout_columns ? ' has-right-sidebar' : ''; ?>"> |
| timing: 0.034s | |
After all this changes the demo plugin now works with WordPress 2.7 and also upcomming WordPress 2.8 version. The download file below has been adjusted and contains the modifications too. The source code also contains additional comments.
Download the example plugin
Based on the explanations and for your more deeply understanding i have build a short package with a full functional plugin that demonstrates all what has been written here. The code is under GPL and can be used or modified as you need it.
If you want to honor this work, please leave a remark at your source code or link to my page. It’s up to you doing so or not.
Here is the download of this demo plugin: howto-metabox-plugin.zip (1624 downloads)






Ptah Dunbar
23.03.2009 | 23:21Thank you for explaining this function. This saved me hours of reverse engineering WP to figure out how it all works. You are officially, awesome.
reply »
edebiyat
16.04.2009 | 01:30this post very good
reply »
AussieDosh
29.04.2009 | 13:21Your example plugin is a very useful resource! The way that you have implemented your class is a good example of how to write an easy to maintain plugin. I am writing some of my own plugins at the moment and I decided to refactor my code after seeing your plugin.
Great stuff!
reply »
Romain
16.06.2009 | 23:03Thanks for this very cool article. It helps a lot to figure the use of metaboxes out
But what is the constant for? Why doesn’t the plugin work if it is changed?
reply »
Romain
16.06.2009 | 23:38Saw it. I didn’t see that it was used in the local plugin. I thought the core would handle it.
reply »
remote
28.06.2009 | 13:37thak you very, very much for this most useful demo!
reply »
Paul
30.06.2009 | 07:34Absolute Genius!
Total generosity.
Thanks!!
reply »
spg
24.07.2009 | 15:39Thanks a million!
reply »
Ade
09.08.2009 | 13:28Heiko,
Thanks for a great write-up and download - I’ve been searching for this kind of information everywhere.
Just a couple of questions though…
1. I notice that if a user clicks 1 Column in the Screen Layout option in the meta tab, the “sidebar” disappears and can’t be reloaded, even ona browser refresh. Something isn’t right there.
2. Do you know how to hook in to the Contextual Help tab? This would be a great thing to be able to do for plugin admin pages.
Thanks again!
Ade.
reply »
Ade
10.08.2009 | 15:16Hi Heiko,
Me again
OK, I figured out question #1 in my earlier comment. I just avoided setting up 2 columns by changing the value of $column in the on_screen_layout_columns function.
So, thanks to your excellent article, I’m almost there. The only problem I now have is the action hook for saving options entered in one of the metaboxes. In this line:
is admin_post_save_howto_metaboxes_general a valid hook? I don’t think it is, which is why my options aren’t saving.
Any assistance you can offer is much appreciated!
Also, your language management plugin looks very interesting and I shall be trying it out on several bilingual sites I look after.
Thanks!
Ade.
reply »
Tony Dew
16.11.2009 | 19:28Wow! This is absolutely perfect! Thank you very much.
reply »
Upekshapriya
28.11.2009 | 04:53Very helpful tutorial. However it has the same issue that I have found when implementing this in my own plugin - if I drag a box to a new position it doesn’t stay there but springs back to its original position after I’ve pressed the save button. I am using 2.8.4.
Do you know of a way to keep the positions of the boxes after save?
reply »
mohsen
02.12.2009 | 16:57Thanks thanks thanks for million times. You really helped me a lot. thanks again
reply »
Marco Cimmino
17.02.2010 | 00:14Good article I wonder few things:
1. can be initialized that all boxes are closed by default and they do not remember their states?
2. can be switched off the possibility to move the boxes?
3. what are the hidden fields you added? Seems some are required, some not.
reply »
chris
31.05.2010 | 07:18Thanks so much for putting this up - excellent tutorial, the best I’ve found for metaboxes (and plugin layout actually!) One question - what if you don’t want *any* of the metaboxes to be able to be turned off? If you move all the add_meta_box calls from on_load_page to on_show_page then the sidebox metaboxes no longer show! What’s up with that?
Thanks : )
reply »
Burner
11.06.2010 | 02:27Hello. I have two questions:
1. How can you toggle a meta-box by default? In your example, the meta-boxes are open. I want to close 2-3 meta-boxes by default.
2. How can you start with 1 column layout selected? I want to start with 1 layout column and let the user to choose the 2 layout column.
Thanks.
reply »
strip that fat
25.07.2010 | 23:57I know this is an old post, but it seems to work with wordpress 3.0 I been searching for a while to figure out how to do this.. Thanks.
Is there any real changes or best practices for wp 3.0 ? Or is it all the same since 2.8 ?
reply »
Radhe
30.07.2010 | 12:32Absolute Genius
For the past 2 days I was trying to reverse engineer dashboard.php, and suddenly you came along and saved me.
This tutorial is awesome and demo plugin is pure generosity for the WP developer community.
You ROCK.
reply »
ผลบอล
19.01.2011 | 05:41what if you don’t want *any* of the metaboxes to be able to be turned off? If you move all the add_meta_box calls from on_load_page to on_show_page then the sidebox metaboxes no longer show! What’s up with that?
reply »
codestyling
25.05.2011 | 08:32There is no preoblem with it. I moved sidebar 2 to on_show_page and it will be excluded from disabling but still shown. If you move it after you did disable it, it will diappeare for sure. Please enable it and move it afterwards to the show method. If it doesnt help, than something else running at your blog damages the functionality.
reply »
ketan mujumdar
15.02.2011 | 08:40More information abt metabox
http://techwithketan.wordpress.com/2011/02/09/adding-metabox-in-post/
reply »
estetik burun
14.04.2011 | 08:46Very useful tutorial for me.
reply »
Christopher Ross
19.05.2011 | 14:13Wonderful Helen! Absolutely wonderful. I struggled to simplify this process for several of my own plugins, now thanks to you the new releases will have a great new process. I really appreciate this sample.
reply »
Devcorn
24.05.2011 | 18:09excellent article,
but one thing which, I would like to correct.. you don’t need to initialize jquery and other scripts. not sure if it is changed after 2.8. the initialize code break the toggle feature. please let me know if I am missing something.
reply »
codestyling
25.05.2011 | 08:21The jquery initialization has to be done always, please look at the main core pages too. It owrk perfectly at my single and multisite installations upto WP 3.1.2 with no feature break.
May be you have got a theme or plugin loading it’s own jquery version not only for frontend but also at any backend pages which is the most common mistake theme writers (and also plugin writers) do at the moment!
Please check it with firebug.
reply »
Devcorn
14.08.2011 | 18:02If you call only
wp_enqueue_script(’dashboard’);
there is no need to call other scripts and also you don’t require to initialize Jquery. The code will be more optimized with less calls.
Thanks
DevCorn
reply »
Ryan
24.06.2011 | 18:57These boxes are a right nightmare.
I’ve written the code from other plugins, blank page.
Just copied and pasted all your code into my own plugin, blank page.
I have error reporting on too so there are no errors, just a nothing. It’s taking hours, a whole day but I’ll this working if it takes me a week lol
Thanks for the help
reply »
Ryan
24.06.2011 | 19:14Does anyone have an example that does not use the entire script within the plugins main page?
Most plugins I find don’t do it this way, this would be suitable for the most simple of plugins. Problem with more advanced plugins is the code is split up into various files its not easy getting to grips with how each developer has applied this.
I can make it work simply by adding the example to my plugins main file but if I put the code into a separate page I find it impossible to get working. Nothing shows in the content area at all.
I will pay someone to get this working for me.
reply »
cupcake
23.10.2011 | 19:25Good article I wonder few things:
1. can be initialized that all boxes are closed by default and they do not remember their states?
2. can be switched off the possibility to move the boxes?
3. what are the hidden fields you added? Seems some are required, some not.
reply »
ken shoufer
03.12.2011 | 17:52Thanks for the tutorial. The sample code still works as of version 3.2.1.
reply »
khushbu
26.12.2011 | 09:26Hi
Thanks ,Such a nice plugin.
i can’t see sidebar after activate this.
plz help me…
reply »