Retivo

SDK Reference

JavaScript SDK for event tracking and identity resolution

Installation

npm install @retivo/sdk
# or
pnpm add @retivo/sdk
# or
yarn add @retivo/sdk

The SDK ships as ESM and CJS with full TypeScript types.

Quick Start

import { Retivo } from '@retivo/sdk'

const retivo = new Retivo({ apiKey: 'rt_live_...' })

retivo.identify('user-123', { name: 'Jane', plan: 'pro' })
retivo.track('feature_used', { feature: 'ai-sprint-planner' })

End-to-End Example

A complete working integration that identifies a user, tracks events, and listens for real-time interventions:

import { Retivo } from '@retivo/sdk'

const retivo = new Retivo({
  apiKey: import.meta.env.VITE_RETIVO_API_KEY,
})

// 1. Identify the user after login
retivo.identify('user-123', {
  name: 'Jane Smith',
  email: 'jane@example.com',
  plan: 'pro',
  company: 'Acme Inc',
})

// 2. Track meaningful product events
retivo.track('onboarding_step_completed', { step: 'invite_team' })
retivo.track('feature_used', { feature: 'ai-sprint-planner' })

// 3. Listen for real-time in-app messages
const unsubscribe = retivo.onMessage((message) => {
  showToast({
    title: message.playbookName,
    body: message.body,
  })
})

// On logout or unmount
function cleanup() {
  unsubscribe()
  retivo.reset()
}

Constructor

new Retivo(options: RetevoOptions)
OptionTypeDefaultDescription
apiKeystringrequiredYour API key (rt_live_... or rt_test_...)
baseURLstringhttps://retivo.aiAPI base URL
flushIntervalnumber1000Batch flush interval in milliseconds
maxBatchSizenumber10Max events per batch

Methods

identify(userId, traits?)

Set the current user identity. Must be called before track().

retivo.identify('user-123', {
  name: 'Jane Smith',
  email: 'jane@example.com',
  company: 'Acme Inc',
  plan: 'pro',
  team_size: 8,
})
  • userId — Unique identifier for the user in your system
  • traits — Optional key-value properties stored on the user profile

Calling identify() sends a special $identify event and stores the userId for subsequent track() calls.

track(event, properties?)

Track a user event.

retivo.track('project_created', {
  projectName: 'Q1 Roadmap',
  templateUsed: true,
})
  • event — Event name (processed by Retivo)
  • properties — Optional event properties

Events are batched and flushed automatically. Each event gets an ISO timestamp and idempotency key.

onMessage(handler)

Register a callback for real-time in-app intervention messages via SSE.

const unsubscribe = retivo.onMessage((message) => {
  console.log(message.body)        // "Try our new AI sprint planner!"
  console.log(message.type)        // "in_app"
  console.log(message.playbookName) // "Feature Adoption Nudge"
})

// Later: stop listening
unsubscribe()

The handler receives a WidgetMessage object:

FieldTypeDescription
interventionIdstringUnique intervention ID
typestringMessage type (in_app)
bodystringThe personalized message text
playbookNamestringName of the triggering playbook
timestampstringISO timestamp

reset()

Clear the current user identity, flush pending events, and disconnect SSE. Use this on logout or when switching users.

retivo.reset()
// userId is now null — call identify() again for the new user

setLocale(locale)

Set the user's locale for i18n-aware interventions. Sends a $locale event to Retivo so messages can be localized.

retivo.setLocale('fr-FR')

Must be called after identify(). The locale is included in the user context sent to the LLM during message generation.

debug(enabled?)

Enable or disable debug logging to the browser console. Useful during development.

retivo.debug()       // enable
retivo.debug(false)  // disable

When enabled, all SDK calls (identify, track, reset, setLocale) are logged with their arguments.

getUser()

Returns the current user identity, or null if not identified.

const user = retivo.getUser()
// { userId: 'user-123', traits: { name: 'Jane', plan: 'pro' }, locale: 'en-US' }

if (!user) {
  console.log('No user identified')
}

destroy()

