Skip to Content
ConceptsHow Triggering Works

How Triggering Works

Every platform runs the same two-stage check before a survey can show. Nothing here is platform-specific — all three implementations (web, Android, iOS; Flutter bridges the natives) agree on this behavior, verified against the same stage1/stage2 contract fixtures.

Stage 1: Trigger Check

The cheap eligibility check, run first, with no script execution:

  • Does the Trigger (a named event, or a DOM condition on web) match?
  • Is the survey allowed to resurvey this user (or was it already shown/completed/ dismissed)?
  • Is the Cooldown or Daily Cap satisfied?
  • Is another survey already active? (Only one survey evaluation runs at a time — see Trigger Queue below.)

A survey with no triggerEventNames matches any event (a wildcard). Otherwise the incoming event name must be a member of that list.

Stage 2: Rules Engine

Only runs if a survey passes Stage 1 and defines trigger rules. Executes a JS filter script (oneSygnalFilterSurvey) fetched from the backend, evaluated against the user’s traits, context, and the triggering event — identically across QuickJS (Android), a JavaScriptCore context (iOS), and browser JS (web). This is the one place all three engines must produce byte-identical pass/fail decisions for the same input.

EVENT_FREQUENCY/EVENT_RECENCY/EVENT_ABSENCE rules read a user’s eventHistory (capped at 90 days / 100 timestamps per event / 50 distinct event names). If a client’s local history doesn’t have an entry for a given event name at all, that’s treated as “never happened” and evaluated normally — but if the history object is entirely absent (an old SDK build talking to a newer filter script), every one of these rules fails open (returns true) rather than silently making surveys unfireable with no signal why.

Trigger Queue

Concurrent trigger evaluations are serialized — only one survey evaluation runs at a time, in submission order. This prevents two events firing in quick succession from racing to show two surveys at once.

See Throttling for Cooldown/Daily Cap mechanics, and Survey Lifecycle Events for what fires once a survey does show.