Admin Notice Generator

Generate a WordPress admin notice with the capability check, the screen it appears on, and a dismissal that is remembered per user.

Live output

Enable JavaScript to customise; default output below.

Type

Sets the colour of the left border. error is red and is not dismissible by convention.

Wrapped in a translation function, so keep it a complete sentence rather than glued-together fragments.

More options Show

Leave empty for the usual single-paragraph notice.

Live preview admin-notice.php
<?php
/**
 * Admin notice: Settings saved. Your changes are live.
 */

/**
 * Prints the notice.
 */
function my_plugin_admin_notice() {
	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}

	if ( get_user_meta( get_current_user_id(), 'my_plugin_notice_dismissed', true ) ) {
		return;
	}

	$html = '<p>' . esc_html__( 'Settings saved. Your changes are live.', 'my-plugin' ) . '</p>';

	$dismiss = wp_nonce_url(
		admin_url( 'admin-post.php?action=my_plugin_dismiss_notice' ),
		'my_plugin_dismiss_notice'
	);

	$html .= '<p><a href="' . esc_url( $dismiss ) . '">'
		. esc_html__( 'Do not show this again', 'my-plugin' )
		. '</a></p>';

	printf(
		'<div class="%1$s">%2$s</div>',
		esc_attr( 'notice notice-success is-dismissible' ),
		wp_kses_post( $html )
	);
}
add_action( 'admin_notices', 'my_plugin_admin_notice' );

/**
 * Stores the dismissal against the user, so the notice stays gone.
 */
function my_plugin_dismiss_notice() {
	check_admin_referer( 'my_plugin_dismiss_notice' );

	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die(
			esc_html__( 'You are not allowed to do that.', 'my-plugin' ),
			'',
			array( 'response' => 403 )
		);
	}

	update_user_meta( get_current_user_id(), 'my_plugin_notice_dismissed', 1 );

	$back = wp_get_referer();

	wp_safe_redirect( $back ? $back : admin_url() );
	exit;
}
add_action( 'admin_post_my_plugin_dismiss_notice', 'my_plugin_dismiss_notice' );

Output is valid and updates as you type.

Pick the type, the screen and who sees it, and the generator writes the whole notice: the capability check, the markup WordPress styles, and a dismissal that is remembered instead of coming back on the next page.

How to use

  1. Write the message as one finished sentence. It goes through a translation function, so fragments joined with a dot cannot be translated properly.
  2. Set the capability. Subscribers can open the dashboard, and a notice with no check is a notice every logged-in user reads.
  3. Narrow the screen. everywhere puts your notice on top of every other plugin’s settings page, which is how notice fatigue starts.
  4. Leave the remembered dismissal on for anything that is not urgent. The cross alone only hides the notice until the next page load.
  5. Paste the result into your plugin. Nothing else has to be registered: both the notice and the dismissal handler hook themselves up.

Example

A warning shown only on the plugins screen, to users who can activate plugins, with a button and a dismissal that sticks:

function acme_admin_notice() {
	if ( ! current_user_can( 'activate_plugins' ) ) {
		return;
	}

	$screen = get_current_screen();

	if ( ! $screen || 'plugins' !== $screen->id ) {
		return;
	}

	if ( get_user_meta( get_current_user_id(), 'acme_notice_dismissed', true ) ) {
		return;
	}

	$html = '<p>' . esc_html__( 'Acme needs an API key before it can sync.', 'acme' ) . '</p>';

	printf(
		'<div class="%1$s">%2$s</div>',
		esc_attr( 'notice notice-warning is-dismissible' ),
		wp_kses_post( $html )
	);
}
add_action( 'admin_notices', 'acme_admin_notice' );

The dismissal link posts to admin-post.php with a nonce, so no JavaScript and no AJAX endpoint is involved.

Pitfalls

  • The dismiss cross is presentation only. WordPress hides the notice in the browser and forgets it; the notice returns on the next screen unless you store the dismissal yourself.
  • admin_notices does not fire on network admin screens. On multisite, a notice that looks missing is usually hooked to the wrong one.
  • Without a capability check every logged-in user sees the notice, including subscribers on a membership site who never asked about your plugin.
  • get_current_screen() can return null early in the request. Check it before reading ->id, or the notice fatals on some screens.
  • wp_admin_notice() escapes nothing. Whatever you pass is printed, so escape the message before it goes in.
  • wp_admin_notice() needs WordPress 6.4. Calling it on 6.3 is a fatal error, not a missing notice.
  • Screen IDs are not post types. The post list table is edit-post, the editor is post, and a settings page is settings_page_your-slug.
  • Printing a notice on every admin screen trains people to ignore notices, including your next important one.

Compatibility

admin_notices, get_current_screen() and the notice classes have been stable since WordPress 4.4. wp_admin_notice() needs WordPress 6.4 or later and is left off by default here. The generated code targets PHP 7.0 and up, and the tool runs entirely in your browser.

Frequently asked questions

Why does my notice come back after I dismiss it?
The cross is a browser-side hide. Nothing is stored unless you store it, which is what the remembered dismissal option adds.
How do I find a screen ID?
Print get_current_screen()->id on the page you want, or check the body class in the admin. List tables are edit-<post_type>.
Should I use wp_admin_notice()?
Only when your minimum is WordPress 6.4. It saves writing the wrapper, but it escapes nothing, so you still escape the message yourself.
Can I show a notice once after activation?
Set a transient on activation and delete it in the notice. The remembered dismissal here is per user, which is the better fit for anything a user should be able to silence.
Where do notices actually appear?
WordPress moves them under the page heading. Add the inline class to keep a notice where you print it, such as inside your own settings form.

From the people who built this tool

WP Adminify

The WordPress admin, rebuilt: a dashboard worth looking at, menu and column control, a real file manager and the login page your client sees.

See WP Adminify Free version on WordPress.org

Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.