Reference → Notifications — Reference

Notifications — Reference

The Notifications surface is the event-to-message plane for SGEN. It owns the rules that decide when a notification fires, the templates that decide what the message says, the channel routing that decides how the message reaches the recipient, and the delivery log that records what happened. Anything the platform sends — order confirmations, form-submission alerts, comment notifications, operator invitations, system alerts — traces back to a record managed here.

This page is a reference for platform engineers and integrators who need to understand the surface before scripting against it, scoping a custom notification, or extending the supported event catalog. Customer-facing notification setup walkthroughs live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.


Overview

Notifications live under the Notifications module in SG-Admin. The module renders four primary views — the rules list, the per-rule editor, the template library, and the delivery log — and exposes a write surface for rule CRUD, template CRUD, channel routing, pause and resume, opt-out management, and per-delivery retry.

A notification rule is three things stored together: a trigger (the event that fires the rule — order placed, form submitted, comment posted, user created, scheduled cron), a recipient resolution (who receives the notification — a fixed operator, the customer who triggered the event, the author of the record, a group of subscribers), and a channel + template binding (which channel — email, in-app, SMS — and which template the channel uses).

Where it lives in SG-Admin:

  • Sidebar: SG-Admin → Notifications
  • URL prefix: /sg-admin/notifications/
  • View templates: application/views/Admin/Notifications/
The module ships with a catalog of pre-defined rules — the standard operational notifications every SGEN site needs (order confirmation, password reset, new comment, contact form submission, low stock, scheduled-post published). Operators can edit the templates, change the recipient resolution, pause individual rules, or add custom rules against the event catalog. Custom rules cannot invent new trigger events; they bind to events the platform already emits.

Three channels are supported by default — email, in-app, and SMS. Email routes through the configured email-service-provider connection (see the Integrations reference). In-app messages persist to a per-user inbox accessible from SG-Admin and from the storefront account area. SMS routes through the configured SMS-gateway connection. Each channel has its own template body — a rule that fires on multiple channels carries multiple templates, one per channel.

┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Notifications → Rules [+ New rule] │├──────────────────────────────────────────────────────────────────────┤│ Rule Trigger Channels State ││ ───────────────────────── ───────────────── ────────── ─────────││ Order confirmation order.placed email active ││ Order shipped order.shipped email+SMS active ││ Password reset user.password_reset email active ││ New form submission form.submitted email active ││ New comment comment.posted in-app paused ││ Low-stock alert inventory.low email active ││ Operator invitation user.invited email active ││ Scheduled post published post.published in-app active ││ ││ [⋯ Edit] [⋯ Pause] [⋯ View deliveries] [⋯ Test send] │└──────────────────────────────────────────────────────────────────────┘

Actions

The Notifications surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.

List rules

Returns the notification rules on the site, paginated, with name, trigger event, active channels, recipient resolution, and state columns. Supports column sort, free-text filter, and state filter (active, paused).

Create rule

Opens the rule editor with an empty form. The operator picks a trigger event from the catalog, selects a recipient resolution from the supported patterns (fixed user, event subject, record author, opted-in subscribers, all operators), picks one or more channels, and binds a template to each channel. On submit the rule persists in the paused state by default — the operator activates it after a test send.

Edit rule

Loads an existing rule into the editor. The same operations available on create are available on edit. Submit replaces the stored configuration. Edits to the recipient resolution or channel set take effect on the next trigger occurrence; in-flight deliveries continue with the previous configuration.

Pause rule

Marks the rule as paused. The trigger event still fires platform-wide, but this rule skips it — no delivery is scheduled, no log entry is written. Other rules listening to the same trigger continue to fire.

Resume rule

Returns a paused rule to active. The next trigger occurrence schedules a delivery.

Edit template

Opens the template editor for a specific channel's template on a rule. The editor offers a subject field (email and in-app only), a body field, a list of available merge tokens (event-shape variables — {{customer.name}}, {{order.total}}, {{form.field_values}}, the event-specific token set), a preview panel that renders the template against a sample event payload, and a test-send control.

Email templates support HTML and plain-text variants; the editor renders both. SMS templates carry a single plain-text body with a character-count indicator. In-app templates carry a body and an optional link target.

Test send

