Actions
An action is what Gordon CRM does automatically when a matching trigger fires. Each action targets a specific
entity via its action_id — either a tag or a campaign.
Gordon CRM supports four action types, split into two categories.
Tag Actions
Tag actions modify a contact's tags. These are the most common automation actions and appear on the central
Automations page (/automations).
Add Tag
| action_type | add_tag |
| action_id | The UUID of the tag to apply |
| Behavior | Adds the specified tag to the contact. Uses UPSERT with ON CONFLICT … DO NOTHING for idempotency — if the contact already has the tag, the operation is silently skipped. |
After a tag is successfully added, the engine fires a cascading tag_applied trigger for the newly added tag.
This enables chaining — for example, adding tag A can trigger a rule that enrolls the contact in a campaign.
Form submitted
→ Action: Add "VIP" tag
→ Cascading trigger: "VIP" tag applied
→ Action: Enroll in "VIP Welcome" campaignImportant: Cascading tag triggers increment an internal depth counter. If the depth exceeds 3, the chain is terminated to prevent infinite loops. See Loop Protection.
Remove Tag
| action_type | remove_tag |
| action_id | The UUID of the tag to remove |
| Behavior | Removes the specified tag from the contact. If the tag was not applied, the operation is silently skipped. |
After a tag is successfully removed (confirmed by checking the return value), the engine fires a cascading
tag_removed trigger. This allows exit workflows — for example, removing a "Member" tag can unenroll a
contact from member-only campaigns.
Campaign Actions
Campaign actions manage a contact's enrollment in drip sequence campaigns. These rules are managed on each
Campaign detail page (/campaigns/[id]) and are excluded from the central Automations page.
Enroll in Campaign
| action_type | enroll_campaign |
| action_id | The UUID of the campaign |
| Behavior | Creates a campaign_enrollments row for the contact with status: active. Uses the campaign engine to calculate the first eligible step and its scheduled next_action_at timestamp. |
The enrollment process includes multiple safety checks:
- Active enrollment check — If the contact already has an
activeorprocessingenrollment in the same campaign, the action is skipped entirely. - Trigger event dedup — If a
triggerEventIdis provided (e.g., from an event registration), the engine checks for a priorcompletedenrollment with the same trigger event ID. This prevents webhook retries from re-enrolling contacts. - Campaign status check — The campaign itself must be in
activestatus. Draft or paused campaigns will not accept new enrollments. - Step calculation — The campaign engine's
calculateNextCampaignStepfunction determines when the first email should be sent based on delay offsets and event dates. If all steps are in the past (late enrollee), the enrollment is immediately marked ascompleted.
Remove from Campaign
| action_type | remove_campaign |
| action_id | The UUID of the campaign |
| Behavior | Sets the contact's active enrollment to status: cancelled and records a cancelled_at timestamp. Only cancels enrollments with active or processing status. |
This is typically used as part of an exit criteria workflow on the campaign detail page — for example, "When the contact is tagged as 'Unresponsive' → remove from this campaign."
Where Actions Are Managed
| Action Type | Managed On | Why |
|---|---|---|
add_tag, remove_tag | Automations page (/automations) | General-purpose rules, not tied to a specific campaign |
enroll_campaign, remove_campaign | Campaign detail page (/campaigns/[id]) | Tightly coupled to campaign lifecycle; entry/exit criteria belong with the campaign |
This split keeps the UI focused — marketers manage campaign enrollment rules alongside the campaign itself, while system-level tag automations live in a central hub.
Action Entity Resolution
When displaying rules in the UI, the engine resolves action_id values to human-readable names:
| Action Type | Resolution Strategy |
|---|---|
add_tag / remove_tag | Tag name from the tags table |
enroll_campaign / remove_campaign | Campaign name from the campaigns table |