WordPress Dev: Adding Custom Admin Notifications Easily
Improve user experience with simple admin notices
Originally published: November 26th, 2017. Updated on: April 29th, 2025.
When developing a WordPress theme or plugin that involves custom user interactions, providing clear and concise feedback is really helpful. Sometimes users just don’t notice errors or warning notices at all! It happens.
While overly intrusive notifications can be a hindrance, a friendly nudge in the right direction is sometimes useful. WordPress has built-in admin notifications, but setting them up properly can be a bit cumbersome, and the default notices aren't always as visible as you might like.
(Image placeholder: Standard WordPress admin notice)
This article outlines a solution using WordPress's transients API and some optional JavaScript/CSS for added visual flair.
(Quick Link: Download the code demonstrated in this article.)
Adding User Notifications Into Your Code
First, we'll add a custom helper function to our code (place this in your theme's functions.php
or within your plugin file).
This function, let's call it my_plugin_add_admin_notice()
, will be a simple helper you can call anywhere in your code to queue up a notification message. For example: my_plugin_add_admin_notice('Oh no! Something went wrong', 'error');
will add an error message to the queue.
<?php
/**
* Add a notification message to be displayed in the WordPress admin.
*
* Stores messages in a user-specific transient until the next admin page load.
*
* @param string $message The message content. Required.
* @param string $type The type of notice ('error', 'warning', 'success', 'info'). Required.
* @return bool False if not in admin or invalid type, true otherwise.
*/
function my_plugin_add_admin_notice(string $message, string $type): bool
{
// Only run in the admin area
if (!is_admin()) {
return false;
}
// Validate the notice type
$allowed_types = ['error', 'warning', 'success', 'info'];
if (empty($message) || !in_array($type, $allowed_types, true)) {
return false;
}
// Use a transient to store notices for the current user
$transient_name = 'my_plugin_admin_notices_' . get_current_user_id();
// Get existing notices (if any)
$notices = get_transient($transient_name);
if (!is_array($notices)) {
$notices = [];
}
// Add the new notice
$notices[] = [
'message' => $message,
'type' => $type,
];
// Store the updated notices back in the transient.
// Set a short expiration (e.g., 1 minute) just in case the delete hook fails.
set_transient($transient_name, $notices, MINUTE_IN_SECONDS);
return true;
}
/**
* Display the stored admin notices.
*
* Hooks into 'admin_notices' and outputs stored notices, then clears the transient.
*/
function my_plugin_display_admin_notices(): void
{
// Only run in the admin area
// Also, let's add a capability check - maybe only show these to admins?
if (!is_admin() || !current_user_can('manage_options')) {
return;
}
$transient_name = 'my_plugin_admin_notices_' . get_current_user_id();
$notices = get_transient($transient_name);
if (is_array($notices) && !empty($notices)) {
foreach ($notices as $notice) {
// Ensure type and message exist and are strings
$type = isset($notice['type']) && is_string($notice['type']) ? $notice['type'] : 'info';
$message = isset($notice['message']) && is_string($notice['message']) ? $notice['message'] : '';
if (empty($message)) continue; // Skip empty messages
// Output the notice HTML - Ensure it's dismissible
// Added 'my-plugin-notice' class for specific targeting
printf(
'<div class="notice notice-%1$s is-dismissible my-plugin-notice my-plugin-notice-%1$s"><p>%2$s</p></div>',
esc_attr($type), // Sanitize type for class attribute
wp_kses_post($message) // Sanitize message content allowing basic HTML
);
}
// Clear the transient now that notices have been displayed
delete_transient($transient_name);
}
}
// Hook the display function into the 'admin_notices' action
add_action('admin_notices', 'my_plugin_display_admin_notices');
?>
The my_plugin_display_admin_notices
function hooks into the admin_notices
action. It retrieves any stored notices for the current user from the transient, prints them out using the standard WordPress notice
CSS classes (notice-error
, notice-success
, etc.), and makes them dismissible. Crucially, it then deletes the transient so the messages don't appear again on the next page load.
Testing
To easily test this, you can add a temporary function that triggers notices when a specific query parameter is present in the URL. Visit http://yoursite.com/wp-admin/?test_my_plugin_notices=1
to see them.
<?php
/**
* Temporary test function to trigger admin notices via URL parameter.
* REMOVE THIS FUNCTION BEFORE DEPLOYING TO PRODUCTION.
*/
function my_plugin_test_admin_notices_trigger(): void
{
// Check if the trigger parameter exists and the user has permission
if (isset($_GET['test_my_plugin_notices']) && current_user_can('manage_options')) {
my_plugin_add_admin_notice('Custom error notice test!', 'error');
my_plugin_add_admin_notice('Custom success notice test!', 'success');
my_plugin_add_admin_notice('Custom warning notice test!', 'warning');
my_plugin_add_admin_notice('Custom info notice test!', 'info');
// Redirect back to the dashboard to display the notices
// Use wp_safe_redirect for security
wp_safe_redirect(admin_url());
exit;
}
}
add_action('admin_init', 'my_plugin_test_admin_notices_trigger');
?>
Remember to remove this test function before deploying your code to a live site! Leaving it in could be a security risk, plain and simple.
Adding Some Custom Animation (Optional)
Sometimes you might want to make certain notices (especially errors or warnings) more visually prominent. Now, I'm not usually a fan of drastically altering a platform's UI, but subtle tweaks can be effective.
Let's implement a simple "wiggle" animation for error and warning notices to grab the user's attention.
(Image placeholder: Animated GIF showing the wiggle effect on error/warning notices)
This animation plays once when the notice appears, not continuously (that would be irritating!).
We'll use CSS keyframes and add the styles and triggering JavaScript to the admin head/footer.
1. Add CSS Styles:
<?php
/**
* Add custom CSS for notice animations to the admin head.
*/
function my_plugin_add_notice_styling_to_admin_head(): void
{
// Only add styles on admin pages
if (!is_admin()) {
return;
}
?>
<style>
@keyframes my-plugin-notice-wiggle {
/* Simple wiggle animation */
10%, 90% { transform: translateX(-1px); }
20%, 80% { transform: translateX(2px); }
30%, 50%, 70% { transform: translateX(-3px); }
40%, 60% { transform: translateX(3px); }
}
/* Apply animation to our custom error notices when .active-wiggle is added */
.my-plugin-notice.my-plugin-notice-error.active-wiggle {
/* Stronger wiggle for errors */
animation: my-plugin-notice-wiggle 0.6s ease-in-out;
}
/* Apply animation to our custom warning notices when .active-wiggle is added */
.my-plugin-notice.my-plugin-notice-warning.active-wiggle {
/* Slightly gentler wiggle for warnings */
animation: my-plugin-notice-wiggle 0.4s ease-in-out;
}
</style>
<?php
}
add_action('admin_head', 'my_plugin_add_notice_styling_to_admin_head');
?>
2. Add Triggering JavaScript:
This small script adds the active-wiggle
class shortly after the page loads, triggering the CSS animation.
<?php
/**
* Add JavaScript to trigger notice animations in the admin footer.
*/
function my_plugin_add_notice_scripting_to_admin_footer(): void // Renamed function
{
// Only add script on admin pages
if (!is_admin()) {
return;
}
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// Add a slight delay before adding the class to ensure notice is rendered
setTimeout(function() {
// Target only our specific error and warning notices
document.querySelectorAll('.my-plugin-notice.my-plugin-notice-error, .my-plugin-notice.my-plugin-notice-warning').forEach(function(notice) {
notice.classList.add('active-wiggle');
});
}, 100); // 100ms delay
});
</script>
<?php
}
add_action('admin_footer', 'my_plugin_add_notice_scripting_to_admin_footer'); // Use admin_footer for JS
?>
(Note: We could enqueue separate CSS and JS files, which is best practice for larger plugins, but for simplicity here, we're injecting directly into the head/footer.)
Using Animation for All WordPress Notifications?
The code above targets only notices generated by our helper function (using the .my-plugin-notice
class). If you wanted the wiggle effect on all WordPress error/warning notices, you would adjust the CSS selectors, removing .my-plugin-notice
:
/* Example - Apply to ALL WP error notices */
.notice.notice-error.active-wiggle {
animation: my-plugin-notice-wiggle 0.6s ease-in-out;
}
/* Example - Apply to ALL WP warning notices */
.notice.notice-warning.active-wiggle {
animation: my-plugin-notice-wiggle 0.4s ease-in-out;
}
And adjust the JavaScript selector accordingly:
document.querySelectorAll('.notice.notice-error, .notice.notice-warning').forEach(/* ... */);
So there you have it – WordPress admin notifications made simpler, and optionally, a bit more eye-catching. Hopefully, this helps make your plugin or theme's behaviour more transparent to users.
Download the Code {#download-code}
(Link placeholder: Download example code .zip)