Overview
event() records a single behavioral event. Events are the primary signal ChurnKit uses to calculate churn risk — frequent, diverse events indicate healthy engagement, while gaps or negative events (e.g. support tickets) raise risk scores.
Signature
churn . event (
userId : string ,
event : string ,
properties ?: EventProperties ,
options ?: CallOptions
): Promise < { ok : boolean } >
Parameters
The user who performed the action.
Event name — use snake_case by convention. Must be non-empty.
Optional key-value metadata. Values must be string | number | boolean | null.
Cancel the request via an AbortSignal.
What events to track
Track events that signal engagement or disengagement :
Positive signals
Negative signals
Session events
// Core feature usage — strongest retention signal
await churn . event ( 'user_123' , 'feature_used' , { feature: 'analytics_dashboard' })
await churn . event ( 'user_123' , 'report_exported' )
await churn . event ( 'user_123' , 'team_member_invited' )
await churn . event ( 'user_123' , 'api_called' )
await churn . event ( 'user_123' , 'integration_connected' , { provider: 'slack' })
Examples
Simple event
await churn . event ( 'user_123' , 'dashboard_viewed' )
Event with properties
await churn . event ( 'user_123' , 'feature_used' , {
feature: 'csv_export' ,
rows_exported: 1500 ,
format: 'csv' ,
})
In a Next.js Route Handler
import { churn } from '@/lib/churnkit'
export async function POST ( req : Request ) {
const { userId , feature } = await req . json ()
await churn . event ( userId , 'feature_used' , { feature })
return Response . json ({ ok: true })
}
Fire and forget (non-blocking)
// Don't await if you don't need to block the response
void churn . event ( userId , 'page_viewed' , { path: '/settings' })
Return value
Errors
Code When VALIDATION_ERRORuserId or event is emptyUNAUTHORIZEDAPI key is invalid RATE_LIMITEDToo many requests — back off and retry TIMEOUTRequest exceeded timeout
For high-throughput scenarios (e.g. tracking every API call), use the EventBatcher instead of calling event() individually.