Toolbar Node Generator
Add a custom node to the admin bar, wire up its dropdown children, and clear the core nodes this site does not use.
<?php // Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). /** * Plugin Name: Acme toolbar node * Description: Adds the acme-tools node to the admin bar. * Version: 1.0.0 * Requires PHP: 7.4 * Text Domain: acme */ defined( 'ABSPATH' ) || exit; /** * Add the Acme node to the toolbar. * * @param WP_Admin_Bar $wp_admin_bar The toolbar instance. */ function acme_toolbar_node( $wp_admin_bar ) { if ( ! current_user_can( 'edit_others_posts' ) ) { return; } $wp_admin_bar->add_node( array( 'id' => 'acme-tools', 'title' => __( 'Acme', 'acme' ), 'href' => esc_url( admin_url( 'options-general.php?page=acme-toolkit' ) ), 'meta' => array( 'title' => __( 'Acme shortcuts', 'acme' ), ), ) ); $wp_admin_bar->add_node( array( 'id' => 'acme-settings', 'parent' => 'acme-tools', 'title' => __( 'Settings', 'acme' ), 'href' => esc_url( admin_url( 'options-general.php?page=acme-toolkit' ) ), ) ); $wp_admin_bar->add_node( array( 'id' => 'acme-clear-cache', 'parent' => 'acme-tools', 'title' => __( 'Clear cache', 'acme' ), 'href' => wp_nonce_url( admin_url( 'admin-post.php?action=acme_clear_cache' ), 'acme_acme-clear-cache' ), ) ); $wp_admin_bar->add_node( array( 'id' => 'acme-docs', 'parent' => 'acme-tools', 'title' => __( 'Documentation', 'acme' ), 'href' => esc_url( 'https://example.com/docs' ), ) ); } add_action( 'admin_bar_menu', 'acme_toolbar_node', 80 ); /** * Clear the core nodes this site does not use. * * @param WP_Admin_Bar $wp_admin_bar The toolbar instance. */ function acme_toolbar_cleanup( $wp_admin_bar ) { $wp_admin_bar->remove_node( 'wp-logo' ); } add_action( 'admin_bar_menu', 'acme_toolbar_cleanup', 999 );
About this generator
Toolbar Node Generator Online
Build a WordPress admin bar menu with WP_Admin_Bar::add_node() — a parent node plus as many children as you need — and copy out the finished admin_bar_menu callback. Every node gets a real id, title, parent, href and meta array, hrefs are wrapped in esc_url( admin_url() ) or left as an absolute URL, and anything pointing at admin-post.php is wrapped in wp_nonce_url().
The toolbar preview draws your node and its dropdown in the real admin bar styling, so you can see how the title reads at 32 pixels high before you paste anything. The Reference tab documents every argument add_node() accepts. Snippet, functions.php block or plugin file. Free, no account, nothing uploaded.
Reviewed Output tested on WordPress 6.8 · PHP 8.3
Why the WordPress admin bar menu generator beats a copied add_node() call
Toolbar node ids are global across every plugin on the site, not namespaced per plugin, so an unprefixed id quietly replaces someone else's menu. The title argument is printed as raw HTML, so anything dynamic in it is an XSS hole waiting to happen. And a child pointing at admin-post.php with no nonce means any site that links to that URL can trigger the action on behalf of your logged-in administrators. This generator handles all three.
Nonced action links
Any child whose href starts with admin-post.php can be wrapped in wp_nonce_url() with a derived action name. Leave it off and the checker raises an error, because a bare admin-post.php link in the toolbar is a CSRF hole your admins click for you.
Href handling that matches what you typed
An absolute https:// URL is passed through esc_url(), an existing home_url() or admin_url() expression is left alone, and anything else is wrapped as esc_url( admin_url( … ) ). You never have to remember which form the toolbar wants.
Front end, admin, or both
Scope the node with a real is_admin() guard rather than hoping. The parent node also gets a meta array with a title attribute, which is what produces the hover tooltip core's own nodes have.
A count bubble wired to a filter
Turn the count on and the generator emits the awaiting-mod / pending-count markup core uses for the comment bubble, fed by a {prefix}_toolbar_count filter that defaults to zero — so the bubble stays hidden until you hook something real to it.
Core nodes removed with remove_node()
Clear the WordPress logo, the comment bubble, the + New menu, the updates counter, Customise or the front-end search with a second callback at priority 999. Removing the updates counter is flagged as a warning: it hides security updates from the people who apply them.
Child ids validated against the parent
Duplicate child ids, a child sharing its parent's id, an empty href, and the contradiction of nesting under new-content while also removing new-content are all caught before you paste. Ids are checked as HTML ids, since that is what they become.
How does the Toolbar Node Generator work?
Four steps: define the parent node, add its children, clear anything core puts there that you do not want, then export.
- 01
Define the parent node
Title, node id, href and where it attaches — top level, under the site name, under Howdy, inside + New, or on the right-hand side. Set the capability and the
admin_bar_menupriority, which decides where your node sits among core's. - 02
Add child nodes
Each child gets a title, an id, an href and a nonce toggle. They render as the dropdown under your parent, and the preview shows exactly how the list will look.
- 03
Remove core nodes
Optionally strip the WordPress logo, comments, + New, updates, Customise or search. These become
remove_node()calls in a separate callback at priority 999, so they run after every plugin has finished adding. - 04
Check and export
Work through the flagged issues — unprefixed ids, missing nonces, a title too long for the bar — then copy the snippet or download it as a plugin or a
functions.phpblock.
Worked example — an Acme menu with a nonced Clear cache action
The admin_bar_menu callback receives the WP_Admin_Bar instance by reference. The parent node is added first; children reference it by id.
function acme_toolbar_node( $wp_admin_bar ) {
if ( ! current_user_can( 'edit_others_posts' ) ) {
return;
}
$wp_admin_bar->add_node(
array(
'id' => 'acme-tools',
'title' => __( 'Acme', 'acme' ),
'href' => esc_url( admin_url( 'options-general.php?page=acme-toolkit' ) ),
'meta' => array(
'title' => __( 'Acme shortcuts', 'acme' ),
),
)
);
$wp_admin_bar->add_node(
array(
'id' => 'acme-clear-cache',
'parent' => 'acme-tools',
'title' => __( 'Clear cache', 'acme' ),
'href' => wp_nonce_url( admin_url( 'admin-post.php?action=acme_clear_cache' ), 'acme_acme-clear-cache' ),
)
);
}
add_action( 'admin_bar_menu', 'acme_toolbar_node', 80 );The node ids become wp-admin-bar-acme-tools and wp-admin-bar-acme-clear-cache in the markup, which is what you target from CSS. Removals are emitted as a second callback at priority 999 so they run after every other plugin has added its own nodes.
The WordPress toolbar — frequently asked questions
Common questions about adding, nesting and removing admin bar nodes.
How do I add a custom link to the WordPress admin bar?
Hook a callback to admin_bar_menu, accept the $wp_admin_bar object it passes, and call $wp_admin_bar->add_node( array( 'id' => '…', 'title' => '…', 'href' => '…' ) ). Use a priority of around 80 so your node lands after core's own items rather than beside the WordPress logo.
How do I add a dropdown submenu to a toolbar node?
There is no separate submenu function. Add the parent node first, then add each child with its parent key set to the parent's id. Core builds the dropdown from that relationship. A node with children and no href becomes a menu that only opens on hover.
Why does my toolbar node not appear on the front end?
Three usual reasons: the toolbar itself is hidden for that user, either by their profile setting or a show_admin_bar filter; your callback returns early on an is_admin() check; or the capability guard fails, since front-end visitors are often logged out entirely. admin_bar_menu fires in both contexts, so the guard is almost always the cause.
How do I remove items from the WordPress toolbar?
Call $wp_admin_bar->remove_node( $id ) on admin_bar_menu at a late priority — 999 is conventional — so it runs after everything has been added. Core ids include wp-logo, comments, new-content, updates, customize and search. Removing a parent removes its children with it.
Can I put an icon or a count bubble in a toolbar title?
Yes. The title argument is printed as HTML, not escaped, so you can include a Dashicon span or core's awaiting-mod / pending-count bubble markup. That also means anything dynamic inside the title must be escaped by you — an unescaped variable in a toolbar title is an XSS hole on every admin page.
How do I make a toolbar item trigger an action rather than just navigate?
Point the href at admin-post.php?action=your_action and wrap it in wp_nonce_url(), then handle it on admin_post_your_action with check_admin_referer() and a capability check before doing anything. Without the nonce, any page that links to that URL can fire the action for any logged-in administrator who visits it.
Where do I paste the code from the Toolbar Node 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.