移动端埋点与数据分析深度实战:从Firebase-Analytics到自定义事件与漏斗分析全解析
移动端埋点与数据分析深度实战:从Firebase-Analytics到自定义事件与漏斗分析全解析
引言
移动应用的数据分析驱动产品决策——用户行为追踪、漏斗分析、留存分析、AB测试效果。Firebase Analytics提供免费基础分析,自定义事件实现精细埋点。本文从移动数据分析出发,系统讲解事件设计、Firebase Analytics集成、自定义埋点、漏斗分析、隐私合规。
一、事件设计
// 事件设计原则
// 1. 标准事件:Firebase预定义(view_item, add_to_cart, purchase等)
// 2. 自定义事件:业务特定(lesson_completed, level_up等)
// 3. 事件参数:附加数据(item_id, value, currency等)
// 4. 用户属性:用户分群(user_type, subscription_status等)
class AnalyticsTracker @Inject constructor(
private val firebase: FirebaseAnalytics
) {
// 标准事件
fun trackViewItem(itemId: String, itemName: String, price: Double) {
val bundle = Bundle().apply {
putString(FirebaseAnalytics.Param.ITEM_ID, itemId)
putString(FirebaseAnalytics.Param.ITEM_NAME, itemName)
putDouble(FirebaseAnalytics.Param.VALUE, price)
putString(FirebaseAnalytics.Param.CURRENCY, "USD")
}
firebase.logEvent(FirebaseAnalytics.Event.VIEW_ITEM, bundle)
}
fun trackAddToCart(itemId: String, quantity: Int, price: Double) {
val bundle = Bundle().apply {
putString(FirebaseAnalytics.Param.ITEM_ID, itemId)
putLong(FirebaseAnalytics.Param.QUANTITY, quantity.toLong())
putDouble(FirebaseAnalytics.Param.VALUE, price * quantity)
putString(FirebaseAnalytics.Param.CURRENCY, "USD")
}
firebase.logEvent(FirebaseAnalytics.Event.ADD_TO_CART, bundle)
}
fun trackPurchase(orderId: String, items: List<PurchaseItem>, total: Double) {
val itemsBundle = items.map { item ->
Bundle().apply {
putString(FirebaseAnalytics.Param.ITEM_ID, item.id)
putString(FirebaseAnalytics.Param.ITEM_NAME, item.name)
putLong(FirebaseAnalytics.Param.QUANTITY, item.quantity.toLong())
putDouble(FirebaseAnalytics.Param.PRICE, item.price)
}
}
val bundle = Bundle().apply {
putString(FirebaseAnalytics.Param.TRANSACTION_ID, orderId)
putDouble(FirebaseAnalytics.Param.VALUE, total)
putString(FirebaseAnalytics.Param.CURRENCY, "USD")
putParcelableArray(FirebaseAnalytics.Param.ITEMS, itemsBundle.toTypedArray())
}
firebase.logEvent(FirebaseAnalytics.Event.PURCHASE, bundle)
}
// 自定义事件
fun trackLessonCompleted(lessonId: String, duration: Long, score: Int) {
val bundle = Bundle().apply {
putString("lesson_id", lessonId)
putLong("duration_seconds", duration)
putInt("score", score)
putBoolean("passed", score >= 60)
}
firebase.logEvent("lesson_completed", bundle)
}
fun trackScreenView(screenName: String, screenClass: String) {
val bundle = Bundle().apply {
putString(FirebaseAnalytics.Param.SCREEN_NAME, screenName)
putString(FirebaseAnalytics.Param.SCREEN_CLASS, screenClass)
}
firebase.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundle)
}
// 用户属性
fun setUserProperties(user: User) {
firebase.setUserProperty("user_type", user.type.name)
firebase.setUserProperty("subscription_status", user.subscription.name)
firebase.setUserProperty("registration_date", user.createdAt.toString())
val uid = user.id.toString()
firebase.setUserId(uid)
firebase.setUserProperty("uid", uid)
}
// 用户细分
fun trackUserSegment(segment: String, value: String) {
firebase.setUserProperty(segment, value)
}
}
二、自动页面追踪
// Compose自动页面追踪
@Composable
fun TrackScreenView(screenName: String) {
val analytics = LocalAnalytics.current
LaunchedEffect(screenName) {
analytics.trackScreenView(screenName, screenName)
}
}
// 使用
@Composable
fun HomeScreen() {
TrackScreenView("Home")
// 页面内容
}
// Navigation自动追踪
@Composable
fun AppNavHost() {
val navController = rememberNavController()
NavHost(navController, startDestination = "home") {
composable("home") {
TrackScreenView("Home")
HomeScreen()
}
composable("user/{id}") { entry ->
val id = entry.arguments?.getString("id")
TrackScreenView("UserDetail_$id")
UserDetailScreen(id)
}
}
// 导航监听
DisposableEffect(navController) {
val listener = NavController.OnDestinationChangedListener { _, destination, _ ->
// Firebase自动追踪
Firebase.analytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundleOf(
FirebaseAnalytics.Param.SCREEN_NAME to destination.route,
FirebaseAnalytics.Param.SCREEN_CLASS to destination.route
))
}
navController.addOnDestinationChangedListener(listener)
onDispose { navController.removeOnDestinationChangedListener(listener) }
}
}
三、漏斗分析
// 漏斗:用户从注册到购买的转化路径
// 注册→完善资料→浏览商品→加入购物车→结算→支付→完成
class FunnelTracker @Inject constructor(
private val analytics: AnalyticsTracker
) {
fun trackFunnelStep(step: FunnelStep, params: Map<String, Any> = emptyMap()) {
val bundle = bundleOf(
"funnel_name" to "registration_to_purchase",
"funnel_step" to step.name,
"step_order" to step.order,
*params.toList().toTypedArray()
)
Firebase.analytics.logEvent("funnel_step", bundle)
}
}
enum class FunnelStep(val order: Int) {
REGISTER(1),
COMPLETE_PROFILE(2),
BROWSE_PRODUCTS(3),
ADD_TO_CART(4),
CHECKOUT(5),
PAYMENT(6),
PURCHASE_COMPLETE(7)
}
// 使用
class CheckoutViewModel @Inject constructor(
private val funnel: FunnelTracker
) : ViewModel() {
fun startCheckout() {
funnel.trackFunnelStep(FunnelStep.CHECKOUT, mapOf(
"cart_total" to cart.total,
"item_count" to cart.items.size
))
}
fun completePayment(orderId: String) {
funnel.trackFunnelStep(FunnelStep.PURCHASE_COMPLETE, mapOf(
"order_id" to orderId,
"payment_method" to "credit_card"
))
}
}
四、埋点中间件
// 埋点中间件:统一管理所有埋点
class AnalyticsMiddleware(
private val providers: List<AnalyticsProvider>
) {
fun track(event: String, params: Map<String, Any>) {
// 1. 数据清洗
val cleaned = sanitize(params)
// 2. 多平台分发
providers.forEach { provider ->
provider.track(event, cleaned)
}
// 3. 调试日志
if (BuildConfig.DEBUG) {
Log.d("Analytics", "$event: $cleaned")
}
}
private fun sanitize(params: Map<String, Any>): Map<String, Any> {
return params.mapKeys { (_, v) ->
// 移除PII(个人身份信息)
v.toString().replace(Regex("\\b[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}\\b"), "[EMAIL]")
.replace(Regex("\\b\\d{11}\\b"), "[PHONE]")
}
}
}
interface AnalyticsProvider {
fun track(event: String, params: Map<String, Any>)
fun setUserProperty(key: String, value: String)
fun setUserId(id: String)
}
// Firebase实现
class FirebaseAnalyticsProvider(
private val firebase: FirebaseAnalytics
) : AnalyticsProvider {
override fun track(event: String, params: Map<String, Any>) {
firebase.logEvent(event, bundleOf(*params.toList().toTypedArray()))
}
override fun setUserProperty(key: String, value: String) {
firebase.setUserProperty(key, value)
}
override fun setUserId(id: String) {
firebase.setUserId(id)
}
}
// Amplitude/Sentry实现
class AmplitudeProvider(...) : AnalyticsProvider {
override fun track(event: String, params: Map<String, Any>) {
amplitude.logEvent(event, params)
}
// ...
}
五、隐私合规
// GDPR/CCPA隐私合规
class PrivacyManager(context: Context) {
private val prefs = context.getSharedPreferences("privacy", MODE_PRIVATE)
fun hasAnalyticsConsent(): Boolean {
return prefs.getBoolean("analytics_consent", false)
}
fun setAnalyticsConsent(granted: Boolean) {
prefs.edit().putBoolean("analytics_consent", granted).apply()
// Firebase
Firebase.analytics.setAnalyticsCollectionEnabled(granted)
// Crashlytics
Firebase.crashlytics.isCrashlyticsCollectionEnabled = granted
// Amplitude
// amplitude.trackingEnabled = granted
}
// 数据删除请求
fun requestDeletion() {
// 删除Firebase Analytics用户数据
// amplitude.regenerateDeviceId()
// 后端API:DELETE /users/me/analytics
}
// IDFA/AAID管理
fun getAdvertisingId(): String? {
return if (hasAdvertisingConsent()) {
// 仅在用户同意时获取
Firebase.installations.id
} else null
}
}
六、总结
移动数据分析驱动产品决策。事件设计遵循标准+自定义组合——Firebase标准事件覆盖电商常见场景(view_item/add_to_cart/purchase),自定义事件覆盖业务特定场景(lesson_completed/level_up)。自动页面追踪通过Navigation监听自动记录屏幕浏览。漏斗分析追踪转化路径每一步——注册→完善资料→浏览→加购→结算→支付→完成。埋点中间件统一管理多平台分发——Firebase Analytics(免费基础)+ Amplitude(高级分析)同时上报。隐私合规遵循GDPR/CCPA——用户同意后才收集数据、支持数据删除请求、PII(邮箱/电话)脱敏。生产最佳实践:标准事件覆盖电商全流程、自定义事件参数有明确命名规范、多平台分发(Firebase+Amplitude/Sentry)、PII数据脱敏、隐私合规(同意机制+数据删除)、调试模式验证埋点正确。数据分析的核心理念是"数据驱动产品"——不是凭感觉判断用户行为,而是用数据验证假设。好的埋点应该:事件命名规范(snake_case)、参数完整(每事件有足够的上下文)、不遗漏关键步骤、不过度埋点(关键事件而非每个按钮)、隐私合规(用户同意后才收集)。数据分析的最终目标是"理解用户行为、优化用户体验、提升业务指标"——漏斗分析找出转化瓶颈、留存分析发现流失原因、AB测试验证改进效果。
- 点赞
- 收藏
- 关注作者
评论(0)