6 min read · Updated May 2025

Field-Level Onboarding Analytics in React Native

React Native onboarding analytics usually stops at completion rate. That number tells you something went wrong, but it does not tell you what, where, or why.

Field-level analytics tells you exactly which input creates friction.

The problem with screen-level tracking

Screen 1 completion: 94%
Screen 2 completion: 71%
Screen 3 completion: 43%

You know screen 3 has a problem. You do not know which of the 4 inputs on screen 3 causes 57% of users to quit.

What field-level analytics looks like

Screen 3 - Profile Setup

  inp_name        98% completion    avg 8 seconds
  inp_email       96% completion    avg 6 seconds
  inp_phone       61% completion    avg 34 seconds  <- problem
  inp_role        89% completion    avg 12 seconds

Screen 3 overall: 59% completion
Drop-off cause:   inp_phone
Fix:              International format hint, country picker
Result:           +22% screen completion after fix

The four events you need to track

track('field_started', {
  flowId: 'flow_abc',
  screenId: 'screen_profile',
  fieldId: 'inp_phone',
  userId: 'usr_123',
  timestamp: Date.now(),
})

track('field_completed', {
  flowId: 'flow_abc',
  screenId: 'screen_profile',
  fieldId: 'inp_phone',
  userId: 'usr_123',
  timeSpentMs: 34000,
  hadValue: true,
  timestamp: Date.now(),
})

track('screen_completed', {
  flowId: 'flow_abc',
  screenId: 'screen_profile',
  userId: 'usr_123',
  timeSpentMs: 87000,
  ctaTaps: 2,
  timestamp: Date.now(),
})

track('flow_completed', {
  flowId: 'flow_abc',
  userId: 'usr_123',
  totalTimeMs: 180000,
  screensCount: 4,
  timestamp: Date.now(),
})

Implementing field tracking in React Native

function useFieldAnalytics(fieldId: string, flowId: string) {
  const focusTime = useRef<number | null>(null)

  const onFocus = () => {
    focusTime.current = Date.now()
    track('field_started', { fieldId, flowId })
  }

  const onBlur = (value: string) => {
    const timeSpentMs = focusTime.current
      ? Date.now() - focusTime.current
      : 0

    track('field_completed', {
      fieldId,
      flowId,
      timeSpentMs,
      hadValue: value.length > 0,
    })

    focusTime.current = null
  }

  return { onFocus, onBlur }
}

The metrics that matter

Drop-off rate per field

High drop-off on a required field means friction. Fix the label, add helper text, or change the input type.

Time-on-field

Normal is 5-15 seconds for text and 10-20 seconds for complex inputs. More than 30 seconds usually means confusion.

CTA tap count per screen

ctaTaps greater than 1 means the user hit validation errors. Consistently high counts mean validation or error messages need work.

App-closed per screen

The screen where users abandon the app often has a trust or friction problem, not just a UX problem.

What Recus tracks automatically

Recus tracks field_started, field_completed, screen_completed, and flow_completed automatically for every field in your flows. No code, event setup, or analytics configuration.

  • Drop-off per field across all users.
  • Average time-on-field.
  • CTA tap count per screen.
  • Flow completion rate over time.
  • Comparison by user segment.

Summary

Screen-level completion rates tell you something is wrong. Field-level analytics tells you exactly what to fix.

Track field_started, field_completed, screen_completed, and flow_completed. Store timeSpentMs, hadValue, and ctaTaps. Or use Recus and get all of it out of the box.