Dashboard Widget Generator
The widget your client actually looks at: gated by capability, filled by a real callback, and — optionally — the calls that clear the core boxes around it.
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). /** * Register the dashboard widget. */ function acme_setup() { if ( ! current_user_can( 'edit_posts' ) ) { return; } wp_add_dashboard_widget( 'acme_overview', __( 'Acme Overview', 'acme' ), 'acme_render', null, array(), 'normal', 'high' ); // Clear the core boxes the client does not use. remove_meta_box( 'dashboard_primary', 'dashboard', 'side' ); remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' ); } add_action( 'wp_dashboard_setup', 'acme_setup' ); /** * Print the widget body. */ function acme_render() { $posts = get_posts( array( 'post_type' => 'post', 'post_status' => 'draft', 'numberposts' => 5, 'orderby' => 'date', 'order' => 'DESC', 'suppress_filters' => false, ) ); if ( ! $posts ) { echo '<p>' . esc_html__( 'Nothing here yet.', 'acme' ) . '</p>'; return; } echo '<ul>'; foreach ( $posts as $post ) { printf( '<li><a href="%1$s">%2$s</a> <span class="post-date">%3$s</span></li>', esc_url( get_edit_post_link( $post->ID ) ), esc_html( get_the_title( $post ) ), esc_html( get_the_date( '', $post ) ) ); } echo '</ul>'; }
About this generator
Dashboard Widget Generator Online
Build a WordPress dashboard widget with wp_add_dashboard_widget() and get back a complete, commented file: the wp_dashboard_setup callback, a capability gate, the render function, and — if you want one — the Configure form behind the widget title with its own nonce check. Four content sources are built in: a single escaped paragraph, a get_posts() list with edit links, a cached wp_remote_get() stats call, or a saved option driven by the Configure form.
The Preview tab draws the widget as it will appear on the dashboard, in the column and at the priority you picked, next to the core boxes you chose to remove. Export as a snippet, a functions.php block or a plugin file, procedural or class. Free, no account, nothing uploaded.
Reviewed Output tested on WordPress 6.8 · PHP 8.3
Why the Dashboard Widget Generator beats a copied wp_add_dashboard_widget snippet
The three-argument version of wp_add_dashboard_widget() is easy and every tutorial shows it. What they leave out is that the widget id is global across every plugin on the site, that $context and $priority only exist from WordPress 5.6, that an uncached HTTP call in a render callback blocks the dashboard for every admin, and that a Configure form without a nonce is a write endpoint anyone can hit. This generator writes all of that in and then checks the result.
Column and priority, with the version caveat
Left, right, third and fourth columns at high, core, default or low priority. The $context and $priority arguments were only added in WordPress 5.6, so the checker says so whenever you move the widget off the defaults — below that version they are ignored and the box lands in the normal column.
Remote stats that cannot stall the dashboard
The remote source wraps wp_remote_get() in a transient with a timeout, handles is_wp_error() and a non-200 response code separately, and refuses to generate with no cache window — an uncached request in a dashboard widget makes every admin page load wait on someone else's server.
A Configure form with a real nonce
Turn on the config callback and you get the form behind the widget's Configure link, complete with wp_nonce_field(), a wp_verify_nonce() check on the POST, sanitize_text_field() on the value and an update_option() write. The checker also notices when the form saves a message the current content source never reads.
Core widgets cleared properly
Tick the core boxes you want gone and the generator emits remove_meta_box() with the correct context for each one — Quick Draft and Events and News are in the side column, Activity and At a Glance are not. Getting that argument wrong is why most removal snippets silently do nothing.
Honest about force-to-top
The generator will rewrite $wp_meta_boxes to pin your widget above everything else, and it warns you in the same breath that this overrides each user's own drag order on every dashboard load. Clients ask for it; a week later they ask why they cannot move it.
Prefix and capability checked
Dashboard ids are global, so an unprefixed id can silently replace another plugin's widget — flagged with a one-click prefix fix. A read capability is flagged too, because on a membership site that means every subscriber.
How does the Dashboard Widget Generator work?
Four steps. Name the widget, pick what it shows, decide which core boxes to clear, then check and export.
- 01
Name and place the widget
Set the widget id, title and function prefix, choose the capability that can see it, and place it in a column at a priority. The placement note under the field spells out what that combination means before a user drags it somewhere else.
- 02
Choose what it shows
Static copy, a recent-posts list, remote stats or a saved option. Each source reveals its own fields — post type, status and count for the query; endpoint and cache minutes for the remote call — and the generated render function changes to match.
- 03
Clear the core boxes
Optionally remove Activity, At a Glance, Quick Draft, Events and News, Site Health or the PHP nag. The checker pushes back on removing Activity and Site Health, since both hide information you will be asked about later.
- 04
Review the checks and export
Add the capability gate and Configure form if you need them, clear the warnings, then copy the snippet or download the file as a plugin or a
functions.phpblock.
Worked example — a static widget in the right column, editors and up
The complete output for a one-paragraph widget pinned to the side column at high priority. Note the seven-argument call: the fourth argument is the control callback, which must be null when you are not using one.
/**
* Register the dashboard widget.
*/
function acme_setup() {
if ( ! current_user_can( 'edit_posts' ) ) {
return;
}
wp_add_dashboard_widget(
'acme_overview',
__( 'Acme Overview', 'acme' ),
'acme_render',
null,
array(),
'side',
'high'
);
}
add_action( 'wp_dashboard_setup', 'acme_setup' );
/**
* Print the widget body.
*/
function acme_render() {
echo '<p>' . esc_html__( 'Everything is running. Nothing needs your attention today.', 'acme' ) . '</p>';
}Switch the source to a recent-posts list and acme_render() becomes a get_posts() call with suppress_filters => false, an empty-state message, and get_edit_post_link() on every row — a drafts list with working edit links is the widget clients actually use.
WordPress dashboard widgets — frequently asked questions
What developers ask most often when adding or removing boxes on the WordPress dashboard.
How do I show a dashboard widget only to administrators?
Wrap the wp_add_dashboard_widget() call in if ( ! current_user_can( 'manage_options' ) ) { return; } inside your wp_dashboard_setup callback. Gating the render function instead still registers the box, so other roles see an empty widget with a title. This generator emits the gate at registration time.
Why is my widget always in the left column even though I set the context?
The $context and $priority arguments of wp_add_dashboard_widget() were added in WordPress 5.6. On older versions they are ignored and the widget falls back to the normal column. Also remember that once a user drags a box, their own arrangement is stored in user meta and wins over your context on every later load.
How do I remove the default WordPress dashboard widgets?
Call remove_meta_box( $id, 'dashboard', $context ) on wp_dashboard_setup. The context has to match where core put the box: dashboard_quick_press and dashboard_primary are in the side column, dashboard_activity, dashboard_right_now and dashboard_site_health are in normal. Pass the wrong context and nothing happens, with no error.
How do I add the Configure link to a dashboard widget?
Pass a fourth argument to wp_add_dashboard_widget() — the control callback. Core then prints a Configure link in the widget header and renders your callback in place of the widget body when it is clicked. The form posts back to the same screen, so it needs its own nonce; the generator writes wp_nonce_field() and the matching wp_verify_nonce() check.
Can a dashboard widget fetch data from an external API?
Yes, but cache it. The render callback runs synchronously while the dashboard is being built, so an uncached wp_remote_get() adds its full round trip to every admin page load, for every admin. Store the decoded response in a transient with a sensible window, set an explicit timeout, and handle both is_wp_error() and a non-200 response code.
How do I force my widget to the top of the dashboard?
There is no argument for it — you have to reorder $wp_meta_boxes['dashboard'] yourself after core has populated it, moving your id to the front of the relevant context and priority bucket. It works, but it runs on every dashboard load and it overrides the position each user chose by dragging, which usually generates a support request.
Where do I paste the code from the Dashboard Widget generator?
You have three good options and one bad one. Best is a small site-specific plugin — the generator can output one for you, and it keeps working when you change theme. A code-snippets plugin is fine too. A child theme's functions.php works but ties the code to that theme. Never edit the parent theme: the next update overwrites it and your code is gone.
Can I use the generated code in client work or a commercial plugin?
Yes. The output is ordinary WordPress API calls that you configured — there is no licence attached to it and no attribution required. Use it in client sites, commercial plugins and themes, or products you sell. The generated file carries a short credit comment you are free to delete.
The other Admin generators in the library, plus the WordPress tools most often used alongside this one.