РазработкаАналитика (OpenPanel)

Аналитика OpenPanel в PlanForge

Актуально на: 2026-03-19

Обзор

PlanForge использует self-hosted OpenPanel через @openpanel/web без @openpanel/nextjs.

Интеграция намеренно ручная для отслеживания screen_view, чтобы первый просмотр страницы всегда был связан с аутентифицированным профилем.

Идентификация и просмотры экранов

Почему используются ручные screen view

@openpanel/web с trackScreenViews: true отправляет первый screen_view сразу после создания SDK. В App Router это происходило до вызова identify() из дочерних аутентифицированных layout’ов, поэтому первое событие часто было анонимным.

Чтобы избежать этого race condition:

  • trackScreenViews отключён в app/analytics-provider.tsx
  • SDK всё равно инициализируется рано в корневом layout
  • identify() вызывается в аутентифицированных layout’ах через app/analytics-identify.tsx
  • после identify() сразу вызывается screenView()
  • последующие переходы по маршрутам отслеживаются в app/analytics-navigation.tsx

Текущий жизненный цикл

  1. Корневой layout монтирует AnalyticsProvider.
  2. SDK OpenPanel создаётся один раз.
  3. Аутентифицированный дочерний layout рендерит AnalyticsIdentify.
  4. Вызывается op.identify(...) с параметрами:
    • profileId = userId
    • firstName = name
    • email = email
    • properties.role = role
  5. Идентификация помечается как готовая в локальном runtime аналитики.
  6. Первый screen_view отправляется вручную.
  7. Все последующие переходы по маршрутам отправляют screen_view из навигационного трекера.
  8. При выходе из системы вызывается op.clear() и состояние готовности идентификации сбрасывается.

Задействованные файлы

Хелперы отслеживания

Всё клиентское отслеживание проходит через lib/analytics-events.ts.

Хелперы:

  • trackEvent(name, properties) — отправляет событие немедленно, если SDK существует
  • trackWhenIdentified(name, properties) — отправляет только после готовности идентификации
  • clearAnalyticsIdentity() — очищает идентификацию пользователя/сессии OpenPanel и локальное состояние готовности

Что отслеживается

Автоматические функции SDK, которые остаются включёнными

Эти функции предоставляются самим SDK OpenPanel:

  • отслеживание исходящих внешних ссылок через trackOutgoingLinks: true
  • события на основе атрибутов через trackAttributes: true

Примечание: события на основе атрибутов срабатывают только для DOM-элементов с data-track="...". PlanForge в основном использует явный trackEvent(...), а не data-track.

Контекст экранов и сессий

  • identify
  • первый аутентифицированный screen_view
  • последующие screen_view при переходах по маршрутам

События проектов

Отслеживаются в app/(app)/projects/projects-client.tsx.

  • project_created
  • project_opened
  • project_renamed
  • project_archived
  • project_unarchived
  • project_deleted
  • template_used
  • listing_publish_opened

Типичные свойства:

  • projectId
  • projectName
  • projectStatus
  • templateId
  • templateType

События листингов и маркетплейса

Отслеживаются в:

События:

  • listing_published
  • listing_opened
  • listing_archived
  • listing_resubmitted
  • listing_review_history_opened
  • purchase_opened
  • checkout_started
  • checkout_completed
  • purchase_project_opened
  • filter_applied

Типичные свойства:

  • listingId
  • projectId
  • projectName
  • purchaseType
  • price
  • previewFieldCount
  • sortBy

События рабочего пространства

Отслеживаются преимущественно в app/workspace-client-legacy.tsx и lib/workspace/use-workspace-persistence.ts.

События:

  • workspace_opened
  • workspace_section_viewed
  • workspace_state_saved
  • workspace_settings_updated
  • project_info_updated
  • project_calc_updated
  • scenario_applied
  • period_value_changed
  • manual_override_set
  • chart_point_adjusted
  • compare_mode_enabled

Типичные свойства:

  • projectId
  • projectName
  • workspaceView
  • classicSection
  • section
  • normalize
  • trigger
  • compareCount
  • chartTab

Примечания к workspace_state_saved

Это событие генерируется из хука персистентности рабочего пространства после успешных сохранений.

