Skip to main content
Outlit tracks two independent dimensions of your customer relationships: contact journey (how engaged each person is with your product) and account billing (whether their company pays you). These are separate because a contact can be highly engaged while their company hasn’t paid yet, or a company can be paying while a specific team member is inactive.

How does Outlit model the customer journey?

Outlit tracks contacts and accounts separately:

Contact Journey (per person)

Account Billing (per company)


What are the contact journey stages?

Each person (contact) progresses through stages based on their product engagement:
StageMeaningHow It’s Set
DiscoveredEmail known, hasn’t signed up yetAutomatic
Signed UpCreated an accountAutomatic
ActivatedCompleted onboarding or key milestoneCall user.activate()
EngagedActively using the productAutomatic or user.engaged()
InactiveNo activity for extended periodAutomatic
Contact stages track product engagement, not billing. A contact can be Engaged even if their company hasn’t paid, or Inactive even if their company is actively paying.

How stages progress

Contacts move forward through Discovered, Signed Up, Activated, and Engaged. They can never move backwards—an Engaged contact can’t become Activated again. The one exception is Inactive: contacts automatically return to Engaged when they have new activity.

How does Outlit detect stages automatically?

Discovered vs Signed Up

The difference is determined by the identifiers you provide:
When you identify a visitor with only an email (no userId), they’re marked as Discovered:
outlit.identify({
  email: 'jane@example.com',
  traits: { source: 'newsletter' }
})
Typical triggers: newsletter signup, contact form submission, lead magnet download.
If a Discovered contact later provides a userId (e.g., they sign up after submitting a lead form), they automatically advance to Signed Up.

Automatic engagement and inactivity

Outlit monitors user activity and automatically advances contacts to Engaged when they show consistent usage—active on multiple distinct days within a rolling time window. When contacts haven’t had any product activity for an extended period (default: 30 days), they’re marked Inactive. When an inactive contact returns, they automatically recover to Engaged.

How do I manually set contact stages?

These examples show browser SDK usage where the user is already identified. For server-side usage, see Node.js SDK → Contact Stage Methods.

user.activate()

Mark a contact as activated after they complete onboarding:
outlit.user.activate({
  flow: 'onboarding',
  completedSteps: ['profile', 'first_action', 'invite_team']
})
Call this when users complete your onboarding flow, perform a key “aha moment” action, or reach your definition of activation.

user.engaged()

While engagement is calculated automatically, you can explicitly mark it for specific milestones:
outlit.user.engaged({
  milestone: 'power_user',
  actionsThisWeek: 50
})

What are the account billing statuses?

Each account (company) has a billing status that’s separate from individual contact journeys:
StatusMeaningHow It’s Set
NoneNever had a subscriptionDefault
TrialingActive trial periodAutomatic (Stripe) or manual
PayingActive paid subscriptionAutomatic (Stripe) or manual
ChurnedHad subscription, now cancelledAutomatic (Stripe) or manual

How does Stripe integration work?

If you’ve connected Stripe to Outlit, billing status is handled automatically:
Stripe Subscription StatusAccount Billing Status
trialingTrialing
activePaying
canceledChurned
unpaidChurned
When a subscription status changes in Stripe, Outlit automatically updates the account’s billing status. Individual contact journey stages are not affected.
Stripe integration links accounts via email matching. When Outlit syncs a Stripe customer, it finds the matching account and updates its billing status.

How do I set billing status manually?

For non-Stripe payment processors or custom billing logic:
// When a trial starts
outlit.customer.trialing({ domain: 'acme.com', trialEndsAt: '2024-02-15' })

// When payment succeeds
outlit.customer.paid({ domain: 'acme.com', plan: 'pro', amount: 99 })

// When subscription is cancelled
outlit.customer.churned({ domain: 'acme.com', reason: 'too_expensive' })
Billing methods target the account by domain, not individual contacts. All contacts under that account share the same billing status.

Best practices

Let automatic detection work. Don’t over-instrument. Outlit handles most stage transitions automatically—Discovered and Signed Up are determined by identifiers, engagement and inactivity are calculated from activity, and Stripe handles billing status. Understand the separation. Contact journey and account billing are independent. Jane can be Engaged while her company is on None, or Inactive while her company is Paying. When Jane returns after being Inactive, she auto-recovers to Engaged regardless of billing status. Call stage methods at the right time. Stage methods like user.activate() should be called when the action is confirmed complete, not when the user clicks a button. Wait for the backend to confirm success before tracking. Include useful properties. Properties help you analyze stage transitions. Include context like which onboarding flow was completed, time-to-activate, and which steps were skipped.

Next Steps