Track user behavior, measure form performance, and gain insights into how users interact with your forms using Formedible's comprehensive analytics system.
Comprehensive analytics that track user interactions and form performance.
Formedible provides built-in analytics that track various user interactions and form events. All analytics are optional and can be customized to fit your specific tracking needs.
Track focus, blur, and change events for individual fields with timing data.
Monitor form start, completion, and abandonment with completion percentages.
Track page changes in multi-step forms with time spent and completion context.
Monitor form rendering and submission performance with detailed timing data.
All events include rich metadata like validation errors and completion states.
Enable analytics by adding an analytics configuration with event handlers.
Enable analytics by adding an analytics
configuration with event handlers:
const { Form } = useFormedible({fields: [{ name: 'email', type: 'email', label: 'Email' },{ name: 'name', type: 'text', label: 'Name' },],analytics: {onFormStart: (timestamp) => {console.log('Form started at:', new Date(timestamp));},onFieldFocus: (fieldName, timestamp) => {console.log(`Field ${fieldName} focused at:`, new Date(timestamp));},onFieldBlur: (fieldName, timeSpent) => {console.log(`User spent ${timeSpent}ms on ${fieldName}`);},onFormComplete: (timeSpent, formData) => {console.log(`Form completed in ${timeSpent}ms`, formData);}}});
Complete reference of all analytics events available in Formedible.
analytics: {// Form lifecycle eventsonFormStart: (timestamp: number) => {// Called when form is first renderedanalytics.track('form_started', { timestamp });},onFormComplete: (timeSpent: number, formData: any) => {// Called when form is successfully submittedanalytics.track('form_completed', {duration: timeSpent,data: formData});},onFormAbandon: (completionPercentage: number, context?: any) => {// FIXED: Only fires on actual page leave, not form navigation// Called when user leaves without completinganalytics.track('form_abandoned', {completion: completionPercentage,currentPage: context?.currentPage,currentTab: context?.currentTab,lastActiveField: context?.lastActiveField});},// Field interaction eventsonFieldFocus: (fieldName: string, timestamp: number) => {// Called when a field receives focusanalytics.track('field_focused', {field: fieldName,timestamp});},onFieldBlur: (fieldName: string, timeSpent: number) => {// Called when a field loses focusanalytics.track('field_blurred', {field: fieldName,duration: timeSpent});},onFieldChange: (fieldName: string, value: any, timestamp: number) => {// Called when field value changesanalytics.track('field_changed', {field: fieldName,value,timestamp});},onFieldError: (fieldName: string, errors: string[], timestamp: number) => {// Called when field validation errors occuranalytics.track('field_error', {field: fieldName,errorCount: errors.length,firstError: errors[0],timestamp});},onFieldComplete: (fieldName: string, isValid: boolean, timeSpent: number) => {// Called when field is successfully completedanalytics.track('field_complete', {field: fieldName,isValid,timeSpent});},// Multi-page form eventsonPageChange: (fromPage: number, toPage: number, timeSpent: number, pageContext?: any) => {// Called when navigating between pages with rich contextanalytics.track('page_changed', {from: fromPage,to: toPage,duration: timeSpent,hasErrors: pageContext?.hasErrors,completionPercentage: pageContext?.completionPercentage});},// Tab-based form eventsonTabChange: (fromTab: string, toTab: string, timeSpent: number, tabContext?: any) => {// Called when navigating between tabsanalytics.track('tab_changed', {fromTab,toTab,duration: timeSpent,completionPercentage: tabContext?.completionPercentage,hasErrors: tabContext?.hasErrors});},onTabFirstVisit: (tabId: string, timestamp: number) => {// Called when a tab is visited for the first timeanalytics.track('tab_first_visit', {tabId,timestamp});},// Performance trackingonSubmissionPerformance: (totalTime: number, validationTime: number, processingTime: number) => {// Called after form submission to track performanceanalytics.track('form_performance', {totalTime,validationTime,processingTime,efficiency: (processingTime / totalTime) * 100});}}
Real-world examples of integrating with popular analytics services.
analytics: {onFormStart: (timestamp) => {gtag('event', 'form_start', {form_name: 'contact_form',timestamp: timestamp});},onFormComplete: (timeSpent, formData) => {gtag('event', 'form_submit', {form_name: 'contact_form',engagement_time_msec: timeSpent,value: 1});},onFormAbandon: (completionPercentage) => {gtag('event', 'form_abandon', {form_name: 'contact_form',completion_percentage: completionPercentage});}}
// Custom analytics serviceclass FormAnalytics {static track(event: string, data: any) {fetch('/api/analytics', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ event, data, timestamp: Date.now() })});}}// Usage in formanalytics: {onFieldFocus: (fieldName, timestamp) => {FormAnalytics.track('field_focus', {field: fieldName,timestamp});},onFieldBlur: (fieldName, timeSpent) => {FormAnalytics.track('field_blur', {field: fieldName,time_spent: timeSpent});}}
import mixpanel from 'mixpanel-browser';analytics: {onFormStart: (timestamp) => {mixpanel.track('Form Started', {form_id: 'registration_form',timestamp: timestamp});},onFieldChange: (fieldName, value, timestamp) => {mixpanel.track('Field Changed', {field_name: fieldName,field_value: typeof value === 'string' ? value.length : value,timestamp: timestamp});},onPageChange: (fromPage, toPage, timeSpent) => {mixpanel.track('Page Changed', {from_page: fromPage,to_page: toPage,time_on_page: timeSpent});}}
Use analytics data to calculate important form performance metrics.
// Example metrics calculationclass FormMetrics {private startTime: number = 0;private fieldTimes: Record<string, number> = {};analytics = {onFormStart: (timestamp: number) => {this.startTime = timestamp;},onFieldBlur: (fieldName: string, timeSpent: number) => {this.fieldTimes[fieldName] = timeSpent;// Calculate average time per fieldconst avgTime = Object.values(this.fieldTimes).reduce((sum, time) => sum + time, 0) / Object.keys(this.fieldTimes).length;console.log(`Average time per field: ${avgTime}ms`);},onFormComplete: (timeSpent: number, formData: any) => {const completionRate = this.calculateCompletionRate();const fieldsCompleted = Object.keys(formData).length;console.log('Form Metrics:', {totalTime: timeSpent,completionRate,fieldsCompleted,avgTimePerField: timeSpent / fieldsCompleted});}};private calculateCompletionRate(): number {// Implementation depends on your tracking systemreturn 0.85; // 85% completion rate}}
Latest enhancements to the analytics system for better insights.
The onFormAbandon
event now only fires when users actually leave the page, not when navigating between form pages or tabs. This provides accurate abandonment metrics.
All analytics events now include rich contextual information like validation errors, completion percentages, and performance metrics for better insights.
New performance metrics track form rendering, validation, and submission times to help optimize user experience.
Important privacy guidelines when implementing form analytics.
Be careful not to track sensitive field values. Consider tracking field interactions without actual values.
Ensure you have proper user consent before tracking form interactions, especially in GDPR regions.
Consider anonymizing or hashing user data before sending to analytics services.
Guidelines for effective form analytics implementation.
Only implement the analytics events you actually need to avoid data overload.
Wrap analytics calls in try-catch blocks to prevent tracking errors from breaking your form.
Use debouncing for high-frequency events like field changes to avoid overwhelming your analytics service.