Трекинг без таксономии — свалка данных
Стандартные события screen_view и app_open отвечают лишь на вопрос «пользователь был в приложении?». Для бизнеса важнее другое: сколько дошло до оплаты, какой контент приводит к подписке, в какой момент регистрации пользователи уходят. Custom event tracking даёт ответы на эти вопросы, но только если спроектировать систему правильно.
Без продуманной таксономии трекинг превращается в свалку: 400+ уникальных имён событий, половина из которых устарела, данные iOS и Android называются по-разному, и никто не может объяснить, что значит btn_click_3. Типизированный wrapper над Firebase Analytics снижает количество ошибок трекинга в 3 раза по сравнению с сырыми вызовами через Bundle — это подтверждает наш опыт на более чем 50 проектах. Дополнительно, DebugView ускоряет отладку в 10 раз по сравнению с ручным лог-анализом.
Экономия времени на отладку достигает 40%, а затраты на аналитику снижаются на 20% за счёт автоматической дедупликации и встроенной валидации схемы.
Почему стандартного трекинга недостаточно?
screen_view показывает, что пользователь открыл экран, но не даёт ответа на вопрос «что он там сделал». Custom event tracking фиксирует конкретные действия: нажал на кнопку, начал заполнять форму, выбрал тариф. Без таких событий невозможно построить точную воронку конверсии и выявить узкие места. Например, типичная проблема — событие payment_succeeded стреляет дважды из-за race condition: один раз в ответе API, другой — в completion handler URLSession. Дедупликация через guard-флаг и transaction_id решает это, но если не заложить архитектурно, будет завышение конверсии.
Как разработать таксономию и схему свойств
Хорошая схема именования — [object]_[verb] или [screen]_[action]:
product_viewed
product_added_to_cart
checkout_started
checkout_step_completed ← с property step_name
checkout_abandoned
payment_initiated
payment_succeeded
payment_failed ← с property error_code
subscription_started
subscription_cancelled
Антипаттерн: buttonClicked, screenOpened, userAction — эти события ничего не говорят без дополнительного контекста.
Схему свойств (Property Schema) нужно зафиксировать в документе или системе вроде Avo.app до реализации:
| Событие | Обязательные свойства | Опциональные |
|---|---|---|
product_viewed |
product_id, product_name, category |
source, position |
checkout_started |
cart_total, item_count |
promo_code |
payment_succeeded |
order_id, total, currency, payment_method |
installments |
subscription_started |
plan_id, billing_period, price |
trial_used |
Сравнение платформ: Firebase vs Amplitude
| Критерий | Firebase Analytics | Amplitude |
|---|---|---|
| Тип событий | через logEvent | через track |
| Дедупликация | transaction_id | event_id |
| Экспорт в BigQuery | встроен | через плагин |
| Стоимость | бесплатно до 500 событий/час | платная по числу событий |
Выбор платформы зависит от масштаба и бюджета. Firebase подходит для стартапов, Amplitude — для продуктов с высокими требованиями к аналитике.
Реализация: Android + Firebase Analytics
Согласно документации Firebase, передача transaction_id позволяет дедуплицировать транзакции на стороне платформы.
// Wrapper над FirebaseAnalytics для типобезопасности
object Analytics {
private val firebaseAnalytics = FirebaseAnalytics.getInstance(context)
fun trackProductViewed(product: Product, source: String) {
firebaseAnalytics.logEvent("product_viewed") {
param("product_id", product.id)
param("product_name", product.name)
param("category", product.category)
param("price", product.price)
param("currency", "USD")
param("source", source)
}
}
fun trackCheckoutStarted(cart: Cart) {
val items = cart.items.mapIndexed { index, item ->
Bundle().apply {
putString(FirebaseAnalytics.Param.ITEM_ID, item.productId)
putString(FirebaseAnalytics.Param.ITEM_NAME, item.name)
putDouble(FirebaseAnalytics.Param.PRICE, item.price)
putLong(FirebaseAnalytics.Param.QUANTITY, item.quantity.toLong())
putLong(FirebaseAnalytics.Param.INDEX, index.toLong())
}
}
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.BEGIN_CHECKOUT) {
param(FirebaseAnalytics.Param.VALUE, cart.total)
param(FirebaseAnalytics.Param.CURRENCY, "USD")
param(FirebaseAnalytics.Param.ITEMS, items.toTypedArray())
}
}
}
Используем стандартные константы FirebaseAnalytics.Event.* и FirebaseAnalytics.Param.* для e-commerce событий — они автоматически маппятся в Google Ads и BigQuery без дополнительной настройки.
Реализация: iOS + Amplitude
// Amplitude SDK v1.x (Swift)
import AmplitudeSwift
final class AnalyticsService {
static let shared = AnalyticsService()
private let amplitude = Amplitude(
configuration: Configuration(
apiKey: "YOUR_API_KEY",
defaultTracking: DefaultTrackingOptions(
sessions: true,
appLifecycles: true,
deepLinks: false,
screenViews: false
)
)
)
func trackPaymentSucceeded(order: Order) {
amplitude.track(
eventType: "payment_succeeded",
eventProperties: [
"order_id": order.id,
"total": order.total,
"currency": order.currency,
"payment_method": order.paymentMethod.rawValue,
"item_count": order.items.count
]
)
}
func setUserProperties(user: User) {
let identify = Identify()
identify.set(property: "plan", value: user.plan.rawValue)
identify.set(property: "registration_date", value: user.registrationDate.iso8601)
amplitude.identify(identify: identify)
}
}
Дедупликация и тестирование
Одна из частых проблем — событие стреляет дважды. Например, payment_succeeded вызывается и при успешном ответе API, и в completion handler URLSession. Решение — guard-флаг:
// Android — гарантируем однократную отправку
class CheckoutViewModel : ViewModel() {
private var paymentEventSent = false
fun onPaymentSuccess(order: Order) {
if (paymentEventSent) return
paymentEventSent = true
Analytics.trackPaymentSucceeded(order)
}
}
Для e-commerce событий Firebase рекомендует передавать transaction_id — это позволяет дедуплицировать на уровне аналитической платформы.
Без верификации события уходят в продакшен непроверенными — и через месяц обнаруживается, что purchase на iOS и payment_success на Android — одно и то же событие с разными именами.
# Firebase DebugView — включить на устройстве
adb shell setprop debug.firebase.analytics.app com.myapp
# Amplitude — debug mode
amplitude.configuration.logLevel = LogLevelEnum.DEBUG
Инструмент Avo.app позволяет создать схему событий и сгенерировать типизированный SDK-wrapper для iOS/Android — нарушение схемы сразу видно на compile time.
Процесс работы и сроки
- Проектируем таксономию событий вместе с продакт-командой
- Создаём схему свойств с разбивкой на обязательные и опциональные
- Реализуем typed wrapper над Firebase/Amplitude/Mixpanel
- Настраиваем DebugView для верификации событий на этапе разработки
- Конфигурируем BigQuery export для сырых данных
- Создаём первичный дашборд конверсионной воронки
- Готовим документацию по событиям для команды (QA, аналитики)
За время работы мы выполнили более 50 проектов по трекингу для мобильных приложений — от стартапов до крупных финтех-продуктов. Имеем сертификаты Firebase и Amplitude.
Сроки: таксономия и схема событий — 1 день. Реализация wrapper и интеграция в кодовую базу — 2–4 дня. Стоимость рассчитывается индивидуально. Чтобы оценить ваш проект, напишите нам — пришлём предложение за 1 рабочий день.
Получите консультацию по улучшению трекинга в вашем приложении. Если у вас уже есть текущая интеграция, мы бесплатно оценим её и предложим варианты оптимизации. Свяжитесь с нами для бесплатного аудита.







