Skip to content

Events & Analytics

import { Aside } from ‘@astrojs/starlight/components’;

The SDK tracks placement impressions and interactions automatically. You can also emit custom events and trigger events for behavioral signals.

The SDK tracks these events automatically when using React components or headless controllers:

EventWhenData
ImpressionPlacement becomes visibleplacementId, templateId, userId
DismissUser dismisses a placementplacementId, interactionType: 'dismiss'
CTA ClickUser clicks primary CTAplacementId, interactionType: 'cta_clicked'
CTA CompleteUser completes the CTA flowplacementId, interactionType: 'cta_completed'
SnoozeUser chooses “remind me later”placementId, interactionType: 'remind_me_later'

You don’t need to instrument these — the slot components and hooks handle it.

Track any behavioral signal with trackEvent:

const { sdk } = useRevTurbine();
// Track a custom event
await sdk.trackEvent('feature_explored', {
feature: 'advanced_filters',
source: 'sidebar_menu',
});
// Track a conversion signal
await sdk.trackEvent('checkout_completed', {
plan: 'professional',
billing_cycle: 'annual',
revenue: 99.00,
});
FieldTypeDescription
namestringEvent name (use snake_case)
dataRecord<string, string | number | boolean>Optional event properties

Trigger events are semantic lifecycle signals that the SDK uses to evaluate targeting rules. When you emit a trigger, the SDK re-evaluates all active placements.

TriggerWhen to Emit
trial_startedUser begins a free trial
trial_expiringTrial is ending soon
trial_expiredTrial has ended
usage_limit_approachingUsage is near the limit (e.g., 80%)
usage_limit_exceededUsage has exceeded the limit
feature_gatedUser hit a feature gate
payment_retry_requiredPayment failed, retry needed
subscription_renewingSubscription is about to renew
// Trial lifecycle
await sdk.emitTrigger('trial_expiring', {
days_remaining: 2,
});
// Usage limits
await sdk.emitTrigger('usage_limit_approaching', {
entitlement_handle: 'api_calls',
current_usage: 9500,
usage_limit: 10000,
usage_percent: 95,
});
// Feature gating
await sdk.emitTrigger('feature_gated', {
feature: 'advanced_automation',
});

Record interactions with placement decisions directly (useful for headless or custom implementations):

await sdk.trackTreatmentInteraction({
userId: 'user_123',
placementId: 'placement_abc',
interactionType: 'cta_clicked',
treatmentId: 'treatment_xyz',
metadata: { source: 'email_footer' },
});
TypeMeaningEffect
dismissUser closed/dismissed the placementSuppresses for cooldown period
remind_me_laterUser chose to be remindedSuppresses for specified duration
cta_clickedUser clicked the primary CTARecords conversion signal
cta_completedUser finished the CTA flowSuppresses further prompts
suppressProgrammatic suppressionSuppresses immediately

The SDK maintains a local impression history to enforce:

  • Cooldown periods — how long after a dismiss/snooze before showing again
  • Cap policies — maximum impressions per session/day/week/month/lifetime
  • Suppression state — which placements are currently suppressed

This state is persisted to localStorage and survives page reloads.

Inspect suppression state using the headless PlacementController:

const ctrl = session.placement({ surfaceSlot: { id: 'placement_abc' } });
await ctrl.load();
// ctrl.visible reflects suppression, cap limits, and targeting
console.log('Visible:', ctrl.visible);

Events are batched and sent to the RevTurbine API in intervals to minimize network overhead. In local_only mode, events are stored locally but not sent to the server.