The SDK provides a fire-and-forget event tracking system for sending telemetry to the Incode dashboard. This allows you to track module lifecycle, screen transitions, and custom events throughout your verification flow.
Overview
Events are sent automatically by the SDK's built-in modules, but you can also track custom events from your own code. All events are:
- Fire-and-forget: Never blocks execution, never throws errors
- Headless-compatible: Available in
@incodetech/core with zero UI dependencies
- Auto-queued: Events sent before SDK is configured are queued and sent automatically when
setup() is called
Quick Start
import {
addEvent,
moduleOpened,
moduleClosed,
eventModuleNames
} from '@incodetech/core/events';
// Track module lifecycle
useEffect(() => {
moduleOpened(eventModuleNames.phone);
return () => moduleClosed(eventModuleNames.phone);
}, []);
// Track custom events
addEvent({
code: 'customButtonClicked',
module: eventModuleNames.phone,
payload: { buttonId: 'submit' },
});
Event Logging
Subscribe to all events for custom logging or analytics:
import { subscribeEvent } from '@incodetech/core/events';
// Custom logger - separate from API event sending
const unsubscribeLogger = subscribeEvent((event) => {
console.log('[Event]', {
code: event.code,
module: event.module,
screen: event.screen,
payload: event.payload,
timestamp: new Date(event.clientTimestamp ?? Date.now()).toISOString(),
});
});
// Events are logged AND sent to API independently
addEvent({ code: 'test', module: 'PHONE' });
// → Logged to console via listener
// → Sent to API (automatic)
// Remove logger when done
unsubscribeLogger();
API Reference
Core Functions
addEvent(event)
Sends a single event to the dashboard. Fire-and-forget - never blocks or throws.
addEvent({
code: 'captureAttemptFinished',
module: eventModuleNames.id,
screen: eventScreenNames.frontCameraCapture,
payload: { logs: [], attemptNumber: 1 },
clientTimestamp: Date.now(), // Optional, defaults to now
});
Parameters:
| Field |
Type |
Required |
Description |
code |
string |
Yes |
Event code identifier |
module |
EventModule | string |
No |
Module name (use eventModuleNames constants) |
screen |
EventScreen | string |
No |
Screen name (use eventScreenNames constants) |
payload |
Record<string, unknown> |
No |
Additional event data |
clientTimestamp |
number |
No |
Timestamp in milliseconds (defaults to Date.now()) |
subscribeEvent(listener)
Subscribes to all SDK events for logging, debugging, or custom analytics. Returns an unsubscribe function.
const unsubscribe = subscribeEvent((event) => {
console.log('[Event]', event.code, event.module);
// Your custom logic here
});
// Later
unsubscribe();
Parameters:
| Field |
Type |
Required |
Description |
listener |
(event: Event) => void |
Yes |
Callback function that receives each event |
Returns: Unsubscribe function to remove the listener
Note: Subscribers receive events before they're queued or sent to the API. Listener errors are silently caught and don't affect event sending.
Helper Functions
// Module lifecycle
moduleOpened(module, screen?, payload?);
moduleClosed(module, screen?, payload?);
// Screen lifecycle
screenOpened(module, screen, payload?);
screenClosed(module, screen, payload?);
// Generic screen event
screenEvent({ module, screen, code, payload });
Available Constants
Module Names
import { eventModuleNames } from '@incodetech/core/events';
| Constant |
Wire value |
eventModuleNames.selfie |
'SELFIE' |
eventModuleNames.authentication |
'AUTHENTICATION' |
eventModuleNames.authFace |
'AUTH_FACE' |
eventModuleNames.mlConsent |
'ML_CONSENT' |
eventModuleNames.combinedConsent |
'COMBINED_CONSENT' |
eventModuleNames.curpValidation |
'CURP_VALIDATION' |
eventModuleNames.faceMatch |
'FACE_MATCH' |
eventModuleNames.qr |
'QR' |
eventModuleNames.videoSelfie |
'VIDEO_ONBOARDING' |
eventModuleNames.id |
'ID' |
eventModuleNames.front |
'ID' (alias) |
eventModuleNames.back |
'ID' (alias) |
eventModuleNames.passport |
'ID' (alias) |
eventModuleNames.idOcr |
'ID_OCR' |
eventModuleNames.document |
'DOCUMENT_CAPTURE' |
eventModuleNames.creditCard |
'CREDIT_CARD_FRONT' |
eventModuleNames.creditCardBack |
'CREDIT_CARD_BACK' |
eventModuleNames.conference |
'CONFERENCE' |
eventModuleNames.otp |
'OTP' |
eventModuleNames.signature |
'SIGNATURE' |
eventModuleNames.ekyc |
'EXTERNAL_VERIFICATION' |
eventModuleNames.watchlist |
'WATCHLIST' |
eventModuleNames.globalWatchList |
'GLOBAL_WATCHLIST' |
eventModuleNames.customWatchList |
'CUSTOM_WATCHLIST' |
eventModuleNames.watchlistForBusiness |
'WATCHLIST_FOR_BUSINESS' |
eventModuleNames.email |
'EMAIL' |
eventModuleNames.phone |
'PHONE' |
eventModuleNames.instantVerifyEmail |
'INSTANT_VERIFY_EMAIL' |
eventModuleNames.instantVerifyConsent |
'INSTANT_VERIFY_CONSENT' |
eventModuleNames.forms |
'FORMS' |
eventModuleNames.customModule |
'CUSTOM_MODULE' |
eventModuleNames.customFields |
'CUSTOM_FIELDS' |
eventModuleNames.geolocation |
'GEOLOCATION' |
eventModuleNames.ekyb |
'EKYB' |
eventModuleNames.identityReuse |
'IDENTITY_REUSE' |
eventModuleNames.antifraud |
'ANTIFRAUD' |
eventModuleNames.aeSignature |
'AE_SIGNATURE' |
eventModuleNames.qeSignature |
'QE_SIGNATURE' |
eventModuleNames.crossDocumentDataMatch |
'CROSS_DOCUMENT_DATA_MATCH' |
Screen Names
import { eventScreenNames } from '@incodetech/core/events';
Grouped by module for readability.
Selfie / Face Capture
| Constant |
Wire value |
eventScreenNames.faceCaptureTutorial |
'SELFIE_CAPTURE_TUTORIAL' |
eventScreenNames.faceCaptureCamera |
'SELFIE_CAMERA_CAPTURE' |
eventScreenNames.faceCaptureError |
'SELFIE_ATTEMPT_FAILED' |
eventScreenNames.faceCaptureSuccess |
'SELFIE_UPLOAD_SUCCEEDED' |
eventScreenNames.faceCaptureUpload |
'SELFIE_UPLOAD_PROGRESS' |
eventScreenNames.faceMatch |
'FACE_MATCH' |
Auth Face
| Constant |
Wire value |
eventScreenNames.authFace |
'AUTH_FACE' |
eventScreenNames.authFaceTutorial |
'AUTH_FACE_TUTORIAL' |
eventScreenNames.authFaceError |
'AUTH_FACE_ATTEMPT_FAILED' |
eventScreenNames.authFaceUpload |
'AUTH_FACE_UPLOAD_PROGRESS' |
eventScreenNames.authFaceUploadSuccess |
'AUTH_FACE_UPLOAD_SUCCEEDED' |
eventScreenNames.authFaceUploadFailed |
'AUTH_FACE_UPLOAD_FAILED' |
Consent
| Constant |
Wire value |
eventScreenNames.mlConsent |
'MACHINE_LEARNING_CONSENT' |
eventScreenNames.combinedConsent |
'COMBINED_CONSENT' |
CURP
| Constant |
Wire value |
eventScreenNames.curpEnter |
'ENTER_CURP' |
eventScreenNames.curpValidate |
'VALIDATE_CURP' |
eventScreenNames.curpGenerate |
'GENERATE_CURP' |
eventScreenNames.curpValidation |
'CURP_VALIDATION_PROGRESS' |
eventScreenNames.curpValidationFailed |
'CURP_VALIDATION_FAILED' |
eventScreenNames.curpValidationSuccess |
'CURP_VALIDATION_SUCCEEDED' |
QR
| Constant |
Wire value |
eventScreenNames.qrTutorial |
'QR_TUTORIAL' |
eventScreenNames.qrScan |
'QR_SCAN' |
OTP / Signature
| Constant |
Wire value |
eventScreenNames.smsOtp |
'OTP' |
eventScreenNames.simpleOTP |
'OTP' (alias) |
eventScreenNames.signatureInput |
'SIGNATURE_INPUT' |
ID — Front
| Constant |
Wire value |
eventScreenNames.frontTutorial |
'FRONT_ID_CAPTURE_TUTORIAL' |
eventScreenNames.frontCameraCapture |
'FRONT_ID_CAMERA_CAPTURE' |
eventScreenNames.frontHelp |
'FRONT_ID_HELP' |
eventScreenNames.frontReviewPhoto |
'FRONT_ID_REVIEW_PHOTO' |
eventScreenNames.frontUploadProgress |
'FRONT_ID_UPLOAD_PROGRESS' |
eventScreenNames.frontAttemptFailed |
'FRONT_ID_ATTEMPT_FAILED' |
eventScreenNames.frontUploadSuccess |
'FRONT_ID_UPLOAD_SUCCEEDED' |
ID — Back
| Constant |
Wire value |
eventScreenNames.backTutorial |
'BACK_ID_CAPTURE_TUTORIAL' |
eventScreenNames.backCameraCapture |
'BACK_ID_CAMERA_CAPTURE' |
eventScreenNames.backHelp |
'BACK_ID_HELP' |
eventScreenNames.backReviewPhoto |
'BACK_ID_REVIEW_PHOTO' |
eventScreenNames.backUploadProgress |
'BACK_ID_UPLOAD_PROGRESS' |
eventScreenNames.backAttemptFailed |
'BACK_ID_ATTEMPT_FAILED' |
eventScreenNames.backUploadSuccess |
'BACK_ID_UPLOAD_SUCCEEDED' |
Passport
| Constant |
Wire value |
eventScreenNames.passportTutorial |
'TUTORIAL_PASSPORT' |
Document Capture
| Constant |
Wire value |
eventScreenNames.documentTutorial |
'DOCUMENT_CAPTURE_TUTORIAL' |
eventScreenNames.documentCameraCapture |
'DOCUMENT_CAMERA_CAPTURE' |
eventScreenNames.documentHelp |
'DOCUMENT_HELP' |
eventScreenNames.documentReviewPhoto |
'DOCUMENT_REVIEW_PHOTO' |
eventScreenNames.documentUploadProgress |
'DOCUMENT_UPLOAD_IN_PROGRESS' |
eventScreenNames.documentAttemptFailed |
'DOCUMENT_ATTEMPT_FAILED' |
eventScreenNames.documentUploadSuccess |
'DOCUMENT_UPLOAD_SUCCEEDED' |
Digital ID
| Constant |
Wire value |
eventScreenNames.digitalIdFileSelection |
'DIGITAL_ID_FILE_SELECTION' |
eventScreenNames.digitalIdFileReview |
'DIGITAL_ID_FILE_REVIEW' |
eventScreenNames.digitalIdUploadProgress |
'DIGITAL_ID_UPLOAD_PROGRESS' |
eventScreenNames.digitalIdUploadSuccess |
'DIGITAL_ID_UPLOAD_SUCCEEDED' |
eventScreenNames.digitalIdUploadFailed |
'DIGITAL_ID_UPLOAD_FAILED' |
eventScreenNames.digitalIdAnalysisProgress |
'DIGITAL_ID_ANALYSIS_PROGRESS' |
eventScreenNames.digitalIdVerificationSuccess |
'DIGITAL_ID_VERIFICATION_SUCCESS' |
eventScreenNames.digitalIdVerificationFailed |
'DIGITAL_ID_VERIFICATION_FAILED' |
Conference
| Constant |
Wire value |
eventScreenNames.conferenceWait |
'CONFERENCE_WAIT' |
eventScreenNames.conferenceVideoChat |
'CONFERENCE_VIDEO_CHAT' |
eventScreenNames.conferenceMessageChat |
'CONFERENCE_MESSAGE_CHAT' |
Video Selfie
| Constant |
Wire value |
eventScreenNames.videoSelfieTutorial |
'VIDEO_SELFIE_TUTORIAL' |
eventScreenNames.videoSelfie |
'VIDEO_SELFIE' |
eventScreenNames.videoSelfieFaceCapture |
'VIDEO_SELFIE_FACE_CAPTURE' |
eventScreenNames.videoSelfieFaceUploadProgress |
'VIDEO_SELFIE_FACE_UPLOAD_PROGRESS' |
eventScreenNames.videoSelfieFaceAttemptFailed |
'VIDEO_SELFIE_FACE_ATTEMPT_FAILED' |
eventScreenNames.videoSelfieFaceUploadSucceeded |
'VIDEO_SELFIE_FACE_UPLOAD_SUCCEEDED' |
eventScreenNames.videoSelfieFrontIdCapture |
'VIDEO_SELFIE_FRONT_ID_CAPTURE' |
eventScreenNames.videoSelfieFrontIdUploadProgress |
'VIDEO_SELFIE_FRONT_ID_UPLOAD_PROGRESS' |
eventScreenNames.videoSelfieFrontIdAttemptFailed |
'VIDEO_SELFIE_FRONT_ID_ATTEMPT_FAILED' |
eventScreenNames.videoSelfieFrontIdUploadSucceeded |
'VIDEO_SELFIE_FRONT_ID_UPLOAD_SUCCEEDED' |
eventScreenNames.videoSelfieBackIdCapture |
'VIDEO_SELFIE_BACK_ID_CAPTURE' |
eventScreenNames.videoSelfieBackIdUploadProgress |
'VIDEO_SELFIE_BACK_ID_UPLOAD_PROGRESS' |
eventScreenNames.videoSelfieBackIdAttemptFailed |
'VIDEO_SELFIE_BACK_ID_ATTEMPT_FAILED' |
eventScreenNames.videoSelfieBackIdUploadSucceeded |
'VIDEO_SELFIE_BACK_ID_UPLOAD_SUCCEEDED' |
eventScreenNames.videoSelfieDocumentCapture |
'VIDEO_SELFIE_DOCUMENT_CAPTURE' |
eventScreenNames.videoSelfieVoiceQuestion |
'VIDEO_SELFIE_VOICE_QUESTION' |
eventScreenNames.videoSelfieVoiceFinalQuestion |
'VIDEO_SELFIE_VOICE_FINAL_QUESTION' |
eventScreenNames.videoSelfieVideoUpload |
'VIDEO SELFIE VIDEO UPLOAD' |
| Constant |
Wire value |
eventScreenNames.ekycInput |
'EKYC_INPUT' |
eventScreenNames.ekycProgress |
'EKYC_PROGRESS' |
eventScreenNames.ekycSucceeded |
'EKYC_SUCCEEDED' |
eventScreenNames.ekycFailed |
'EKYC_FAILED' |
eventScreenNames.ekybForm |
'EKYB_FORM' |
eventScreenNames.forms |
'FORMS' |
Watchlists
| Constant |
Wire value |
eventScreenNames.globalWatchListInput |
'GLOBAL_WATCHLIST_INPUT' |
eventScreenNames.globalWatchListProgress |
'GLOBAL_WATCHLIST_PROGRESS' |
eventScreenNames.globalWatchListSuccess |
'GLOBAL_WATCHLIST_SUCCEEDED' |
eventScreenNames.globalWatchListFailed |
'GLOBAL_WATCHLIST_FAILED' |
eventScreenNames.customWatchListInput |
'CUSTOM_WATCHLIST_INPUT' |
eventScreenNames.customWatchListProgress |
'CUSTOM_WATCHLIST_PROGRESS' |
eventScreenNames.customWatchListSuccess |
'CUSTOM_WATCHLIST_SUCCEEDED' |
eventScreenNames.customWatchListFailed |
'CUSTOM_WATCHLIST_FAILED' |
Phone / Email / Instant Verify
| Constant |
Wire value |
eventScreenNames.phoneInput |
'PHONE_INPUT' |
eventScreenNames.emailInput |
'EMAIL_INPUT' |
eventScreenNames.instantVerify |
'INSTANT_VERIFY' |
Custom Module
| Constant |
Wire value |
eventScreenNames.customModuleCallback |
'CUSTOM_MODULE_CALLBACK' |
eventScreenNames.customModuleProcessing |
'CUSTOM_MODULE_PROCESSING' |
Video Selfie Events
import { videoSelfieEvents } from '@incodetech/core/events';
| Constant |
Wire value |
videoSelfieEvents.imageTooBlurry |
'imageTooBlurry' |
videoSelfieEvents.fillFrame |
'fillFrame' |
videoSelfieEvents.checkCameraOrLighting |
'checkCameraOrLighting' |
videoSelfieEvents.frontIdCaptureStarted |
'frontIdCaptureStarted' |
videoSelfieEvents.lookAtCamera |
'lookAtCamera' |
videoSelfieEvents.moveCloser |
'moveCloser' |
videoSelfieEvents.lookingForFrontId |
'lookingForFrontId' |
videoSelfieEvents.lookingForBackId |
'lookingForBackId' |
videoSelfieEvents.cameraSwitchToBack |
'cameraSwitchToBack' |
videoSelfieEvents.cameraSwitchToFront |
'cameraSwitchToFront' |
videoSelfieEvents.audioStreamOpened |
'audioStreamOpened' |
videoSelfieEvents.audioStreamClosed |
'audioStreamClosed' |
videoSelfieEvents.videoSelfieVideoUploadInProgress |
'videoSelfieVideoUploadInProgress' |
videoSelfieEvents.videoSelfieTosNotAccepted |
'videoSelfieTosNotAccepted' |
videoSelfieEvents.videoSelfieTosAccepted |
'videoSelfieTosAccepted' |
videoSelfieEvents.videoSelfieStreamCreated |
'videoSelfieStreamCreated' |
videoSelfieEvents.videoSelfieStreamDestroyed |
'videoSelfieStreamDestroyed' |
videoSelfieEvents.videoSelfieReconnecting |
'videoSelfieReconnecting' |
videoSelfieEvents.videoSelfieReconnected |
'videoSelfieReconnected' |
Event Queue
Events sent before the SDK is configured (before setup() is called with a token) are automatically queued. When setup() is called with a token, all queued events are automatically flushed and sent.
// This event will be queued
addEvent({ code: 'sdkLoading', payload: { timestamp: Date.now() } });
// Later, after setup with token
await setup({ apiURL: '...', token: 'session-token' });
// ^ Queued events are automatically sent here
Common Event Codes
The SDK automatically sends these events from built-in modules:
| Code |
Description |
When Sent |
moduleOpened |
Module started |
When module component mounts |
moduleClosed |
Module ended |
When module component unmounts |
screenOpened |
Screen displayed |
When screen component mounts |
screenClosed |
Screen hidden |
When screen component unmounts |
continue |
User continued |
When user clicks continue/submit |
tutorialSelfie |
Selfie tutorial shown |
When selfie tutorial displays |
tutorialVideoStarted |
ID tutorial video started |
When ID tutorial video plays |
captureAttemptFinished |
Capture attempt completed |
After capture upload completes |
strSessionDidConnect |
Recording session connected |
When video recording starts |
strStreamVideoCaptureStart |
Video capture started |
When video recording begins |
Examples
import { addEvent, eventModuleNames } from '@incodetech/core/events';
function handleSubmit() {
addEvent({
code: 'customSubmitClicked',
module: eventModuleNames.phone,
payload: { timestamp: Date.now() },
});
// Your submit logic...
}
Track Screen Transition
import { screenEvent, eventModuleNames, eventScreenNames } from '@incodetech/core/events';
function navigateToTutorial() {
screenEvent({
module: eventModuleNames.id,
screen: eventScreenNames.frontTutorial,
code: 'screenOpened',
});
// Navigate...
}
Track Module Lifecycle in Headless Mode
import { moduleOpened, moduleClosed, eventModuleNames } from '@incodetech/core/events';
function MyCustomPhoneFlow() {
useEffect(() => {
moduleOpened(eventModuleNames.phone);
return () => {
moduleClosed(eventModuleNames.phone);
};
}, []);
// Your custom implementation...
}
Best Practices
- Use constants - Always use
eventModuleNames and eventScreenNames instead of hardcoded strings
- Fire-and-forget - Don't await
addEvent() - it's designed to never block
- Use hooks for lifecycle - Use
useModuleEvents/useScreenEvents for automatic tracking
- Include context - Add relevant data in
payload for debugging
- Don't track sensitive data - Never include PII or sensitive information in event payloads
- Use subscribers for custom logging - Use
subscribeEvent() for custom analytics or logging needs
- Keep listeners lightweight - Event listeners are called synchronously; avoid heavy operations
See Also