Automations
Gordon CRM includes a unified automation engine that lets you connect triggers (things that happen) to actions (things you want to do in response). Automations eliminate repetitive manual work and ensure every lead, registrant, or customer is handled consistently.
How It Works
Every automation rule has three parts:
- Name — A human-readable label for the rule (e.g. "Tag VIP on form submit").
- Trigger — The event that starts the automation (e.g. a form is submitted, a deal moves to a new stage).
- Action — What Gordon CRM does automatically in response (e.g. add a tag, enroll in a campaign, create a task).
When a trigger fires, the engine queries all active rules that match the trigger_type and trigger_id,
then executes each matching action for the contact involved.
Trigger fires → Engine queries matching active rules → Actions execute per-contactArchitecture
Automations are powered by a single server-side function — processAutomationTrigger — that is called from every
part of the application where triggerable events occur:
| Caller | Trigger Type |
|---|---|
Form submission endpoint (/api/forms/[id]) | form_submission (new contacts) |
Form verification endpoint (/api/forms/verify) | form_submission (existing contacts) |
RSVP endpoint (/api/rsvp/[id]) | event_registration |
Eventbrite webhook handler (/api/webhooks/eventbrite) | event_registration |
Stripe webhook handler (/api/webhooks/stripe) | product_purchase |
| Contact tag operations (server actions) | tag_applied, tag_removed |
| Deal stage/status updates (server actions) | deal_stage_changed, deal_status_changed |
Birthday cron sweeper (/api/cron/birthday-sweeper) | contact_birthday |
This centralized design means that new triggers can be added without changing the core engine logic — only a new
call to processAutomationTrigger is needed at the point where the event originates.
The Automation Rule Model
Each automation rule is stored in the automations table:
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
workspace_id | uuid | Tenant isolation — rules belong to a single workspace |
name | text | Human-readable name shown in the UI |
trigger_type | text | One of the eight supported trigger types |
trigger_id | text | The specific entity that fires the trigger (form ID, tag ID, stage ID, etc.) |
action_type | text | One of the seven supported action types |
action_id | text | The target entity for the action (tag ID, campaign ID, or generated UUID for create_task) |
action_config | jsonb | Inline configuration for the action (used by create_task for title, description, assignee, and due offset). Defaults to '{}'. |
is_active | boolean | Toggle to enable/disable without deleting |
created_at | timestamptz | When the rule was created |
updated_at | timestamptz | When the rule was last modified |
RBAC
Automations are classified as structural data in Gordon CRM's role-based access control model:
- Owner & Admin — Can create, edit, toggle, and delete automation rules.
- Member — Can view automation rules but cannot modify them.
Where Automations Are Managed
Automation rules appear in two places within the dashboard:
-
Automations page (
/automations) — The central hub for tag-based, task-creation, and notification rules. Campaign-related rules are excluded from this view because they are managed directly on each campaign. -
Campaign detail page (
/campaigns/[id]) — Entry and exit automations for drip sequences. These rules use theenroll_campaignandremove_campaignaction types and are tightly coupled to campaign lifecycle management.
Automation Detail Dialog
Clicking any automation rule on the Automations page opens a read-only detail dialog that shows the full rule configuration:
- Trigger — The trigger type and entity (resolved to a human-readable name).
- Action — The action type and target entity.
- Configuration — For
create_taskrules: title, description, assignee, and due offset. Forsend_notificationrules: recipient list. - Status — Whether the rule is active or inactive.
The detail dialog is also available from the dependency tracking components — clicking an automation relationship on a form detail, event detail, tag list, or product list opens the same dialog.
Dependency Tracking
Gordon CRM includes a "Where Is This Used?" system that surfaces automation relationships directly on the pages of the components involved — tags, forms, events, and products. This makes it easy to understand how automations are wired together without navigating to the central Automations page.
How It Appears
Dependency tracking uses two shared UI components:
| Component | Used On | Behavior |
|---|---|---|
| DependenciesCard | Form detail, Event detail | Inline card rendered on the page. Fetches and displays all automation relationships on mount. |
| DependenciesDrawer | Tags list, Products list | Side drawer (sheet) opened by clicking an automation badge. Lazy-loads dependency data when opened. |
Automation Count Badges
On list pages (Tags, Products), each item displays an amber ⚡ N badge if it is referenced by one or more automation rules. The counts are batch-fetched on page load alongside the entity data — a single query returns counts for all visible items with no per-item requests.
Items with no automation references show no badge (Tags show "—" in the Automations column).
Natural-Language Rendering
Both components render automation relationships as natural-language sentences instead of raw rule names. Each item reads as a clear cause-and-effect statement with bolded entity names:
- "When this tag is applied to a contact, it enrolls them in the Welcome Drip campaign."
- "When the Lead Magnet Form form is submitted, this tag is added to the contact."
- "When this tag is applied to a contact, it creates a Follow Up task."
- "When this tag is applied to a contact, it sends the Standard Liability Waiver agreement."
This eliminates the "Unnamed Rule" problem for campaign automations — since campaign entry/exit rules don't have user-assigned names, the sentence itself conveys the full relationship.
How It Works (Backend)
Two server actions power the system:
| Action | Purpose |
|---|---|
getComponentDependencies() | Queries the automations table from both directions — as trigger (trigger_id) and as action target (action_id). Uses Promise.all() for concurrent name resolution across up to six tables (campaigns, tags, forms, events, products, agreement_templates). Returns categorized DependencyResult. |
getAutomationCounts() | Batch count query for list pages. Returns a map of componentId → count. Includes an empty-array guard to prevent Supabase IN clause errors on empty pages. |
Cascade Deletion
When a component that is referenced by automation rules is deleted, all associated rules are automatically cascade-deleted. This prevents orphaned rules from referencing entity IDs that no longer exist.
Which Entities Cascade
| Entity | Cascade Scope | Match Column |
|---|---|---|
| Campaign | Rules where the campaign is the action target | action_id |
| Tag | Rules where the tag is the trigger OR the action target | trigger_id OR action_id |
| Form | Rules where the form is the trigger | trigger_id |
| Event | Rules where the event is the trigger | trigger_id |
Automation-Aware Confirmation
When an entity has automation rules referencing it, the delete confirmation dialog includes a warning:
"This [tag/form/event] is used in N automation rule(s). Deleting it will also remove those rules. Continue?"
The count is sourced from the batch-fetched automation counts already loaded at page load — no additional network request is needed for the warning.
Note: Campaign deletions do not show an automation warning because campaign entry/exit automations are conceptually part of the campaign — they are always created and managed on the campaign page itself.
Next Steps
- Triggers — All eight trigger types and how they fire.
- Actions — The seven action types and their behavior.
- Loop Protection — How cascading rules are kept safe, and depth-limit notifications.