Recently I set up a demo site for one of my plugins (Conditional Woo Checkout Field Pro). On the demo site I am using Ninja Demo, which is a great plugin for letting potential customers spin up quick preconfigured demo sites to try out a plugin. The plugin has a few steps I wanted to describe to the potential customer, and I also wanted to include a call-to-action “Buy Now” sort of button.
My initial thought was to add these as widgets on the dashboard using wp_add_dashboard_widget
, however I had three boxes and wanted to set each in a specific spot on the dashboard. Using wp_add_dashboard_widget
would only allow me to position these widget either all in the same column, or split between the first and second columns. I really didn’t like this idea because one of them would likely get missed as it would be pushed far down the dashboard page.
But, “the user can drag and drop the box wherever they want it to be“. Yea, I know this, but when dealing with short attention spans, that would assume that the user (a) knew that they could move it if they wanted to, and (b) knew that the extra widgets were even there to begin with.
Force Dashboard Widget Positions
I knew that once a user changes the widget positions on the dashboard, the order of the widgets gets saved in that user’s usermeta. I logged in with my administrator account and set up the metaboxes the way I wanted them to be. Then I logged into my site’s phpMyAdmin and found my account’s usermeta row for meta_key meta-box-order_dashboard
. It looked something like this:
a:4:{s:6:"normal";s:18:"custom_help_widget";s:4:"side";s:23:"conditional_help_widget";s:7:"column3";s:20:"override_help_widget";s:7:"column4";s:0:"";} |
Looks like a bunch of gibberish, but if we break it down, it’s actually not that bad. The data is “serialized”, which adds a bunch of stuff that you won’t need to really worry about because WordPress handles adding it in for us.. Basically all the ‘a:’ and ‘s:’ followed by numbers both indicate the size of the respective elements. ‘a’ gives the size of the array (in this case 4), and ‘s’ gives the number of characters in the string that follows (s:6 for the word “normal” because “normal” has 6 characters).
That whole last paragraph is informational only – you don’t really need to know that stuff for this tutorial.
The strings above are key/value pairs so 'normal' => 'custom_help_widget'
is one pair. We’ll need these pairs in just a minute.
So now we need to make sure that anytime someone accesses the dashboard, their usermeta has the same order set as my account did.
I created a custom plugin, which housed this function.
add_action( 'admin_init', 'set_dashboard_meta_order' ); function set_dashboard_meta_order() { $id = get_current_user_id(); //we need to know who we're updating $meta_value = array( 'normal' => 'custom_help_widget', //first key/value pair from the above serialized array 'side' => 'conditional_help_widget', //second key/value pair from the above serialized array 'column3' => 'override_help_widget', //third key/value pair from the above serialized array 'column4' => '', //last key/value pair from the above serialized array ); update_user_meta( $id, 'meta-box-order_dashboard', $meta_value ); //update the user meta with the user's ID, the meta_key meta-box-order_dashboard, and the new meta_value } |
I should probably stop here and make sure everyone is on the same page with where some of this data is coming from. The dashboard has four columns.
Normal = the far left column on the dashboard.
Side = the second from the left column on the dashboard.
column3 = the third column.
column4 = the…wait for it…fourth column at the far right.
When I setup my custom widgets, I gave them the id’s custom_help_widget
, conditional_help_widget
, and override_help_widget
. This is how I created those widgets:
add_action( 'wp_dashboard_setup', 'cwcfp_dashboard_widgets' ); function cwcfp_dashboard_widgets() { wp_add_dashboard_widget('custom_help_widget', 'Conditional Woo Checkout Field Pro Demo', 'custom_dashboard_help' ); wp_add_dashboard_widget('conditional_help_widget', 'Create Conditional Fields', 'conditional_dashboard_help' ); wp_add_dashboard_widget('override_help_widget', 'Override Default Fields', 'override_dashboard_help' ); } |
I also removed all of the default meta boxes, so all I had were my three custom widgets. Removing the default boxes is not the purpose of this article though. You can read about removing meta boxes here.
OK, back to the regularly scheduled programming.
With the set_dashboard_meta_order
function above, anytime someone visits the admin side of the site, their usermeta will get updated with the widgets in the order I want them to be.
Downside to Forcing Dashboard Widget Positions
The downside to this is your site’s users will never be able to save the dashboard widgets in the order that they want them in. This could get frustrating for your users, so use this method sparingly.
Another possible method is to check to see what the default widget positions are when a new user first visits the dashboard. You can use this in the update_user_meta
, by adding a fourth parameter for the previous value. This would look at the previous value and only change it if it is what you’re expecting it to be – in this case the default layout of your dashboard widgets.
What if we have 5 custom widget? i tried to write values as an array by returned an error. For example i need to set x and y widgets in column3. what should i do?
Good question! While I haven’t tested this myself, I believe all you need to do is add a comma separated list of widgets in the array. So for example:
add_action( 'admin_init', 'set_dashboard_meta_order' );
function set_dashboard_meta_order() {
$id = get_current_user_id(); //we need to know who we're updating
$meta_value = array(
'normal' => 'widget_one,widget_five', //first key/value pair from the above serialized array
'side' => 'widget_two', //second key/value pair from the above serialized array
'column3' => 'widget_three', //third key/value pair from the above serialized array
'column4' => 'widget_four', //last key/value pair from the above serialized array
);
update_user_meta( $id, 'meta-box-order_dashboard', $meta_value ); //update the user meta with the user's ID, the meta_key meta-box-order_dashboard, and the new meta_value
}
This should put widgets one, two, three, and four across the top, and widget five will be below widget one on the far left.
This work an absolute treat! Thank you very much. And I can confirm the multiple widgets per column edit worked too! Good work
Thank you for sharing this! I’ve been looking for a way to force a support info widget into the first widget position because as you said yourself attention spans are short. The benefit here far out weighs the downside.
Thank you!!
But I’m trying to discover how to put a meta box at the very top, and span the columns of the dashboard. I tried your code, and it puts my widget at the top, but not the very top. For example, after a WordPress update, the WordPress banner “Welcome to WordPress” appears at the very top and all of the other widgets are below that, including the one I wanted to move to the top.
For my purposes, I just want to put my Plugin’s widget at the top, initially, after plugin activation. After that, if the user wants to move it around or — gasp — hide it, I’m okay with that. You could do something similar, letting the user move the widgets around the way they want after you have forced your widgets to the top, and just revisit the order periodically when there’s something important to convey to the user.
It looks like you probably want something like this: https://www.engagewp.com/how-to-create-full-width-dashboard-widget-wordpress/
Hello. Is there a way to make that widgets collapsed too? Thanks.
Thank you, Scott. Your post helped me a lot.
I also made a little adjustment to your code in order to first get the order from user options and only then overwrite it. This way, we don’t mess up user’s order, “just” add our widget always on top.
I am sure that the code could be improved, but as a general concept you can use it from here: https://gist.github.com/swoboda/0012700c7f0d00ab8190f002dd14485b