This project is not covered by Drupal’s security advisory policy.

Conditional Notification sends the right message to the right people at the right moment — modelled entirely in content, no custom code required.

Editors and site builders create notification templates (subject, message text, conditions, deliveries) that fire when entities are saved. Per-entity overrides adjust or suppress a template for one specific context — one course, one group, one department — so a single template scales across an entire site while every stakeholder keeps control over their corner of it. An override only varies a notification its trigger already fires: it never creates a firing event of its own, so the trigger list stays the complete inventory of what your site sends, and handing overrides to editors never widens it.

Why this module?

  • Config first: triggers, conditions, recipients and texts live in content and configuration — site builders model workflows, developers only extend.
  • Smart scoping: notifications follow your data model. Scope resolutions walk entity references (built hop by hop in the UI — no unresolvable paths), and scope providers resolve special relations in code, e.g. a group membership to its group. Overrides are matched against the resolved scope entity, so an override on a container adjusts everything triggered inside it; where the scope has moved away, the triggering entity's own override still applies. Saving and the cron re-evaluation resolve overrides identically.
  • Real conditions: nestable AND/OR condition trees, including time-based conditions ("3 days before the start date") that are tracked and evaluated on cron — sent exactly once, re-armed when dates move.
  • Multi-channel by design: the core is delivery-agnostic. Channels are submodules; recipients are deduplicated per channel, tokens are replaced everywhere.

What does that look like in practice?

  • Course reminders that manage themselves: "Three days before a course starts, text every participant a reminder with room and time." The time-based condition is tracked on cron and sent exactly once — and when the trainer moves the start date, the reminder re-arms and fires again at the right moment.
  • One template, per-event exceptions: a site-wide "registration confirmed" e-mail covers every event. For the annual conference, the organizer adds an override on that one event with custom wording — and for the internal test event, an override simply switches the notification off. Nobody touches the global template.
  • Welcome new members where they arrive: when someone joins a group, the membership itself is the trigger: the new member gets a welcome e-mail, the group's coordinators get an SMS — same event, two channels, recipients deduplicated automatically.
  • Escalate to the tools your team lives in: "when a VIP registers, post to our support channel" — the ECA model delivers delivery hands the full context to an ECA model, which calls the webhook. No PHP written, no template changed.
  • Notify up the hierarchy: a scope resolution like activity → event → responsible department means an override placed on the department adjusts the notifications for everything happening beneath it.

Delivery channels included

  • E-mail via Symfony Mailer — Mailer Policy applies (sender, theme, reroute), recipient address from the account or a configurable field.
  • SMS via Symfony Notifier transports — bring the bridge of your provider (Twilio, Vonage, …). Credentials stay out of your config: DSNs are read through Key entities, e.g. from a container secret. Messages are generated from your template text, converted to plain text automatically.
  • ECA — the ECA model delivers delivery hands the whole notification to an ECA model as an event with full context tokens: post to a webhook, write a log, do anything a model can. An ECA model decides condition lets models answer conditions, too.
  • Group integration for Group: notify all group members or the user of the triggering membership, by e-mail or SMS — loosely coupled, each channel active only while its submodule is installed.

Built to be extended

Two plugin types (conditions and deliveries, both context-aware), scope providers as tagged services, and a fieldable template/override pair where every same-named field merges automatically. A new channel is a small submodule: a base class wrapping the transport, one delivery plugin declaring its channel — queueing, per-channel deduplication and token replacement come from the core.

Requirements

  • Drupal 11.1+, PHP 8.4+
  • Dynamic Entity Reference, Token
  • Per channel (optional): Symfony Mailer for e-mail; Key plus the symfony/*-notifier bridge of your SMS provider for SMS; ECA; Group.

Versions

Use 2.0.x. Version 2.0 is a complete rewrite with a new data model and new APIs — it shares no code or configuration with the legacy 1.0.x branch, which is unsupported. There is no upgrade path from 1.x to 2.x: existing 1.x notifications have to be migrated manually (recreate templates, overrides and settings in 2.x). Setup guides with copy-paste examples — including an end-to-end Twilio walkthrough — live in the README.

The 2.0.x branch is in alpha, and alpha releases may change behavior without a deprecation period. 2.0.0-alpha5 is such a release: an override no longer triggers its template on its own. If you run an earlier alpha, review your overrides for scope entities their trigger cannot reach — the override form now warns about those, and they no longer send anything. See the CHANGELOG for details.

Credits

The 2.x rewrite is developed and maintained by Daniel Pernold at think modular – digital solutions GmbH.

Supporting organizations: 
Idea, Concept and Funding of the complete work

Project information

Releases