GeneratorsAdminAdmin Notice

Admin Notice Generator

Notices that appear on the right screens, to the right people, and stay gone when dismissed — the AJAX handler and nonce included.

acme-setup-notice.php
Saved just now
Live preview

Acme Toolkit: add your API key to finish setting up.

Open settings

×
Shown on 2 screens
The notice
Where it shows
2 screens
Writes acme_setup_dismissed to user meta over AJAX — each person dismisses their own copy, permanently.
Behaviour
Dismissible
Adds is-dismissible so core prints the X button.
notice-alt styling
The flat variant core uses inside plugin table rows.
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io).
/**
 * Print the notice.
 */
function acme_notice() {
	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}

	$screen = get_current_screen();

	if ( ! $screen || ! in_array( $screen->id, array( 'dashboard', 'plugins' ), true ) ) {
		return;
	}

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

	printf(
		'<div class="notice notice-warning is-dismissible" data-notice="acme_setup"><p><strong>%1$s</strong> %2$s</p><p><a href="%4$s" class="button button-primary">%3$s</a></p></div>',
		esc_html__( 'Acme Toolkit:', 'acme' ),
		esc_html__( 'add your API key to finish setting up.', 'acme' ),
		esc_html__( 'Open settings', 'acme' ),
		esc_url( admin_url( 'options-general.php?page=acme-toolkit' ) )
	);
}
add_action( 'admin_notices', 'acme_notice' );

/**
 * Send the dismissal back so it sticks. Printed only where the notice itself would appear.
 */
function acme_dismiss_script() {
	if ( ! current_user_can( 'manage_options' ) ) {
		return;
	}

	$screen = get_current_screen();

	if ( ! $screen || ! in_array( $screen->id, array( 'dashboard', 'plugins' ), true ) ) {
		return;
	}

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

	$nonce = wp_create_nonce( 'acme_setup_dismissed' );
	?>
	<script>
	document.addEventListener( 'click', function ( event ) {
		var button = event.target.closest( '[data-notice="acme_setup"] .notice-dismiss' );

		if ( ! button ) {
			return;
		}

		window.fetch( ajaxurl, {
			method: 'POST',
			credentials: 'same-origin',
			headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
			body: new URLSearchParams( {
				action: 'acme_dismiss_notice',
				nonce: '<?php echo esc_js( $nonce ); ?>'
			} )
		} );
	} );
	</script>
	<?php
}
add_action( 'admin_footer', 'acme_dismiss_script' );

/**
 * Store the dismissal.
 */
function acme_dismiss() {
	check_ajax_referer( 'acme_setup_dismissed', 'nonce' );

	if ( ! is_user_logged_in() ) {
		wp_send_json_error( null, 403 );
	}

	update_user_meta( get_current_user_id(), 'acme_setup_dismissed', time() );

	wp_send_json_success();
}
add_action( 'wp_ajax_acme_dismiss_notice', 'acme_dismiss' );

About this generator

Admin Notice Generator Online

Generate a WordPress admin notice that behaves: the right notice notice-success|info|warning|error class, a capability check, a get_current_screen() guard so it only appears where it should, and — when you make it dismissible — the AJAX handler and nonce that make the dismissal actually stick. Notices are printed with printf() and esc_html__(), so every string is escaped and translatable.

The notice redraws live in the admin-styled preview as you change the type, the lead-in, the message and the button, and the Reference tab lists what each core notice class looks like and when to use it. Snippet, functions.php block or plugin file, procedural or class. Free, private, nothing leaves the browser.

Reviewed Output tested on WordPress 6.8 · PHP 8.3

Why the WordPress admin notice generator beats a two-line echo

An admin notice is three lines of code and four ways to annoy people. Without a capability check every role that can reach wp-admin sees it. Without a screen check it appears on all of them, forever. And is-dismissible is client-side only — core hides the div, then the notice returns on the next page load, which reads as broken. This generator writes the guards and the persistence together.

Four ways to remember a dismissal

Not at all, per user forever in user meta, per user for a set number of days via a transient, or site-wide in an option. Each mode explains its trade-off inline — the site-wide option is flagged as a warning, because whoever clicks the X first closes it for everyone, including people who never saw it.

The AJAX round trip written for you

Choose any persistence mode with dismissible on and you get three blocks: the notice, a footer script that listens for a click on .notice-dismiss inside your own data-notice attribute and posts to ajaxurl, and a wp_ajax_ handler with check_ajax_referer() and a logged-in check before it writes.

Screen scoping, not a blanket notice

Pick the screens the notice belongs on and the generated code compares get_current_screen()->id against your list. Leave it empty and the checker warns you: a notice on every admin page is the fastest way to make a client stop reading your notices.

