Перейти к основному содержимому

Классификация зрителя и источника (ViewerKind / ViewSource)

Дом типизированных enum'ов, которыми dev-stats размечает каждый факт просмотра и по которым режет метрики внимания застройщика (ADR-0057). Хранение — LowCardinality(String) в ClickHouse; wire — нижний регистр.

Назначение

Два измерения разметки просмотра объекта недвижимости:

  • ViewerKindкто смотрел (тип аудитории), для сегментации «гость / агент / инвестор».
  • ViewSourceоткуда пришёл просмотр (поверхность каталога), для атрибуции трафика.

Оба проставляются консюмером при ingestion факта (property-object-view-ended, action-tracked) и хранятся в property_object_view_facts; ViewerKind дополнительно — order-компонент rollup property_object_view_daily. Unknown-значение на входе метода → ValidationError (молчаливый дефолт запрещён).

ViewerKind (тип зрителя просмотра)

Значение (wire)EnumПравило классификации
guestGuestUserId == null — аноним по AnonymousId (полностью выводится из payload)
agentAgentаутентифицированный зритель с ролью агента/риэлтора (по сигналу роли)
investorInvestorаутентифицированный зритель-инвестор (доминирующий тип аудитории каталога)

Assumption v1: разделение Agent/Investor требует роли зрителя, которой в v1 нет ни в payload, ни в измерениях dev-stats (реплики dim_user нет, ADR-0056). До появления сигнала роли (optional-поле ViewerRole в событии — additive; либо реплика dim_user) аутентифицированный зритель пишется как Investor, Agent детектируется по мере появления сигнала. Зафиксировано в «Известных ограничениях» README.

SessionViewerKind (тип зрителя сессии)

Для session_facts применяется огрублённая пара (роль зрителя на уровне сессии не разрешается):

Значение (wire)EnumПравило
guestGuestUserId == null
userUserUserId != null (аутентифицирован; без деления Agent/Investor)

ViewSource (источник просмотра)

Значение (wire)EnumСмысл
catalogCatalogпубличный каталог
searchSearchпоиск/выдача
selectionSelectionподборка
favoritesFavoritesизбранное
newsNewsлента/новости застройщика
direct-linkDirectLinkпрямой заход по ссылке
unknownUnknownисточник не определён (open-факт action-tracked до closed-события)

ViewSource несёт только property-object-view-ended; open-факт action-tracked ViewPropertyObject пишет Unknown, авторитетное значение приходит с closed-событием (тот же PropertyObjectViewId, позже по IngestionTime) и побеждает при argMax. ViewSource не хранится в rollup — при фильтре по нему метод переключается на сырьё property_object_view_facts (SLO p95 ≤ 600 мс вместо ≤ 300 мс).

Порядок разрешения классификации

Классификация детерминирована: тот же факт при переигрывании получает ту же метку. Разрешение — по первому совпавшему правилу сверху вниз.

ViewerKind (просмотр):

ПриоритетУсловиеРезультат
1UserId == nullGuest
2UserId != null и есть сигнал роли «агент/риэлтор»Agent
3UserId != null без сигнала роли (v1: сигнала нет)Investor (дефолт аутентифицированного — Assumption v1)

ViewSource (просмотр): для closed-факта — значение из метаданных action; для open-факта — Unknown; при склейке open/closed побеждает closed (позже по IngestionTime). Unknown wire-значение из closed-payload → Unknown + warning (fallback контракта на ingestion, не ValidationError).

Связь ViewerKindSessionViewerKind (огрубление на уровне сессии): сессионный факт не разрешает роль зрителя, поэтому Agent и Investor схлопываются в User:

ViewerKind просмотраSessionViewerKind сессии
GuestGuest
AgentUser
InvestorUser

Обработка неизвестных значений (ingestion vs вход метода)

Одно и то же unknown-значение обрабатывается по-разному в зависимости от того, где оно появилось:

МестоEnumПоведение при unknownПочему
Ingestion (payload события)ViewSourceUnknown + warning (не DLQ)producer мог добавить значение; факт сохраняем, размечаем как «источник не определён»
Ingestion (payload события)ViewerKindне приходит как enum — выводится консюмером (правила выше); невыводимого случая нетклассификация всегда даёт валидную метку
Вход метода (фильтр)ViewerKind/ViewSourceValidationError (400), молчаливый дефолт запрещёнвизуализатор должен явно выбирать известный сегмент

Проверяемость

  • Unknown ViewerKind/ViewSource во входе метода → ValidationError (не дефолт).
  • Open-факт с ViewSource = Unknown, затем closed того же PropertyObjectViewId с Catalog → при чтении выигрывает Catalog (argMax по IngestionTime).
  • Аутентифицированный зритель без сигнала роли (v1) → Investor; тот же просмотр после появления сигнала роли агента → Agent (детерминированно от сигнала, additive).
  • Сессия аутентифицированного зрителя → SessionViewerKind = User независимо от Agent/Investor.

Совместимость

  • Добавление нового wire-значения — breaking для клиента-визуализатора (согласовывать); unknown на входе → ValidationError, не молчаливый дефолт.
  • Хранение — строкой (LowCardinality), поэтому новое значение не ломает существующие факты.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы