Notifly in WordPress
WordPress sends almost all important events through the hook system (do_action,
apply_filters). You can hook into them from a tiny mu-plugin — no admin panel,
no visual editor.
Installation
Section titled “Installation”- Create the folder
wp-content/mu-plugins/if it doesn’t exist. - Put the file
notifly.phpthere (see below).
mu-plugins are loaded automatically on every request and are not disabled by
updates.
Basic notifly.php file
Section titled “Basic notifly.php file”<?php/** * Plugin Name: Notifly notifications * Description: Push notifications about key site events. */
if (!defined('ABSPATH')) exit;
if (!function_exists('notifly_send')) { function notifly_send(string $title, string $message, int $priority = 5): void { $url = defined('NOTIFLY_URL') ? NOTIFLY_URL : (getenv('NOTIFLY_URL') ?: ''); $token = defined('NOTIFLY_TOKEN') ? NOTIFLY_TOKEN : (getenv('NOTIFLY_TOKEN') ?: ''); if (!$url || !$token) return;
wp_remote_post("$url/message?token=$token", [ 'timeout' => 5, 'headers' => ['Content-Type' => 'application/json'], 'body' => wp_json_encode([ 'title' => mb_substr($title, 0, 200), 'message' => mb_substr($message, 0, 1500), 'priority' => $priority, ], JSON_UNESCAPED_UNICODE), ]); }}In wp-config.php set:
define('NOTIFLY_URL', 'https://your-notifly.example.com');define('NOTIFLY_TOKEN', 'AGdjfk_L.dKe8q');New comments
Section titled “New comments”add_action('comment_post', function ($comment_id, $approved) { $c = get_comment($comment_id); if (!$c) return; $status = $approved === 1 ? 'опубликован' : ($approved === 0 ? 'на модерации' : 'спам');
notifly_send( title: "💬 Комментарий ($status): " . wp_trim_words($c->comment_content, 8), message: "Автор: {$c->comment_author}\n" . "Пост: " . get_the_title($c->comment_post_ID) . "\n" . "Текст:\n{$c->comment_content}\n\n" . "Управление: " . admin_url("comment.php?action=editcomment&c=$comment_id"), priority: $approved === 0 ? 6 : 4, );}, 10, 2);New users
Section titled “New users”add_action('user_register', function ($user_id) { $u = get_userdata($user_id); if (!$u) return; notifly_send( title: "👤 Новый пользователь: {$u->user_login}", message: "Email: {$u->user_email}\n" . "Роль: " . implode(',', $u->roles) . "\n" . "Профиль: " . admin_url("user-edit.php?user_id=$user_id"), priority: 4, );});Core / plugins available
Section titled “Core / plugins available”add_action('upgrader_process_complete', function ($upgrader, $hook_extra) { $type = $hook_extra['type'] ?? 'unknown'; $action = $hook_extra['action'] ?? '?'; notifly_send( title: "🔄 WordPress: $action $type", message: "Сайт: " . home_url() . "\nДетали: " . wp_json_encode($hook_extra, JSON_UNESCAPED_UNICODE), priority: 5, );}, 10, 2);WooCommerce: new order
Section titled “WooCommerce: new order”add_action('woocommerce_new_order', function ($order_id) { $order = wc_get_order($order_id); if (!$order) return; $items = []; foreach ($order->get_items() as $item) { $items[] = "• {$item->get_name()} × {$item->get_quantity()}"; } notifly_send( title: "🛒 Новый заказ #{$order->get_order_number()} — " . wc_price($order->get_total()), message: "Покупатель: {$order->get_billing_first_name()} {$order->get_billing_last_name()}\n" . "Email: {$order->get_billing_email()}\n" . "Телефон: {$order->get_billing_phone()}\n" . "Способ оплаты: {$order->get_payment_method_title()}\n\n" . "Состав:\n" . implode("\n", $items) . "\n\n" . admin_url("post.php?post=$order_id&action=edit"), priority: 8, );});PHP-cron / WP-cron failure
Section titled “PHP-cron / WP-cron failure”WP-cron runs on every HTTP request. If there are no requests, scheduled tasks don’t run. Set up a “canary” — a daily event that should arrive in Notifly:
register_activation_hook(__FILE__, function () { if (!wp_next_scheduled('notifly_daily_canary')) { wp_schedule_event(time(), 'daily', 'notifly_daily_canary'); }});
add_action('notifly_daily_canary', function () { notifly_send( '🟢 WP-cron alive', 'Сайт ' . home_url() . ' жив. Время сервера: ' . current_time('mysql'), 2 );});If there’s no notification within 25 hours — something is wrong with the site’s cron.
Throttling
Section titled “Throttling”To avoid receiving 100 notifications in 5 minutes during a spam wave:
function notifly_throttled(string $key, int $cooldown, callable $fn): void { $cache_key = "notifly_throttle_$key"; if (get_transient($cache_key)) return; set_transient($cache_key, 1, $cooldown); $fn();}
add_action('comment_post', function ($id) { notifly_throttled("comment_$id", 60, function () use ($id) { notifly_send(/* ... */); });});Benefits
Section titled “Benefits”- See the live pulse of the site. Every order, every registration — push notifications.
- No email in spam. Notifly bypasses mail filters.
- No need for paid plugins like Mainwp, Jetpack or specialized “alert” add-ons.
What to improve next
Section titled “What to improve next”- Separate Notifly channels for different sites in a multisite network.
- Tags in extras: you can filter messages in the Notifly admin by tag
wc_orderorcomment. - “Confirm” / “Mark as spam” buttons via your own REST endpoint.