Flush pending events and disconnect SSE.

await retivo.destroy()

Call this on page unload or when the SDK is no longer needed.

Event Naming Conventions

Use consistent, descriptive event names so Retivo can accurately score activation and match playbooks.

Use snake_case for all event names. This keeps events uniform across your codebase and readable in the Retivo dashboard.

Recommended patterns:

PatternExampleWhen to use
feature_usedfeature_usedUser engages with a core product feature
<noun>_<past_verb>project_created, report_exportedUser completes a discrete action
<flow>_step_completedonboarding_step_completedUser progresses through a multi-step flow
<noun>_<state>trial_started, subscription_upgradedLifecycle or billing state changes

Events by Lifecycle Area

Different lifecycle areas rely on different event types. Here are the key events for each area:

AreaKey EventsPurpose
Onboardingonboarding_step_completed, feature_used, invite_sentTrack progress toward first value
Churn Preventionsubscription_cancelled, usage_dropped, support_ticket_createdDetect disengagement signals
Retentionfeature_used, milestone_reached, streak_continuedMeasure ongoing engagement depth
Upsellplan_limit.approaching, feature_gate.hit, usage_threshold_crossedIdentify expansion readiness
Win-backpage_viewed (from returning users), reactivation_startedDetect returning churned users

The feature_gate.hit event is particularly important for upsell detection — track it whenever a user attempts to use a feature they don't have access to on their current plan.

Why this matters: Retivo uses event names for two things:

  1. Activation scoring — events are matched against activation milestones to compute health scores. Inconsistent names (e.g., createProject vs project_created) fragment your signals.
  2. Playbook matching — playbook triggers reference event names directly. A playbook targeting feature_used will not fire on featureUsed.

Avoid generic names like click or action. Include enough context in the event name itself so it is meaningful without inspecting properties.

Common Integration Patterns

SPA Route Tracking

Track page views on client-side route changes. Useful for understanding navigation patterns and drop-off points.

import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'

function useRouteTracking(retivo: Retivo) {
  const location = useLocation()

  useEffect(() => {
    retivo.track('page_viewed', {
      path: location.pathname,
      search: location.search,
    })
  }, [location.pathname])
}

Form Submission Tracking

Capture form completions with relevant metadata. Pair with onboarding_step_completed for multi-step flows.

async function handleFormSubmit(data: FormData) {
  await api.submitOnboardingProfile(data)

  retivo.track('onboarding_step_completed', {
    step: 'profile_setup',
    fields_filled: Object.keys(data).length,
  })
}

Feature Adoption Tracking

Wrap key product features to measure adoption depth. This feeds directly into Retivo's activation scoring.

function trackFeatureUsage(retivo: Retivo, feature: string, metadata?: Record<string, unknown>) {
  retivo.track('feature_used', {
    feature,
    ...metadata,
  })
}

// Usage throughout your app
trackFeatureUsage(retivo, 'ai-sprint-planner', { items_planned: 12 })
trackFeatureUsage(retivo, 'csv-export', { row_count: 340 })
trackFeatureUsage(retivo, 'team-invite', { invitee_count: 3 })

Test Mode

API keys starting with rt_test_ put the SDK into test mode. In test mode:

  • Events are tagged with test: true metadata
  • Interventions are logged but not delivered to real channels
  • All data appears in the dashboard with a test mode indicator
// Development
const retivo = new Retivo({ apiKey: 'rt_test_...' })

// Production
const retivo = new Retivo({ apiKey: 'rt_live_...' })

Use test keys during development and CI to avoid sending real emails or webhooks.

Event Batching

The SDK batches events to minimize HTTP requests:

  • Events queue in memory
  • Flushed when batch reaches maxBatchSize (default: 10)
  • Or when flushInterval elapses (default: 1000ms)
  • Each batch is a single POST /api/track call

This keeps latency under 1 second while preventing excessive API calls.

TypeScript

The SDK is fully typed. Import types directly:

import type { RetevoOptions, TrackEvent, MessageHandler } from '@retivo/sdk'

On this page