The dismiss script prints only where the notice does

The same capability, screen and persistence guards are repeated at the top of the admin_footer callback, so the inline script is never printed on screens where the notice would not have appeared.

Tone checked against the message

Mark a notice as an error and the checker looks for words like fail, missing, expired or invalid in the text. An error notice for something that is not an error trains people to ignore the red ones, so it suggests warning or info instead.

HTML caught before it prints as text

Message strings go through esc_html__(), so tags typed into the message would render literally. The checker spots that and points you at the bold lead-in and the action button fields, which are separate placeholders in the same printf().

How does the Admin Notice Generator work?

Four steps: write the notice, decide who sees it and where, decide whether it comes back, then export.

  1. 01

    Write the notice

    Choose success, info, warning or error, then set the bold lead-in, the message, and optionally an action button with its label and admin target. The preview shows the finished notice in admin styling as you type.

  2. 02

    Scope it

    Pick the capability and tick the screens it should appear on — Dashboard, Plugins, the posts list, the post editor, Settings, Themes or Media. Both become real guard clauses at the top of the callback.

  3. 03

    Decide what happens on dismiss

    Turn dismissible on, then choose whether the dismissal is forgotten on reload, remembered per user forever, snoozed for a number of days, or stored once for the whole site. The note under the field spells out exactly what gets written where.

  4. 04

    Clear the checks and export

    Fix anything flagged — a dismissible notice with no persistence, a button with no target, no capability — then copy the snippet or download it as a plugin or functions.php block.

Worked example — a setup nudge on the Dashboard and Plugins screens

An amber notice with a bold lead-in and a primary button, restricted to administrators and to two screens. This is the complete generated output.

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

	$screen = get_current_screen();

	if ( ! $screen || ! in_array( $screen->id, array( 'dashboard', 'plugins' ), true ) ) {
		return;
	}

	printf(
		'<div class="notice notice-warning" data-notice="acme_setup"><p><strong>%1$s</strong> %2$s</p><p><a href="%4$s" class="button button-primary">%3$s</a></p></div>',
		esc_html__( 'Acme Toolkit:', 'acme' ),
		esc_html__( 'add your API key to finish setting up.', 'acme' ),
		esc_html__( 'Open settings', 'acme' ),
		esc_url( admin_url( 'options-general.php?page=acme-toolkit' ) )
	);
}
add_action( 'admin_notices', 'acme_notice' );

Turn dismissible on with per-user persistence and two more blocks appear: an admin_footer script that posts the dismissal to ajaxurl, and a wp_ajax_acme_dismiss_notice handler that runs check_ajax_referer() before writing acme_setup_dismissed to user meta.

WordPress admin notices — frequently asked questions

The questions developers actually hit when adding notices to the WordPress admin.

Why does my dismissible admin notice come back after a page reload?

Because is-dismissible is presentation only. Core adds the X button and removes the div from the DOM, but nothing is recorded anywhere. To make a dismissal stick you have to store it yourself — user meta, a per-user transient, or a site option — and check that value before printing the notice. This generator writes both halves plus the AJAX call between them.

How do I show an admin notice only on my own plugin page?

Call get_current_screen() inside your admin_notices callback and return early unless $screen->id matches. For a page added with add_menu_page() the screen id is the hook suffix that call returned, typically toplevel_page_your-slug. Checking $_GET['page'] also works but breaks the moment the page moves under a different parent.

What are the WordPress admin notice classes?

Core styles notice notice-success (green), notice notice-info (blue), notice notice-warning (amber) and notice notice-error (red). Add is-dismissible for the X button and notice-alt for the flat variant core uses inside plugin table rows. The outer element should be a div with a paragraph inside — core's CSS assumes that structure.

Why is my admin notice not showing at all?

Three usual causes: the callback is hooked too late — admin_notices fires early in the page, so anything registered on admin_footer misses it; you are on the network admin, which uses network_admin_notices; or a capability or screen guard is returning first. On the user profile screen core also runs user_admin_notices rather than admin_notices.

How do I show a notice after a redirect?

Notices do not survive a redirect, because the callback runs on the request that produced the page. Either add a query argument to the redirect target and check for it in your admin_notices callback, or use the Settings API route: add_settings_error() plus settings_errors(), which stores the message in a transient across the redirect.

Can I add a button to an admin notice?

Yes — core's .button and .button-primary classes work inside a notice. Keep it to one action and put it in its own paragraph so it does not sit inline with the text. If the button triggers a change rather than just navigating, it needs a nonce on the URL and a capability check at the other end.

Where do I paste the code from the Admin Notice 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.