Analytics
Track form behavior without coupling metrics to rendering.
Analytics callbacks report start, field, page, completion, reset, and abandon events while your form stays a normal React component.
Configuration
Analytics is a callback object passed to useFormedible. Current events cover form start, field focus, field blur, field change, field complete, field error, page change, form complete, abandon, and reset.
- Field callback names use Extract<keyof TFormValues, string> | string, so nested paths are allowed.
- Runtime timestamps come from Date.now; blur time is the blur timestamp minus the stored focus timestamp.
- Page completion, tab analytics, and performance callbacks are typed as never and are not emitted.
| Property | Type | Default | Description |
|---|---|---|---|
onFormStart | (timestamp: number) => void | undefined | Runs once from the analytics hook mount effect. |
onFieldFocus | (fieldName: Extract<keyof TFormValues, string> | string, timestamp: number) => void | undefined | Runs when a field receives focus. |
onFieldBlur | (fieldName: Extract<keyof TFormValues, string> | string, timeSpent: number) => void | undefined | Runs on blur with elapsed focus time. |
onFieldChange | (fieldName: Extract<keyof TFormValues, string> | string, value: unknown, timestamp: number) => void | undefined | Runs after a field change with the new field value. |
onFieldComplete | (fieldName: Extract<keyof TFormValues, string> | string, isValid: boolean, timeSpent: number) => void | undefined | Runs after blur with the latest validity flag and elapsed focus time. |
onFieldError | (fieldName: Extract<keyof TFormValues, string> | string, errors: readonly string[], timestamp: number) => void | undefined | Runs when blur receives field errors, or when the standalone tracker records errors. |
onPageChange | (fromPage: number, toPage: number, timeSpent: number, pageValidationState?: { readonly hasErrors: boolean; readonly completionPercentage: number }) => void | undefined | Runs after page movement with timing and validation state for the page being left. |
onFormComplete | (timeSpent: number, formData: TFormValues) => void | undefined | Runs after Formedible tracks a successful submit. |
onFormAbandon | (completionPercentage: number, context?: { readonly currentPage?: number; readonly currentTab?: string; readonly lastActiveField?: string }) => void | undefined | Runs from cleanup if the form unmounts before completion. |
onFormReset | (timestamp: number, reason?: string) => void | undefined | Runs when reset tracking is called. The built-in reset path passes the reset reason when supplied. |
Field events
Field tracking is wired through the FieldRenderer controller from useFormedible. Focus stores time, change reports the next value, and blur reports elapsed focus time plus validity.
- trackFieldFocus stores lastActiveField and focusedAt[fieldName], then calls onFieldFocus.
- trackFieldChange calls onFieldChange with fieldName, value, and Date.now().
- trackFieldBlur calls onFieldBlur, optional onFieldError, then onFieldComplete, and removes the stored focus timestamp.
- getFieldBlurTime returns 0 when blur occurs without a stored focus timestamp.
Page and form events
Page changes start in useMultiPage. useFormedible passes the page context to analytics.trackPageChange and the public onPageChange option.
- useMultiPage measures timeSpent as Date.now() minus pageStartedAt before it changes the page.
- analytics.trackPageChange includes hasErrors and completionPercentage for the page being left.
- trackFormComplete sets completedRef before onFormComplete, so abandon does not fire after a completed submit.
- The built-in reset path passes reason "reset" to trackFormReset.
Abandonment tracking
Abandonment runs in the analytics hook cleanup. It is skipped after trackFormComplete, so unmounting an incomplete form calls onFormAbandon when you provide it.
- useFormedible calculates completionPercentage from completed fields divided by total fields.
- currentPage is always included; currentTab is included when tab state is active.
- lastActiveField comes from getAbandonContext or the focus tracker fallback.
- When no getAbandonContext is supplied, the analytics hook falls back to completionPercentage: 0.
Standalone factory
createFormAnalyticsTracker is exported from use-form-analytics.ts for code outside React. It takes the same analytics config plus an optional clock.
- options.now defaults to Date.now.
- trackFieldChange and trackFieldError include a current timestamp from the configured clock.
- trackFieldComplete forwards isValid and timeSpent without React focus state.
- trackFormReset forwards an optional reason string.
| Property | Type | Default | Description |
|---|---|---|---|
trackFieldChange | (fieldName: Extract<keyof TFormValues, string> | string, value: unknown) => void | Returned | Calls onFieldChange with the current clock value. |
trackFieldComplete | (fieldName: Extract<keyof TFormValues, string> | string, isValid: boolean, timeSpent: number) => void | Returned | Calls onFieldComplete without React focus state. |
trackFieldError | (fieldName: Extract<keyof TFormValues, string> | string, errors: readonly string[]) => void | Returned | Calls onFieldError with the current clock value. |
trackFormReset | (reason?: string) => void | Returned | Calls onFormReset with the current clock value and optional reason. |