Form Analytics
Built-in field-level analytics — track drop-offs, time per field, and completion rates
Full example
The complete sandbox example, read directly from the form-develop-app source at build time —
switch framework/skin to see useFormAnalytics wired to a real form. No shadcn/Vue/Angular
equivalent exists yet — those tabs show as disabled.
'use client'
import { Box, Code, Heading, Text, VStack } from '@chakra-ui/react'
import { DemoPageLayout } from '../_components'
export default function AnalyticsDemoPage() {
return (
<DemoPageLayout
title="Form.Analytics"
description="Встроенная field-level аналитика форм — drop-off, время на полях, completion rate"
>
<VStack gap={8} align="stretch">
<Box>
<Heading size="md" mb={3}>
Использование
</Heading>
<Code display="block" whiteSpace="pre" fontSize="xs" p={4} borderRadius="md">
{`import { AnalyticsPanel, createUmamiAdapter, useFormAnalytics } from '@letar/forms'
const analytics = useFormAnalytics({
formId: 'contact-form',
adapters: [createUmamiAdapter()],
onAbandon: (lastField, filled, total) => {
console.log(\`Drop-off на поле: \${lastField} (\${filled}/\${total})\`)
},
})
<Form schema={ContactSchema} onSubmit={save}>
<Form.Field.String name="name" />
<Form.Field.String name="email" />
<Form.Field.Textarea name="message" />
<Form.Button.Submit>Отправить</Form.Button.Submit>
<AnalyticsPanel analytics={analytics} position="bottom-right" />
</Form>`}
</Code>
</Box>
<Box>
<Heading size="md" mb={3}>
Адаптеры
</Heading>
<Code display="block" whiteSpace="pre" fontSize="xs" p={4} borderRadius="md">
{`// Umami (наш стек)
createUmamiAdapter()
// Яндекс Метрика (для РФ рынка)
createYandexMetrikaAdapter(12345) // counter ID → goals: form_*_abandon, form_*_complete
// Google Analytics 4
createGtagAdapter() // gtag events: form_field_interaction, form_abandon, form_complete
// PostHog
createPostHogAdapter() // posthog.capture: form_field_focus, form_form_complete
// Кастомный
const myAdapter = { name: 'custom', track: (event, formId) => fetch('/api/analytics', { body: JSON.stringify({ event, formId }) }) }`}
</Code>
</Box>
<Box>
<Heading size="md" mb={3}>
Что трекается
</Heading>
<VStack align="start" gap={2} fontSize="sm">
<Text>
<strong>field_focus</strong> — количество фокусов на каждом поле
</Text>
<Text>
<strong>field_blur</strong> — время проведённое на поле (мс)
</Text>
<Text>
<strong>field_error</strong> — ошибки валидации по полям
</Text>
<Text>
<strong>field_correction</strong> — возврат к полю после blur (исправления)
</Text>
<Text>
<strong>form_abandon</strong> — последнее поле, заполненных полей, общее время
</Text>
<Text>
<strong>form_complete</strong> — общее время, время по каждому полю
</Text>
</VStack>
</Box>
<Box>
<Heading size="md" mb={3}>
Статистика
</Heading>
<VStack align="start" gap={2} fontSize="sm">
<Text>67% форм бросают незавершёнными (Zuko, 2025)</Text>
<Text>Поле пароля — рекордсмен drop-off (10.5%)</Text>
<Text>Оптимизация формы даёт +30-50% к completion rate</Text>
<Text>Desktop: 47% completion vs Mobile: 42%</Text>
</VStack>
</Box>
</VStack>
</DemoPageLayout>
)
}shadcn-вариант этого примера ещё не готов.
Vue-пример для этого поля появится позже.
Angular-пример для этого поля появится позже.
Overview
67% of forms are abandoned before completion. The password field alone has a 10.5% drop-off rate. useFormAnalytics() gives you visibility into exactly where users struggle.
import { AnalyticsPanel, createUmamiAdapter, useFormAnalytics } from '@letar/forms'
function ContactForm() {
const analytics = useFormAnalytics({
formId: 'contact-form',
adapters: [createUmamiAdapter()],
})
return (
<Form schema={ContactSchema} onSubmit={save}>
<Form.Field.String name="name" />
<Form.Field.String name="email" />
<Form.Field.Textarea name="message" />
<Form.Button.Submit>Send</Form.Button.Submit>
{/* Dev-only panel */}
{process.env.NODE_ENV === 'development' && <AnalyticsPanel analytics={analytics} />}
</Form>
)
}What's Tracked
| Metric | Description |
|---|---|
| Focus count | How many times each field received focus |
| Time per field | Total milliseconds spent on each field |
| Error count | Validation errors per field |
| Corrections | How many times user returned to fix a field |
| Completion rate | Percentage of fields filled (0-100%) |
| Abandon | Last field, filled count, total time on beforeunload |
| Complete | Total time and per-field breakdown on submit |
Adapters
Umami
import { createUmamiAdapter } from '@letar/forms/analytics'
const adapter = createUmamiAdapter()Yandex Metrika
import { createYandexMetrikaAdapter } from '@letar/forms/analytics'
const adapter = createYandexMetrikaAdapter(12345) // counter IDSends goals: form_{formId}_field_focus, form_{formId}_abandon, form_{formId}_complete.
Google Analytics 4
import { createGtagAdapter } from '@letar/forms/analytics'
const adapter = createGtagAdapter()PostHog
import { createPostHogAdapter } from '@letar/forms/analytics'
const adapter = createPostHogAdapter()Custom Adapter
const myAdapter: AnalyticsAdapter = {
name: 'my-analytics',
track(event, formId) {
fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify({ event, formId }),
})
},
}API: useFormAnalytics(config?)
const analytics = useFormAnalytics({
enabled: true,
formId: 'contact-form',
adapters: [createUmamiAdapter()],
trackCorrections: true,
onFieldFocus: (field, timestamp) => {},
onFieldBlur: (field, timestamp, timeSpentMs) => {},
onFieldError: (field, error) => {},
onAbandon: (lastField, filledFields, totalFields) => {},
onComplete: (totalTimeMs, fieldTimes) => {},
})Returns:
| Field | Type | Description |
|---|---|---|
fieldAnalytics | Map<string, FieldAnalytics> | Per-field metrics |
completionRate | number | 0-100% |
lastFocusedField | string | null | Last focused field |
totalTimeMs | number | Time since form mount |
totalErrors | number | Total error count |
trackAbandon() | () => void | Force abandon event |
trackComplete() | () => void | Force complete event |
reset() | () => void | Reset all metrics |
AnalyticsPanel
Dev-only floating panel showing live metrics:
<AnalyticsPanel
analytics={analytics}
position="bottom-right" // bottom-right | bottom-left | top-right | top-left
/>Import
import { AnalyticsPanel, useFormAnalytics } from '@letar/forms'
import { createUmamiAdapter } from '@letar/forms/analytics'