Send WordPress system events to an Apprise API endpoint.
  • PHP 95.4%
  • CSS 2%
  • JavaScript 1.6%
  • Shell 1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Eric Schewe 0a74e23318
All checks were successful
CI / Lint + Static Analysis (push) Successful in 1m52s
CI / Unit Tests (PHP 8.3) (push) Successful in 1m41s
CI / Unit Tests (PHP 8.4) (push) Successful in 1m36s
CI / Unit Tests (PHP 8.5) (push) Successful in 1m48s
docs: note that Authorized Integrations can't restrict the Actions token
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 22:39:19 -07:00
.claude I guess 2026-03-12 21:25:17 -07:00
.forgejo/workflows fix(ci): paginate the release lookup in release.yml 2026-10-16 22:09:52 -07:00
assets v2.4.1: bug fixes and code quality improvements from 4th Context7 review 2026-03-12 20:46:35 -07:00
includes docs: review README and readme.txt against the code 2026-10-16 22:13:32 -07:00
tests fix: update-notice cron respects the global enabled switch 2026-10-16 22:08:19 -07:00
.distignore fix: pin DNS on the cURL handle and check resolved IPs for loopback 2026-10-16 21:45:17 -07:00
.gitattributes chore: normalize line endings to LF 2026-10-16 16:30:44 -07:00
.gitignore test: add wp-env integration suite 2026-10-16 21:26:29 -07:00
.wp-env.json test: add wp-env integration suite 2026-10-16 21:26:29 -07:00
apprise-notifications.php chore: release 2.7.0 2026-10-16 22:21:43 -07:00
CHANGELOG.md chore: release 2.7.0 2026-10-16 22:21:43 -07:00
CLAUDE.md docs: note that Authorized Integrations can't restrict the Actions token 2026-10-16 22:39:19 -07:00
composer.json test: add wp-env integration suite 2026-10-16 21:26:29 -07:00
LICENSE Getting going on v1.2.2 2026-02-06 17:07:13 -08:00
package-lock.json test: add wp-env integration suite 2026-10-16 21:26:29 -07:00
package.json test: add wp-env integration suite 2026-10-16 21:26:29 -07:00
patchwork.json fix: pin DNS on the cURL handle and check resolved IPs for loopback 2026-10-16 21:45:17 -07:00
phpcs.xml.dist feat: one-click updates via Update URI; require PHP 8.3 (2.6.0) 2026-10-16 16:37:08 -07:00
phpstan.neon ci: add PHPCS, PHPStan and PHPUnit gates on Forgejo Actions 2026-10-16 16:32:39 -07:00
phpunit.xml test: add wp-env integration suite 2026-10-16 21:26:29 -07:00
README.md docs: review README and readme.txt against the code 2026-10-16 22:13:32 -07:00
readme.txt chore: release 2.7.0 2026-10-16 22:21:43 -07:00
SECURITY.md Last one 2026-03-12 22:12:39 -07:00
uninstall.php feat: one-click updates via Update URI; require PHP 8.3 (2.6.0) 2026-10-16 16:37:08 -07:00

Apprise Notifications for WordPress

Send WordPress system events to an Apprise API endpoint.

Related blog post

AI Disclosure

This plugin was completely written by Claude AI.

I (a human) did testing to verify each feature worked and ran the code through Semgrep.dev to see if there was anything blatantly wrong.

Features

  • 🔔 Multiple Notification Events: See Supported Events for a full list
  • 🔒 Security-First Design: Built following WordPress security best practices and OWASP guidelines, or at least that's what I told the AI Agent to do
  • ⚡ Lightweight: Notifications are queued and sent at PHP shutdown, after the page has been delivered, so they don't slow the request down
  • 🔧 Highly Configurable: Enable/disable individual events, debug logging, and more
  • 🔌 Extensible: Filter hooks for customizing every aspect of notifications
  • 🛡️ Privacy-Aware: Configurable IP logging with anonymization options
  • 📧 Email Suppression: Prevent duplicate notifications by suppressing WordPress default emails for events handled by Apprise
  • 🔄 Update Checker: Optional update checking with one-click updates and Apprise notifications

Requirements

Installation

Install Plugin

  1. Go to the Releases page
  2. Download the latest release's apprise-wordpress-notifications.X.Y.Z.zip file (not the Source Code (ZIP) archive)
  3. Login to your Wordpress Site
  4. Click Plugins
  5. Click Add Plugin
  6. Click Upload Plugin
  7. Click Browse and select ZIP file you downloaded from the Releases page
  8. Click Install Now
  9. Click Activate Plugin

