Triggers & targeting
Triggers decide when a form fires. Targeting and eligibility decide whether that person is allowed to see it. Both are configured per form in the console — your app only supplies the raw material: events, traits, and context.
Evaluation order
When a trigger matches, or you call showForm(), the SDK checks three things in this order. All must pass.
Triggers
A form carries a list of triggers. A registered form fires when any one of them matches.
| Kind | Fires when | What your app must do |
|---|---|---|
event | You track a matching event name, optionally with matching properties. | Call track(). |
url | The current URL matches by exact, contains, or regex. | Nothing — the SDK watches navigation, including SPA route changes. |
user | The identified user’s traits match. | Call identify(). |
time | The user has been on the page for afterMs. | Nothing. |
exit_intent | The pointer leaves toward the browser chrome. | Nothing. Desktop pointers only. |
manual | Never automatically. | Call showForm() yourself. |
Event triggers
The most useful kind, because you control exactly when they happen. Track a business event and let the console decide which form, if any, responds to it.
client.track('checkout_completed', { value: 99, currency: 'USD' })
client.track('feature_used', { feature: 'export' })A trigger can additionally require property equality, so one event name can drive several forms:
// Console config for the form:
{ kind: 'event', eventName: 'feature_used', propertyEquals: { feature: 'export' } }Setting disableEventApi: true stops events being POSTed to Intunix, but they still evaluate triggers locally. Useful when you have your own analytics pipeline and only want Intunix for the forms.
Targeting
Targeting filters who qualifies. Rules are ANDed — every rule must pass.
Rules
Each rule is { kind, key, op, value }. kind selects what is being matched:
trait— a trait fromidentify().context— a value fromsetContext()or a per-call context.url— the current page URL.
And op is one of eq, neq, in, nin, gt, lt, contains, or exists.
// Console config — show only to pro users, on course c-101, off the pricing page
targeting: {
rules: [
{ kind: 'trait', key: 'plan', op: 'eq', value: 'pro' },
{ kind: 'context', key: 'courseId', op: 'eq', value: 'c-101' },
{ kind: 'url', op: 'contains', value: '/pricing' },
],
}Your app's side of that is just supplying the data:
client.identify('user_42', { plan: 'pro' })
client.setContext({ courseId: 'c-101' })Traits from identify() are not persisted. After a page reload the user is identified again only when your app calls identify() again — so call it on every app boot where you know who the user is, not just at the moment of login. Trait-based targeting silently fails to match otherwise.
Eligibility
Eligibility gates on how long someone has been around and when the form is scheduled to run. These are device-level facts the SDK tracks itself.
| Field | Meaning | Example |
|---|---|---|
minSessions | Skip users with fewer than N sessions. Avoids surveying first-time visitors. | 2 |
minDaysSinceFirstSeen | Skip users first seen fewer than N days ago. | 3 |
startAt | ISO date-time before which the form is not eligible. | "2026-08-01T00:00:00Z" |
endAt | ISO date-time after which the form stops being eligible. | "2026-09-01T00:00:00Z" |
A session lasts 30 minutes of inactivity. Any tracked event or navigation renews it; a gap longer than that starts a new one and increments the session count.
reset() deliberately keeps firstSeenAt and the session count. They describe the device, not the account — clearing them would let anyone reset themselves to a “brand-new user” simply by logging out, defeating minSessions entirely.
autoActivate
A form marked autoActivate in the console registers itself as soon as the catalog loads — no register() call in your code. It only takes effect under register: 'all', since otherwise the form is never fetched. This is what lets a marketing team launch a form on a WordPress or Shopify site with no developer involved.
Next: Cadence — how often the same person may see a form that passes all of this.