In stock GLPI, a notification is an asynchronous email: it lands in spam, the technician does not live in the webmail, and the follow-up sits unanswered for hours. Smart Notify replaces that model with a bell in GLPI's own navbar that polls the database and aggregates over a dozen ITIL events in near real time. Running client GLPI estates in production taught us that turning the bell on is the easy part - the hard part is tuning what it shows so it does not become noise. This guide covers how the poll works under the hood, a diagnostic SQL, the matrix of which events to keep on, and the field traps that most often break the install.
Why native email does not solve operational alerting
GLPI's native notifications rely on the queuednotification queue and email templates. It is an asynchronous, out-of-tool model: the technician must switch between GLPI and the inbox, transactional email lands in corporate spam, and nobody watches the webmail in real time. The classic operational outcome is an approval stuck for hours and an assigned task nobody saw.
The bell solves this for whoever is logged into GLPI. But mind the first trap: the bell does not replace email for the requester. It notifies the technician in session, not the customer who opened the ticket through self-service. The common mistake is disabling email notifications assuming the bell covers everyone - and the requester stops being notified. Bell and email are complementary layers, not mutually exclusive.
How the bell works under the hood (polling + delta)
The bell's JavaScript polls every 30 seconds (default refresh_interval) against an AJAX endpoint. On each cycle the backend scans up to sixteen event sources, builds the list, applies retention (retention_days, default 90 days), caps at max_notifications (default 50) and sorts by date descending. Each notification gets a stable hash (sha1(type_id_timestamp)) - that is what marks the item as read without adding a new field to the ticket.
What only operators notice is the cost of that 30-second poll per logged-in technician. That is why the endpoint uses delta mode: the client returns the hash of the last state (state=); if nothing changed, the response drops from about 18 KB to ~93 bytes. And the read-check became a single bulk SELECT - it used to be one SELECT per notification, reaching ~700 per poll for users with a large backlog. The GET also calls session_write_close() right away so it does not hold PHP's session lock while scanning the database.
# The bell polls every 30s at this endpoint (routed via module_ajax):
GET /plugins/nextool/ajax/module_ajax.php?module=smartnotify&file=notifications.php&action=get&state=${HASH}
# With nothing new since the last poll, the response is a ~93-byte delta:
{ "success": true, "unchanged": true, "state": "...md5...", "unread_count": 4 }
# Only when something changes does the full payload (~18KB) with notifications[] arrive.
The event sources and what to keep on
The global configuration exposes sixteen triggers, and each technician further refines their own in the preferences modal (reachable straight from the bell dropdown). Two targeting rules matter: a follow-up you wrote does not notify you (the query filters users_id != user), and a notification arrives through direct involvement or through a technical group (notify_group_involvement), always respecting the session's active entities.
In production sustaining, three triggers ship off by default on purpose, and experience confirms the choice: attached documents are noise in estates with heavy uploads; new problems and new changes are less frequent events that clutter the bell of someone who only handles tickets. Turning everything on is the fastest path to alert fatigue - the technician starts ignoring the bell, and then it is useless.
| Event family | Trigger (config) | Default | Field note |
|---|---|---|---|
| Follow-ups (ticket, problem, change) | notify_*_followup | On | What moves the backlog most; keep it |
| Validations and validation responses | notify_*_validation(_response) | On | A stuck approval is a silent bottleneck |
| Assigned tasks | notify_*_task | On | It is the technician's work queue |
| Recorded solutions | notify_solution | On | Closes the loop for followers |
| Attached documents | notify_document | Off | Noisy where uploads are heavy |
| New tickets | notify_new_ticket | On | Queue intake signal |
| New problems / changes | notify_new_problem / _change | Off | Less common; enable per profile |
| Manual broadcasts | notify_manual | On | Maintenance, process change |
SQL diagnostics: who muted what
When a client complains that "the bell does not alert", the problem is almost always an individual preference or the wrong entity, not a bug. These three queries handle the triage straight in the database (the module's real tables):
-- 1. How many technicians muted each event type (find noise/fatigue):
SELECT
SUM(ticket_followups = 0) AS muted_ticket_followup,
SUM(solutions = 0) AS muted_solution,
SUM(documents = 0) AS muted_document,
SUM(sound_enabled = 0) AS sound_off
FROM glpi_plugin_nextool_smartnotify_preferences;
-- 2. Read records per user (backlog and last activity):
SELECT users_id, COUNT(*) AS reads_logged, MAX(date_read) AS last_read
FROM glpi_plugin_nextool_smartnotify_read
GROUP BY users_id
ORDER BY last_read DESC;
-- 3. Active manual broadcasts and their target (all/user/group/entity):
SELECT id, title, priority, target_type, target_id, entities_id, date_creation
FROM glpi_plugin_nextool_smartnotify_manual
WHERE is_active = 1
ORDER BY date_creation DESC;
Sounds by priority and the autoplay trap
Notifications play a sound via the Web Audio API, with four tones mapped by priority. Before looking at the screen, the technician hears whether what arrived is routine or urgent:
| Priority | Sound | Tone (approx.) |
|---|---|---|
| Low | subtle | Short and low (440 Hz) |
| Normal | default | Default (523 Hz) |
| High | alert | Mid (659 Hz) |
| Urgent | alarm | Long and high (880 Hz) |
The trap here is not the module, it is the browser: Chrome's autoplay policy only lets you create the AudioContext after the user's first gesture. In practice, the first sound of a session only plays after the first click on the page. Every month someone opens a ticket saying "the sound does not work" - the answer is to click once on the page. It is not a bug, it is the Web Audio API respecting the browser.
Manual broadcasts and automatic cleanup
Administrators send manual notices with precise targeting: all, a single user, a group or an entity (the target_type column in the _manual table). It is the right channel for a maintenance window or a process change without emailing the whole base. Retention is handled by a daily CronTask (smartnotify_cleanup), registered at install as MODE_EXTERNAL. That matters: in MODE_INTERNAL the task runs via a web-hit and can hang at state=2. Trigger GLPI's cron externally (on GLPI 11, front/cron.php) and cleanup happens on its own according to retention_days and logs_retention_days.
# CronTask registered at install (idempotent), once a day, MODE_EXTERNAL:
# Name: smartnotify_cleanup Frequency: DAY_TIMESTAMP (86400s)
# Trigger GLPI's cron externally (never rely on MODE_INTERNAL via web-hit):
* * * * * www-data /usr/bin/php /var/www/html/front/cron.php >/dev/null 2>&1
The trap that breaks the install: MySQL 8 vs MariaDB
A real sustaining case (June 2026, a client on MySQL 8.0.46): the module's install turned into an HTTP 500 and the estate had no bell. The root cause was not in GLPI, it was in the SQL: an ALTER TABLE ... ADD COLUMN IF NOT EXISTS block - syntax exclusive to MariaDB. On MySQL 8 that column-level IF NOT EXISTS does not exist and the statement fails with error 1064, taking the whole install down. The lesson holds for any GLPI plugin: conditional DDL is not portable between MariaDB and MySQL. The fix (version 2.2.1+) removed the conditional DDL from the .sql and moved migrations to PHP with the base plugin's portable helpers. If you run MySQL 8, make sure the module is on 2.2.1 or later.
At NexTool we deploy and sustain GLPI environments end to end. If your team lives with forgotten tickets and email notifications nobody opens, Smart Notify is free and turns on in minutes through the NexTool module catalog - and our sustaining team helps calibrate what each profile receives so the bell becomes signal, not noise.
This content was produced with the help of artificial intelligence and reviewed by the Nextool Solutions team.