Trigger Rules
Overview
A Trigger Rule is a one-to-one "When → Then" automation built through a plain form rather than a drag-and-drop canvas. The admin picks the event that fires the rule, optionally narrows it with conditions, and chooses a single action to perform — all controlled by an on/off switch.
The feature suits admins who want straightforward automation: switching a customer's Rich Menu when their profile data changes, or sending a Rich Message the moment someone joins a target audience, without designing an entire workflow.
Each rule holds the following data:
| Field | Description |
|---|---|
| Rule name | The label shown in the list and on the execution log page |
| Source | The event type that fires the rule, plus its type-specific configuration |
| Action | What the system does when the rule fires, plus that action's configuration |
| Frequency | How often the rule may fire again for the same user |
| Status | Whether the rule is enabled |
Four source types are supported:
| Type | Use it when |
|---|---|
| Attribute change | A user attribute changes and matches the configured conditions |
| Audience membership | A user is added to or removed from a specific audience |
| Form submitted | Someone submits a form built with the Form Builder |
| Campaign click | A user clicks a tracked spot in a campaign |
How this differs from Workflow Automation
| Aspect | Trigger Rule | Workflow |
|---|---|---|
| Authoring | A standard form | A drag-and-drop canvas |
| Structure | One event → one action, no branching | A multi-node graph with branches (conditions, delays, splits, AI) |
| Conditions | Multiple conditions joined by AND/OR at a single level | Condition nodes with yes/no branches, multi-splits, and split tests |
| Status | Enabled / disabled | Draft / active / inactive |
| Version history | None | Full history with rollback |
| Testing | None | Dry runs and a chat sandbox |
The important relationship is that Workflow sits above Trigger Rule. Activating a workflow generates rules bound to it; those rules carry a badge in the list with a tooltip naming the owning workflow, and clicking the badge jumps straight to that workflow — a signal that such rules should not be edited from this page.
In the other direction, the condition and frequency enums are defined here and reused by the workflow nodes, which makes Trigger Rule the single source of truth for the condition vocabulary shared by both modules.
Business Flow
Managing the rule list
- Opening the list checks the user's access rights first (the
VIEWpermission on thetrigger-rulemodule). All three pages of this feature are gated the same way. - The table loads rules sorted by creation date, showing the row number, rule name, source type, a condition summary, action type, the enable switch, the creation date, and action buttons (logs / edit / delete).
- Rules generated by a workflow carry a badge next to their name linking to the owning workflow.
- Rules can be enabled or disabled straight from the switch; the change is saved immediately and the list refreshes. Failures surface as an error dialog.
- Deletion requires confirmation in a dialog, after which the table refreshes.
- Note: this list currently has no search or filter controls, and the condition summary column is fully detailed only for attribute-change rules — other source types show an abbreviated summary.
Creating and editing a rule
Loading the option data
- Opening the form loads every option set in parallel: attributes (merge tags), audiences, active Rich Menus that are available to automation, active Rich Messages, active forms, and campaigns.
- Edit mode loads the existing rule and maps it back onto the form fields. The form stays hidden until every value is in place, so an empty form is never briefly visible.
- Create mode defaults to an attribute-change source, a switch-Rich-Menu action, enabled status, once-per-hour frequency, and one empty condition row joined by AND.
The "When" section
- The source type is chosen from four options; the section beneath it changes to match.
- Attribute change — conditions can be added as multiple rows, each combining the attribute to watch, a comparison operator, and a value.
- The operator list is filtered by the attribute's data type — text, number, date, boolean, and so on.
- Operators that need no value (exists, does not exist, has changed, is today) hide the value field automatically.
- Day-count operators (days before / days after) accept numbers only.
- Changing a row's attribute clears that row's operator and value so nothing incompatible with the new data type is left behind.
- When more than one row exists, a selector appears for whether all conditions must match (AND) or any single one is enough (OR).
- Audience membership — pick the audience and whether the rule fires on add or on remove.
- Form submitted — pick a form from the active list.
- Campaign click — pick the campaign and the tracked spots (free text entry is allowed), plus the same optional condition block as attribute change; here the conditions are not required.
- Frequency — shown for every source type, with four options: every time, once per hour, once ever, and a custom cooldown. The custom option asks for a number and a unit (seconds / minutes / hours / days), which the system converts to seconds before saving.
The "Then" section
- The action type is chosen from a set of option buttons.
- Switch Rich Menu — select the Rich Menu the user should be moved to.
- Send message — select the Rich Message to send, plus a switch for link-click tracking on that message.
- Note: the three remaining action options (add to audience, remove from audience, update attribute) have no configuration fields in the UI yet and are therefore not usable in the current version.
Saving
- Pressing save opens a confirmation dialog before anything is submitted.
- On confirmation, the payload is assembled according to the selected types. An attribute-change rule with a single condition is stored in the single-condition shape for backward compatibility, while multiple conditions are stored together with their AND/OR operator.
- A successful save shows a result dialog whose close button returns the user to the list.
- Field-level errors returned by the server are displayed inline beneath the relevant field; any other failure surfaces as an error dialog.
- When an existing rule is reopened, the form accepts both the single-condition and multi-condition shapes, and converts a stored cooldown back into the most readable unit automatically.
Reviewing execution logs
- The log page is reached from the list. Opening it without a rule id shows a not-found screen.
- The header shows the rule name, its current status, a back button, and a refresh button that reloads both the statistics and the log list.
- Three statistic cards cover total executions with success/failure counts, a success-rate gauge that changes colour by threshold, and link-tracking numbers (reach, unique clicks, and total clicks).
- Logs can be filtered by keyword, success/failure status, source type, and date range.
- The log table shows the user id (truncated with a copy action), the source, the action, the status, any error message, and the execution timestamp.
- Note: the source filter currently covers only attribute change and audience add/remove, and the action column renders just two values — switch Rich Menu and send message.
Key Screens & Components
List page (/trigger-rule)
- Rule table — name, source, condition summary, action, status, and creation date, with horizontal scrolling on narrow screens.
- Workflow badge — marks rules generated by a workflow and links to the owning workflow.
- Enable switch and delete button — the switch saves immediately; deletion asks for confirmation first.
Primary files: src/app/trigger-rule/page.tsx, src/components/trigger-rule/list/trigger-rule-list.container.tsx
Form page (/trigger-rule/form)
- Form header — the rule name and the enable switch.
- When block — the source type selector, the repeatable condition rows, and the frequency selector.
- Then block — the action type selector and the configuration fields for that action.
- Footer actions — cancel returns to the list; save opens the confirmation dialog before submitting.
Primary files: src/app/trigger-rule/form/page.tsx, src/components/trigger-rule/form/trigger-rule-form.container.tsx, src/components/trigger-rule/form/trigger-rule-form.tsx
Log page (/trigger-rule/logs)
- Header — rule name, status, back button, and refresh.
- Statistic cards — execution totals, success rate, and link-tracking figures.
- Filters and log table — keyword, status, source, and date-range filtering over the execution history.
Primary files: src/app/trigger-rule/logs/page.tsx, src/components/trigger-rule/logs/trigger-rule-logs.container.tsx
Shared option definitions
src/components/trigger-rule/form/enums/trigger-rule.enum.ts holds the feature's full vocabulary: four source types, five action types, the audience add/remove options, four frequency options, twenty comparison operators, and the mapping of which operators apply to which data types. Workflow reuses this file directly.
API service
All calls live in src/services/trigger-rule.service.ts under the trigger-rules base path.
| Capability | Endpoint |
|---|---|
| List rules | GET /trigger-rules |
| Get a single rule | GET /trigger-rules/{id} |
| Create a rule | POST /trigger-rules |
| Update a rule (including enable/disable) | PUT /trigger-rules/{id} |
| Delete a rule | DELETE /trigger-rules/{id} |
| Fetch execution logs | GET /trigger-rules/{id}/logs |
| Fetch statistics and link tracking | GET /trigger-rules/{id}/stats |
| List rules bound to an audience | GET /trigger-rules/by-audience/{audienceId} |
Dependencies
- Permissions — all three pages are gated by the
trigger-rulemodule permission. - Workflow Automation — the layer above, generating and owning some rules on the user's behalf; workflow-owned rules should be edited from the workflow page. Workflow also borrows this feature's operator and frequency definitions.
- Audience — both a source of events (membership add/remove) and a consumer, since the audience detail page lists the rules bound to a given audience.
- Form Builder — supplies the forms available to the form-submitted source.
- Campaign and Audience Filter — supply the campaigns and tracked spots used by the campaign-click source.
- Rich Menu and Rich Message — the targets of the two working actions, offered as options from their active records only.
- Attributes / merge tags — supply the attribute list and the data types that determine which operators are selectable; system-level attributes are excluded from this feature's options.
- Shared infrastructure — the CMS authentication and HTTP client (automatic sign-out on token expiry), the breadcrumb and side-menu system, the standard modal set, and the shared field-level error handling used across the CMS.
Backend Details (CMS API)
The backend lives in internal/modules/triggerrule/. This module is only the authoring and reporting side — rules are actually executed by line-management-worker-go, a separate service.
Required permissions
- Every route is wrapped in the module gate for the
trigger-rulemodule; organisations without it are rejected before the handler runs. - Policies are split by action:
readfor the list, the dropdown options, rule detail, statistics, logs, and the lookup by audience;create/update/deletefor the corresponding operations. - Enabling and disabling a rule goes through the ordinary update endpoint, so it requires the
updatepermission rather than a separate one.
Validation and business rules enforced by the backend
- When a rule is created, the backend verifies that everything the rule references actually exists — the audience, the form, and the campaign. Referencing something deleted or non-existent returns an error identifying exactly which reference is wrong, rather than saving quietly and failing at execution time.
- That check is performed with queries written directly in this module rather than going through the owning modules' layers.
- The source-type options the form loads through
GET /api/trigger-rules/dropdownare cached in Redis (theTRIGGER_SOURCE_TYPESkey) rather than being re-read from the database on every call. GET /api/trigger-rules/by-audience/:audienceIdis a purpose-built endpoint answering which rules are bound to a given audience. It is used before deleting an audience, to warn that rules depend on it.
What gets stored, and the side effects
- Rules are stored in the
trigger_ruletable and individual executions intrigger_log, with cross-references intoaudience,form_builder,campaign, andworkflow. - This module does not publish queue messages itself. The events that fire rules arrive on the system's message queues, published by other features: audience membership changes, form submissions, campaign clicks, inbound messages, and booking events.
- At execution time the worker reads rules from Redis (the
TRIGGER_RULESkey) rather than hitting the database each time, and uses a locking mechanism (TRIGGER_LOCK) to prevent the same rule from running concurrently more than once. Results are then written intotrigger_log. - Actions that call an external API are handed off through the
web_request_executequeue for the worker to perform.
Edge cases worth knowing
- The backend supports more source types than the UI exposes — notably "message received" and the booking event family. Those reach the table mainly through Workflows compiled down into rules rather than being created directly from the Trigger Rule form.
- The statistics column on the list page is computed per row as part of the list query, so page load time degrades as the number of rules and the accumulated log volume grow.
- Because the worker reads rules from a cache, an edited rule may not take effect on the very next execution. If a freshly edited rule still behaves the old way, check the cache first.
- Workflow-generated rules live in the same table as hand-made ones, so editing them from this page does save — but the change is overwritten the next time the owning workflow is saved or activated.