Sends a synthetic delivery using the active template and a sample event payload. The recipient is the operator triggering the test (not the rule's configured recipient). The test does not write to the delivery log; it returns the rendered output and the channel's outcome inline.

Browse delivery log

Returns the delivery records for a rule, paginated, with timestamp, recipient, channel, outcome, and originating event columns. Supports column sort, free-text search across recipient identifiers, date-range filter, and outcome filter (delivered, failed, bounced, opted_out). Each row opens the delivery detail view — the rendered template, the channel's response, and a manual-retry control.

Retry failed delivery

Re-issues a delivery for a failed entry. The system re-resolves the recipient (in case the underlying record changed), re-renders the template (in case it was edited since the original delivery), and re-runs the channel. The retry appends to the delivery log; the original failed entry is retained.

Manage opt-outs

For channels that respect opt-out (email and SMS), opens the opt-out browser. The surface lists every recipient who has opted out, the channel they opted out from, the rule that triggered the opt-out moment, and the timestamp. The operator can search, export, or — with the appropriate capability — clear an opt-out (the consent flow is the operator's responsibility outside the surface).

Subscribe / unsubscribe (visitor-facing)

A reduced version of the opt-out surface exposed to visitors and customers from the storefront account area. The visitor sees the rules they are subject to and toggles per-rule subscription. The toggle writes to the opt-out store; subsequent triggers respect the new state.


Data model

A notification rule carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.

FieldTypeNotes
idintegerPrimary key. Stable across edits.
namestringDisplay name. Unique.
descriptionstringOptional.
trigger_eventstringEvent identifier from the catalog — order.placed, form.submitted, etc.
recipient_resolutionenumfixed_user, event_subject, record_author, opted_in_subscribers, all_operators.
recipient_referencestringType-dependent — user id for fixed_user, ignored otherwise.
channelsarraySubset of email, in_app, sms.
stateenumactive, paused.
is_system_rulebooleanTrue for shipped catalog rules. System rules can be paused and re-templated but not deleted.
created_attimestampSet on create, immutable.
updated_attimestampTouched on save.
A template carries:
FieldTypeNotes
idintegerPrimary key.
rule_idintegerForeign key to the rule.
channelenumemail, in_app, sms.
subjectstringSubject line for email and in-app; null for SMS.
body_htmlstringHTML body for email; null for other channels.
body_plainstringPlain-text body. Required for all channels. SMS uses this exclusively.
merge_token_schemaJSONThe event-specific token set the template can use. Auto-populated from the trigger event.
updated_attimestampTouched on save.
A delivery log entry carries:
FieldTypeNotes
idintegerPrimary key.
rule_idintegerForeign key to the rule.
recipient_identifierstringEmail address, phone number, or user id depending on channel.
channelenumemail, in_app, sms.
event_payload_snapshotJSONThe event payload at fire time.
rendered_subjectstringSubject after merge-token expansion (email and in-app only).
rendered_bodystringBody after merge-token expansion.
outcomeenumdelivered, failed, bounced, opted_out, retried.
channel_response_codeintegerResponse code from the channel transport.
attempted_attimestampWhen the delivery ran.
An opt-out record carries:
FieldTypeNotes
idintegerPrimary key.
recipient_identifierstringEmail or phone.
channelenumemail, sms.
rule_idintegerOptional. Null for global opt-out (all rules on the channel).
opted_out_attimestampWhen the opt-out was recorded.
sourceenumvisitor_link, bounce_threshold, operator_manual.
Event-payload snapshot: the delivery log carries the event payload inline so the historical record stays accurate even if the underlying record (the order, the form submission, the user) is later edited or deleted. Re-rendering the template uses the live event lookup; the snapshot is for audit.

System-rule semantics: rules with is_system_rule = true ship with the platform and cannot be deleted. The operator can edit the templates, pause the rule, and change the recipient resolution. The trigger event and the rule identifier are fixed.

Opt-out scope: an opt-out can be global (the rule_id field is null — applies to all rules on the channel) or per-rule. The two are checked in sequence at fire time — a global opt-out always wins; a per-rule opt-out applies only to the matching rule.

TRIGGER EVENT FIRES│ (order.placed, form.submitted, user.invited,...)▼┌──────────────────────────┐│ Match rules on event │ all rules with this trigger event└──────────────┬───────────┘│ for each matching rule▼┌──────────────────────────┐│ Filter by state │ paused → skip└──────────────┬───────────┘│ active rules▼┌──────────────────────────┐│ Resolve recipient │ fixed user / event subject / record│ │ author / opted-in subscribers / all ops└──────────────┬───────────┘│▼┌──────────────────────────┐│ Check opt-out store │ opted-out → skip + log opted_out└──────────────┬───────────┘│▼ for each channel on the rule┌──────────────────────────┐│ Render template │ expand merge tokens against payload└──────────────┬───────────┘│▼┌──────────────────────────┐│ Dispatch via channel │ email-service / in-app store / SMS└──────────────┬───────────┘│▼delivery log entry+ outcome (delivered / failed / bounced)

Permissions

Access to the Notifications surface is gated at two layers.

Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Notifications surface.

Layer 2 — per-action capability. Within SG-Admin, each Notifications action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:

CapabilityAdministratorEditorViewer
List rules
Create rule
Edit rule (trigger, recipient, channels)
Edit template
Pause / resume
Delete custom rule
Test send
Browse delivery log
Retry failed delivery
Manage opt-outs (operator-facing)
Visitor-facing subscribe / unsubscribealwaysalwaysalways
Visitor-facing subscribe and unsubscribe are not gated by the role system — they expose to anyone holding a signed unsubscribe link or an authenticated storefront session for their own opt-out state. The operator-facing opt-out browser is the privileged surface.

Recipient privacy. The delivery log carries the recipient identifier (email, phone) in cleartext. Custom roles may scope log visibility to rules-this-operator-owns rather than all rules — useful in shared sites where a marketing operator and an operations operator each need their own slice. The scope is configured under Settings → Roles and enforces at log-browse time.

Channel-credential cascade. Email and SMS channels depend on the configured connection records (the email-service-provider connection for email, the SMS-gateway connection for SMS). A notification rule that targets a channel without a configured connection fails at delivery time with a structured channel-not-configured outcome — the rule itself is not rejected, but no message goes out.

Audit. Every rule create, edit, pause, resume, delete, template edit, test send, retry, and opt-out clear emits an Activity Log entry. The log records the acting operator, the rule identifier, and the change shape. Delivery-log entries are their own audit surface and are not duplicated to the Activity Log to keep log volume manageable.

System-rule protection. System rules cannot be deleted by any role. Their trigger event and rule identifier are fixed at the platform level. The protection prevents an operator from breaking a transactional flow (order confirmation, password reset) by accident.

NOTIFICATION ABOUT TO DELIVER│ rule = "Order shipped" channel = "email"│ recipient = "customer@example.com"▼┌───────────────────────────┐│ Global opt-out check │ recipient + channel, rule_id=null└─────────────┬─────────────┘│ no global opt-out▼┌───────────────────────────┐│ Per-rule opt-out check │ recipient + channel + rule_id└─────────────┬─────────────┘│ no per-rule opt-out▼┌───────────────────────────┐│ Channel-credential check │ email-service connection active?└─────────────┬─────────────┘│ connection active▼dispatch+ delivery log = delivered│▼ alternate outcomesopt-out present → log = opted_outno connection → log = failed (channel-not-configured)channel returns error → log = failed (vendor response code)

Related references

  • Integrations — Reference. Email-service and SMS-gateway connections live there; the channel-credential cascade routes through their state.
  • Forms — Reference. Form-submission events drive the form.submitted trigger; the form's own routing configuration is separate from notification rules.
  • Users — Reference. Recipient resolution against fixed_user and record_author patterns references user records.
  • Settings — Reference. Owns the channel defaults, delivery-log retention period, opt-out store retention, and the per-rule recipient overrides at the site level.
  • Orders — Reference. Order-lifecycle events drive a large share of the system-rule catalog.
  • Posts — Reference. Scheduled-post publication fires a notification trigger.
  • Discussions — Reference. Comment events fire notification triggers.
For the corresponding customer-facing walkthrough — editing the order-confirmation template, adding an SMS channel, managing opt-outs — see the Notifications section of the customer docs at /docs/notifications.
On this page