Configuration

  1. Navigate to Settings and Apprise Notifications
  2. Enter your Apprise API URL (Example: https://apprise.yourdomain.com/notify/{APIKEY})
  3. (Optional) Set a default tag for notifications
  4. Checkmark Enable Notifications
  5. Review and checkmark which notifications you would like to receive
  6. Click Test Connection to verify your setup
  7. Click Save Changes

Supported Events

All events except Admin Login and New Comment are off until you enable them.

Event Description
Admin Login Triggered when a user with manage_options logs in (on by default)
User Registration Triggered when a new user registers
User Role Changed Triggered when a user's role changes
User Deleted Triggered when a user is deleted
Post Published Triggered when a post is published
Post Updated Triggered when a published post is updated
Post Moved to Trash Triggered when a post is moved to trash
Post Permanently Deleted Triggered when a post is permanently deleted
New Comment Triggered when a comment is posted (on by default)
Pingback / Trackback Triggered when a pingback or trackback is received
Core Updated Triggered when WordPress core is updated
Plugin Installed Triggered when a plugin is installed
Plugin Updated Triggered when a plugin is updated
Plugin Deleted Triggered when a plugin is deleted
Theme Installed Triggered when a theme is installed
Theme Changed Triggered when the active theme changes
Theme Updated Triggered when an installed theme is updated, manually or automatically

Posts and pages are covered by default; see Add Custom Post Types for others. A separate notice for new versions of this plugin is sent when Update Checking is on.

Email Suppression

To avoid receiving duplicate notifications (one from Apprise and one from WordPress), the Suppress WordPress Emails setting has three modes:

Mode Behavior
None (default) WordPress emails are unaffected
Matching events only Suppresses a WordPress email only when the Apprise event that replaces it is enabled: comment notifications (New Comment; pingbacks and trackbacks by Pingback / Trackback), the admin's new-user email (User Registration; the new user still gets their set-password email), and the automatic-update emails (Core Updated, Plugin Updated, Theme Updated)
All emails Blocks all emails sent via wp_mail(), including password resets, which have no Apprise replacement. Use with caution

Email suppression is only active when the plugin is globally enabled and an Apprise API URL is set. Deactivating or uninstalling the plugin automatically restores all WordPress emails.

Update Checking

Since this plugin is hosted on a self-hosted Forgejo instance rather than wordpress.org, it includes an optional update checker. It is off by default. When Check for Updates is enabled under Settings → Apprise Notifications:

  • WordPress reads the releases feed whenever it checks for plugin updates (about twice a day; the result is cached for 12 hours, a failed fetch for 1 hour)
  • A newer release shows up on Plugins and Dashboard → Updates like any other plugin update, and Update now installs the release zip from Forgejo
  • An Apprise notification is sent once per new version, from a daily WP-Cron job, as long as Enable Notifications is also on
  • The request uses an Apprise-Notifications/<version> user agent, so the site's address isn't sent to the forge

On multisite, the main site's setting applies to the whole network, and only the main site sends the Apprise notification.

The plugin header's Update URI also stops WordPress from offering a wordpress.org plugin with the same slug as an update.

Plugin Architecture

apprise-wordpress-notifications/
├── apprise-notifications.php   # Main plugin bootstrap
├── uninstall.php               # Cleanup on plugin deletion (multisite-aware)
├── includes/
│   ├── class-apprise-client.php           # Apprise API client, SSRF protection
│   ├── class-apprise-event-dispatcher.php # Central event dispatcher, shutdown queue
│   ├── class-apprise-admin-settings.php   # Admin settings page
│   ├── class-apprise-email-suppressor.php # WordPress email suppression
│   ├── class-apprise-update-checker.php   # Forgejo release update checker
│   ├── class-apprise-logger.php           # Secure logging
│   ├── class-apprise-role-utils.php       # Role slug → label helpers
│   ├── trait-apprise-event-deduplication.php
│   └── events/
│       ├── class-apprise-comment-events.php
│       ├── class-apprise-login-events.php
│       ├── class-apprise-user-events.php
│       ├── class-apprise-post-events.php
│       ├── class-apprise-plugin-events.php # Also theme install/switch/update
│       └── class-apprise-core-events.php
├── assets/
│   ├── admin.css
│   └── admin.js
├── CHANGELOG.md
├── readme.txt
└── README.md

Developer Documentation

Filter Hooks

Modify Notifications Before Sending

add_filter( 'apprise_notifications_before_dispatch', function( $notification, $event_type, $context ) {
    // Add a prefix to all notification titles
    $notification['title'] = '[My Site] ' . $notification['title'];
    
    // Change notification type
    $notification['type'] = 'warning';
    
    // Cancel the notification by returning false
    if ( 'post_update' === $event_type ) {
        return false;
    }
    
    return $notification;
}, 10, 3 );

Add Custom Post Types

add_filter( 'apprise_notifications_supported_post_types', function( $types ) {
    $types[] = 'product';
    $types[] = 'event';
    return $types;
} );

Send Custom Events

Route your own events through the plugin's dispatcher. Event types that aren't one of the built-in keys are dropped unless you enable them:

add_filter( 'apprise_notifications_unknown_event_enabled', function( $enabled, $event_type ) {
    return 'woocommerce_order' === $event_type ? true : $enabled;
}, 10, 2 );

add_action( 'woocommerce_new_order', function( $order_id ) {
    $dispatcher = apprise_notifications()->get_component( 'dispatcher' );
    if ( $dispatcher ) {
        $dispatcher->dispatch( 'woocommerce_order', 'New order', "Order #{$order_id} was placed." );
    }
} );

Use apprise_notifications_event_type_map to give your event a notification type other than info:

add_filter( 'apprise_notifications_event_type_map', function( $map ) {
    $map['woocommerce_order'] = 'success';
    return $map;
} );

Privacy Controls

// Disable IP logging in notifications
add_filter( 'apprise_notifications_include_login_ip', '__return_false' );

// Anonymize IP addresses instead of disabling
add_filter( 'apprise_notifications_anonymize_ip', '__return_true' );

// Leave the user's email out of user notifications
add_filter( 'apprise_notifications_include_user_email', '__return_false' );

// Allow localhost for development
add_filter( 'apprise_notifications_allow_localhost', '__return_true' );

All Hooks

Hook Type Default Purpose
apprise_notifications_before_dispatch filter — Change a notification's title, body, type or tag, or return false to cancel it
apprise_notifications_supported_post_types filter ['post', 'page'] Post types that trigger post events
apprise_notifications_event_type_map filter — Map event keys to info / success / warning / failure
apprise_notifications_unknown_event_enabled filter false Whether an event key with no setting is sent
apprise_notifications_async_dispatch filter true Return false to send synchronously instead of at shutdown (for debugging)
apprise_notifications_request_args filter — Modify the HTTP request args; security-critical args are enforced after this filter
apprise_notifications_allow_localhost filter false Allow loopback addresses (the only way to open them)
apprise_notifications_allow_private_ip filter Allow Private IPs setting Allow private/reserved addresses; link-local and cloud metadata addresses get false as the default and need a strict true
apprise_notifications_include_login_ip filter true Include the IP address in login notifications
apprise_notifications_anonymize_ip filter false Anonymize that IP address
apprise_notifications_include_user_email filter true Include the user's email in user notifications
apprise_notifications_queue_flushed action — Fires after the shutdown queue is sent; receives the number of notifications
apprise_notifications_log action — Fires for each log entry; receives level, message and context
apprise_notifications_uninstalled action — Fires when the plugin's data is removed on uninstall

Action Hooks

Custom Log Handler

add_action( 'apprise_notifications_log', function( $level, $message, $context ) {
    // Send logs to your custom logging service
    my_custom_logger( $level, $message, $context );
}, 10, 3 );

Security Features

  • Input Validation: All inputs are sanitized using WordPress sanitization functions
  • Output Escaping: All outputs are escaped to prevent XSS
  • Nonce Verification: All admin actions use WordPress nonces
  • Capability Checks: Admin functions require manage_options capability; on multisite only a super admin can change Allow Private IPs
  • SSRF Protection: The API URL's host is resolved and pinned for the request, loopback, private, link-local and cloud metadata addresses are blocked (private ranges can be opened with Allow Private IPs), and redirects are not followed
  • Secure Logging: Sensitive data (API keys, passwords, tokens) is automatically redacted from logs
  • Non-Blocking Failures: Network errors never block WordPress execution