Текущие триггеры:

  • manual
  • autosave
  • cashflow-autosave
  • full-autosave
  • flush
  • unmount

Для шумных автосохранений в клиенте рабочего пространства есть throttle, чтобы повторные автосохранения не засоряли аналитику.

События сущностей на уровне строк

Отслеживаются путём сравнения текущих и предыдущих коллекций в app/workspace-client-legacy.tsx.

Охваченные коллекции:

  • продукты
  • строки МИК
  • займы
  • строки персонала
  • строки общих расходов
  • фазы календаря

События, генерируемые из diff коллекций:

  • row_created
  • row_updated
  • row_deleted

Типичные свойства:

  • entityType
  • entityId
  • entityName
  • projectId
  • projectName
  • workspaceView
  • classicSection

Текущие значения entityType:

  • product
  • mik
  • loan
  • personnel
  • general_expense
  • calendar_phase

События массового заполнения

Отслеживаются в:

События:

  • bulk_fill_applied

Текущие режимы:

  • linear
  • repeat
  • monthly
  • quarterNeed

Текущие секции:

  • ops-sales
  • ops-mik-pricing
  • ops-mik-procurement

Уведомления и авторизация

Отслеживаются в:

События:

  • notification_opened
  • notification_link_opened
  • notification_marked_all_read
  • user_signed_out

Где добавлять новые события

Используйте следующие правила:

  • бизнес-действие, инициированное страницей или модалкой: отслеживать в компоненте страницы/клиента, который владеет действием
  • мутации данных рабочего пространства, затрагивающие коллекции: предпочтительно diff-отслеживание в app/workspace-client-legacy.tsx
  • повторяющиеся действия сохранения/персистентности: отслеживать в lib/workspace/use-workspace-persistence.ts
  • жизненный цикл авторизации или сессии: отслеживать рядом с точкой входа/выхода

Предпочитайте явные имена событий вместо обобщённых событий кликов.

Хорошо:

  • project_created
  • workspace_state_saved
  • checkout_completed

Избегайте:

  • button_clicked
  • modal_opened
  • action_done

Соглашения по именованию событий

Текущее соглашение — snake_case с продуктовой семантикой:

  • объект + действие: project_created
  • процесс + состояние: checkout_started
  • семантическое действие рабочего пространства: workspace_section_viewed
  • нормализованное обобщённое событие для diff сущностей: row_created

Известные ограничения

  • Отслеживается не каждый клик в UI. Фокус на продуктовых действиях и значимых изменениях состояния.
  • trackAttributes включён, но кодовая база в настоящее время не зависит от большого количества атрибутов data-track.
  • Diff-отслеживание строк считает любое изменение сериализованного объекта обновлением, поэтому даже очень мелкие правки считаются как row_updated.
  • В репозитории всё ещё есть не связанное с аналитикой предупреждение Next.js о deprecated именовании middleware; это не влияет на аналитику.

Чек-лист проверки

При изменении аналитики проверьте:

  1. Первый аутентифицированный screen_view не анонимный
  2. Переходы по маршрутам продолжают отправлять screen_view
  3. Выход из системы очищает идентификацию
  4. Ключевые потоки проектов/рабочего пространства генерируют ожидаемые события в OpenPanel
  5. pnpm prisma:generate
  6. pnpm build

Быстрый индекс событий

Идентификация / навигация

  • identify
  • screen_view
  • user_signed_out

Проекты

  • project_created
  • project_opened
  • project_renamed
  • project_archived
  • project_unarchived
  • project_deleted
  • template_used

Рабочее пространство

  • workspace_opened
  • workspace_section_viewed
  • workspace_state_saved
  • workspace_settings_updated
  • project_info_updated
  • project_calc_updated
  • scenario_applied
  • period_value_changed
  • manual_override_set
  • chart_point_adjusted
  • compare_mode_enabled
  • bulk_fill_applied
  • row_created
  • row_updated
  • row_deleted

Маркетплейс / листинги / покупки

  • listing_publish_opened
  • listing_published
  • listing_opened
  • listing_archived
  • listing_resubmitted
  • listing_review_history_opened
  • purchase_opened
  • checkout_started
  • checkout_completed
  • purchase_project_opened
  • filter_applied

Уведомления

  • notification_opened
  • notification_link_opened
  • notification_marked_all_read