Track the ID and Face Validation journey
The onJourneyEvent callback reports structured progress from the
IdAndFaceValidation flow. Use it to answer
questions such as:
- Did the user reach ID capture or face liveness?
- Which documents did the user capture?
- Did the user retry a capture?
- Which stages did the user complete?
- Did the user explicitly exit, and from where?
Journey events contain progress metadata only. They never contain captured images, document contents, submission requests, or validation responses.
Add the callback
React
import {
IdAndFaceValidation,
type IdAndFaceValidationJourneyEvent,
} from "idmission-web-sdk";
function reportJourneyEvent(event: IdAndFaceValidationJourneyEvent) {
analytics.track(event.name, event);
}
export default function App() {
return (
<IdAndFaceValidation
sessionId={getSessionId}
onJourneyEvent={reportJourneyEvent}
onApproved={handleApproved}
onDenied={handleDenied}
/>
);
}Every event has the same envelope:
type IdAndFaceValidationJourneyEventEnvelope = {
version: 1;
flow: "id-and-face-validation";
timestamp: string; // ISO 8601 UTC timestamp
name: string;
[eventSpecificField: string]: unknown;
};Use your own journey or analytics identifier to correlate events from a mounted
flow instance. The flow field identifies the SDK flow type; it is not a unique
instance ID.
Event reference
| Event | Additional fields | When it is emitted |
|---|---|---|
flow.started | None | Once, when the mounted flow begins reporting events. This is always the first journey event. |
stage.started | stage | When a stage becomes current, including its loading or introduction screen. |
document.captured | stage: 'id-capture', documentType | When a document captured through the wizard is stored. Camera capture, fallback capture, and file upload are all included. |
selfie.captured | stage | When a selfie is accepted in face liveness or video signature capture. |
capture.retried | stage, optional attempt | When the user chooses to retry a supported capture. attempt is included when the stage can supply it. |
stage.completed | stage | After a stage succeeds or is accepted and before the SDK advances to the next stage. |
flow.exited | reason, optional stage | When the user takes an SDK-provided explicit exit action. stage is included when the SDK knows it. |
Stages
| Value | Meaning |
|---|---|
id-capture | Capture of the primary ID document. |
face-liveness | Selfie and realness check. |
signature-capture | On-screen signature capture, when enabled. |
video-signature-capture | Recorded selfie/signature capture, when enabled. |
additional-document-capture | Additional document collection, when configured. |
Document types
document.captured reports one of idCardFront, idCardBack, passport, or
singlePage. Additional-document collection is represented by its stage events;
it does not emit document.captured for each additional document.
Exit reasons
| Value | Meaning |
|---|---|
capture-exit | The user selected the exit control during ID, face, or video signature capture. |
failure-exit | The user exited from the face-liveness failure experience. |
user-cancel | The user selected the cancel control on a loading or introduction screen. |
tamper-exit | The user exited from the tamper-detection screen. The stage may be unknown. |
Journey telemetry does not add or change exit controls. For example,
onUserCancel must still be supplied for the cancel control to be shown, and
onExitAfterTamperSealPopped must be supplied for the tamper-screen exit control
to be shown. Continue to use those callbacks to navigate away or unmount the
flow. A flow.exited event reports the action but does not close the flow by
itself.
Example sequence
A typical ID-card and face-liveness journey produces events in this order:
flow.started
stage.started stage=id-capture
document.captured stage=id-capture documentType=idCardFront
document.captured stage=id-capture documentType=idCardBack
stage.completed stage=id-capture
stage.started stage=face-liveness
selfie.captured stage=face-liveness
stage.completed stage=face-livenessConfigured optional stages appear in the same stage.started /
stage.completed sequence. If an asynchronous captureSignature or
captureSignatureVideo condition skips its stage, that stage still reports
stage.started followed by stage.completed; there is no separate
stage.skipped event.
The exact sequence depends on the flow configuration and user actions. For
example, a passport journey emits one document.captured event with
documentType: 'passport', and a retry can insert capture.retried before the
next capture event.
Handle event variants safely
The exported TypeScript event type is a discriminated union, so checking
event.name narrows the event-specific fields:
import type { IdAndFaceValidationJourneyEvent } from "idmission-web-sdk";
function reportJourneyEvent(event: IdAndFaceValidationJourneyEvent) {
switch (event.name) {
case "document.captured":
analytics.track("identity_document_captured", {
documentType: event.documentType,
occurredAt: event.timestamp,
});
break;
case "capture.retried":
analytics.track("identity_capture_retried", {
stage: event.stage,
attempt: event.attempt,
occurredAt: event.timestamp,
});
break;
case "flow.exited":
analytics.track("identity_flow_exited", {
stage: event.stage,
reason: event.reason,
occurredAt: event.timestamp,
});
break;
default:
analytics.track(event.name, event);
}
}Treat attempt and the exit event’s stage as optional. Currently, face
liveness retries provide an attempt number; ID and video signature retries do
not.
Journey progress versus final outcomes
onJourneyEvent describes what the user did inside the capture experience. It
does not report the final validation decision and there is no flow.completed
journey event. Keep the existing completion callbacks for business outcomes:
| What you need to observe | Callback |
|---|---|
| User progress, capture milestones, retries, and exits | onJourneyEvent |
| Completed SDK-managed submission only | onComplete |
| Approved validation | onApproved |
| Denied validation | onDenied |
| Submission failure | onRequestFailure |
| Upload lifecycle and progress | onBeforeDocumentUpload, onDocumentUploadProgress, onDocumentUploaded, onDocumentUploadFailed |
Combining these callbacks gives you journey telemetry without treating a completed capture stage as a successful validation.
Delivery behavior
Events are delivered synchronously and in causal order. The SDK does not wait for a returned promise. If the callback throws, the SDK logs the error and continues the capture journey.
Keep the handler fast. Enqueue or batch network work instead of blocking it, and handle delivery retries in your analytics client. The SDK does not buffer or replay events if the browser closes or the network is unavailable.
const pendingEvents: IdAndFaceValidationJourneyEvent[] = [];
function reportJourneyEvent(event: IdAndFaceValidationJourneyEvent) {
pendingEvents.push(event);
scheduleAnalyticsFlush();
}Precapture and abandonment behavior
- Documents supplied through
precapturedDocumentsdo not emitdocument.captured. A later recapture of the same document type does. - A precaptured selfie can bypass face liveness and does not emit
selfie.captured. - Closing the tab, refreshing, losing power, or navigating away outside an SDK
exit control does not emit
flow.exited. If abandonment telemetry is required, add host-page lifecycle tracking such aspagehideand usenavigator.sendBeaconwhere appropriate.
Privacy guidance
Journey events are intentionally image-free, but they still describe identity verification activity. Send only the fields your telemetry system needs, use a customer-controlled correlation ID instead of personal data, and apply your organization’s retention, consent, and access-control policies.