Automations
Triggers

Triggers

A trigger is the event that causes an automation rule to fire. Each trigger is scoped to a specific entity via its trigger_id — for example, a particular form, a particular tag, or a particular pipeline stage.

Gordon CRM supports eight trigger types.


Entity-Based Triggers

These triggers fire when a contact interacts with a specific entity in the CRM.

"Any" option: Each entity-based trigger supports an "Any" option (e.g. "Any Form", "Any Event", "Any Tag", "Any Product") that fires the rule regardless of which specific entity was involved. This is useful for broad rules like "When any form is submitted → send notification."

Form Submitted

trigger_typeform_submission
trigger_idThe UUID of the specific form
Fires whenA contact submits a headless form (see Context-Aware Double Opt-In below)
Called from/api/forms/[id] (new contacts) or /api/forms/verify (existing contacts)

Context-Aware Double Opt-In

Gordon CRM uses a split processing model based on whether the submitter already exists in the workspace:

  • New contact — The contact is created immediately, the submission is logged, and the automation fires right away in the form submission endpoint (/api/forms/[id]). No email verification is required because a brand-new email address has no prior data to protect.

  • Existing contact — The submission is staged in a pending_form_submissions table with a secure token, and a verification email is sent. The automation only fires after the contact clicks the verification link (/api/forms/verify), which prevents impersonation attacks that could overwrite existing contact data.

Example use case: When someone submits the "Request a Demo" form → add the "Demo Request" tag.


Event Registration

trigger_typeevent_registration
trigger_idThe UUID of the CRM event
Fires whenA contact registers for an event (manual RSVP or Eventbrite ticket purchase)
Called from/api/rsvp/[id] (manual events) and /api/webhooks/eventbrite (Eventbrite events)

This trigger fires from both event sources:

  • Manual events — When a contact submits the public RSVP form, the automation fires after the registration record is created or re-activated.

  • Eventbrite events — When the Eventbrite webhook handler (order.placed or attendee.updated) processes a registration, it also calls processAutomationTrigger with the CRM event ID. The handler deduplicates per-contact — if a single order contains multiple tickets for the same contact, the automation fires only once.

Note: For Eventbrite events, the trigger_id is the CRM event UUID (not the Eventbrite event ID). This means the same automation rule works regardless of whether the registration came through the native RSVP form or an Eventbrite webhook.

Example use case: When someone registers for "Spring Gala 2026" → enroll in the "Event Reminder" campaign.

See also: Events → Registration & Public Pages for the full registration flow, and Events → Eventbrite Integration for webhook processing details.


Product Purchase

trigger_typeproduct_purchase
trigger_idThe UUID of the purchased product
Fires whenA Stripe checkout.session.completed webhook is received for a linked product
Called from/api/webhooks/stripe — after the payment is verified and the contact is matched

Example use case: When someone purchases "Annual Membership" → add the "Member" tag.


Tag-Based Triggers

These triggers fire when a tag is added to or removed from a contact. They can be caused by manual user action or by a preceding automation action.

Tag Applied

trigger_typetag_applied
trigger_idThe UUID of the tag that was applied
Fires whenThe specified tag is added to a contact
Called fromThe processAutomationTrigger engine itself (cascading), or manual tag operations

Example use case: When "VIP" tag is applied → enroll in the "VIP Welcome Sequence" campaign.


Tag Removed

trigger_typetag_removed
trigger_idThe UUID of the tag that was removed
Fires whenThe specified tag is removed from a contact
Called fromThe processAutomationTrigger engine itself (cascading), or manual tag operations

Example use case: When "Active Member" tag is removed → remove from the "Members-Only Newsletter" campaign.


Deal Triggers

These triggers fire when a deal progresses through a sales pipeline. Both use a cascading pipeline → stage/status picker in the UI.

Deal Stage Changed

trigger_typedeal_stage_changed
trigger_idSee patterns below
Fires whenA deal is moved to a matching stage (via drag-and-drop on the Kanban board or manual edit)
Called fromDeal update server actions

The UI uses a two-tier picker: first select a pipeline (or "Any Pipeline"), then select a stage within that pipeline (or "Any Stage").

PipelineStagetrigger_id Pattern
Any PipelineAny Stage__any__
Specific PipelineAny Stage{pipelineId}__any_stage__
Specific PipelineSpecific Stage{stageId}

Example use case: When a deal moves to the "Proposal Sent" stage → add the "Proposal Sent" tag.


Deal Status Changed

trigger_typedeal_status_changed
trigger_idSee patterns below
Fires whenA deal's terminal status is changed to Won or Lost
Called fromDeal update server actions

The UI uses a two-tier picker: first select a pipeline (or "Any Pipeline"), then select a status (Won, Lost, or "Any Status").

PipelineStatustrigger_id Pattern
Any PipelineAny Status__any__
Any PipelineWon or Lost__any___won or __any___lost
Specific PipelineAny Status{pipelineId}__any_status__
Specific PipelineWon or Lost{pipelineId}_won or {pipelineId}_lost

Example use case: When any deal is marked as "Won" → send notification to the sales manager.


Lifecycle Triggers

Contact Birthday

trigger_typecontact_birthday
trigger_id__birthday__ (static sentinel value)
Fires whenThe daily birthday cron sweeper finds contacts whose birthday matches today
Called from/api/cron/birthday-sweeper

Unlike other triggers, this one does not require a specific entity to be selected in the UI — it fires globally for all contacts in the workspace whose birth_month and birth_day fields match the current date.

Example use case: On a contact's birthday → enroll in the "Birthday Greeting" campaign.


Trigger Resolution

When a trigger fires, the engine resolves human-readable names for display purposes:

Trigger TypeResolution Strategy
form_submissionForm name from forms table (or "Any Form")
event_registrationEvent name from events table (or "Any Event")
product_purchaseProduct name from products table (or "Any Product")
tag_applied / tag_removedTag name from tags table (or "Any Tag")
deal_stage_changed"Pipeline Name: Stage Name", "Pipeline Name: Any Stage", or "Any Pipeline: Any Stage"
deal_status_changed"Pipeline Name: Won/Lost", "Pipeline Name: Any Status", "Any Pipeline: Won/Lost", or "Any Pipeline: Any Status"
contact_birthdayStatic label: "Contact's Birthday"