西瓜客户端埋点实践:基于责任链的埋点框架

埋点的背景

目前互联网/软件行业内,广泛使用数据驱动产品迭代,通过精细的数据分析、模型训练为用户提供更好的服务。在此过程中,数据埋点的工作是后续数据分析、模型训练等工作的基础。

数据埋点通常是产品经理、数据分析师,以及推荐系统工程师,基于业务需求(例如:广告的下载安装转化),产品需求(例如:关注按钮的曝光次数以及点击的人数)对用户行为的每一个事件确定埋点需求。客户端工程师进行对应的埋点功能开发,通过 SDK 上报埋点的数据结果,后端记录数据进行一系列处理,并汇总后提供给产品经理、数据分析师,以及推荐系统工程师进行数据分析或模型训练,帮助优化产品运营策略。

经典的消费场景

下面有几种经典的数据消费场景:

我们可以看到,行为分析埋点,需要包括某一事件发生时的前因、后果,以及事件发生对象的特征。在复杂的数据分析、模型训练等需求中,不仅仅需要获知某个事件的发生次数,对埋点上下文尤为关注。此处上下文指的通常有 2 类,分别是:

  • 事件发生的页面信息和页面位置信息

  • 用户经过怎样的路径来到当前页面,也就是“来源”信息

经典的埋点需求

下面我们结合具体场景,看 1 个简单的埋点需求,“点击收藏”事件

上面左图是西瓜放映厅的推荐列表,右图是某个影片的详情页,点击推荐列表的影片卡片,会跳转到详情页。作为最常见的消费场景,列表和详情都有收藏按钮,我们希望知道每一个收藏事件发生的场景,方便后续优化收藏功能,以及结合用户收藏的情况,优化推荐模型。

埋点需求是上报收藏按钮的点击事件 click_favorite,要求包含收藏影片的信息,所在的场景信息等。

  1. 如果收藏事件发生在列表页,会上报如下的内容

{
  "event": "click_favorite",
  "params": {
    "video_id": "123", // 影片ID
    "video_type": 2, // 影片类型
    "page_name": "feed", // 当前页面
    "tab_name": "long_video" // 当前所在的底Tab
    "channel_name": "lvideo_recommend", // 当前所在的频道
  }
}
  1. 如果收藏事件发生在详情页,会上报如下的内容

{
  "event": "click_favorite",
  "params": {
    "video_id": "123", // 影片ID
    "video_type": 2, // 影片类型
    "page_name": "detail", // 当前页面
    "from_page": "feed", // 来源页面
    "from_tab_name": "long_video" // 来源底Tab
    "from_channel_name": "lvideo_recommend", // 来源频道
  }
}

现有方案

前端用户交互的界面,通常有复杂的页面层级关系和跳转逻辑,为了准确记录埋点信息,满足上述埋点需求,主要有以下几种实现方案。

直接传参

通过平台支持的参数传递方式,逐个定义并且读写参数;或者基于面向对象程序设计,对每个类添加相应的埋点参数,在类对象的关系中进行埋点参数传递。

对于上面的埋点需求 click_favorite,我们假设列表页和详情页的层级结构是:

  • 列表页:CinemaTabFragment(放映厅 Tab)=> VideoChannelFragment(频道)=> VideoViewHolder(卡片)

  • 详情页:VideoDetailActivity(详情页 Activity) -> BottomActionBar(底部操作栏)

当然实际情况因为项目的组件抽象复用等原因,往往会有更复杂的层级。直接传参要怎么实现这个埋点需求呢:

  1. 列表页的 click_favorite 埋点,需要从底 Tab 把所在 Tab 信息传给频道,频道再把底 Tab 和频道信息传给卡片

class CinemaTabFragment {
    fun getItem() {
        fragment = VideoChannelFragment()
        // 配置频道所处的底Tab
        fragment.tabName = "long_video"
        return fragment
    }
}

class VideoChannelFragment {
    var tabName
    var channelName

    fun onBindViewHolder(position) {
        holder.videoInfo = items.get(position)
        // 配置卡片的tabName和channelName
        holder.tabName = this.tabName
        holder.channelName = this.channelName
    }
}

class VideoViewHolder {
    var tabName
    var channelName
    var videoInfo

    fun clickFavorite() {
        // 上报埋点的时候,拼接参数
        LogSdk.onEvent("click_favorite", mapOf(
            "tab_name" to this.tabName,
            "channel_name" to this.channelName,
            "video_id" to this.videoInfo.id,
            "video_type" to this.videoInfo.type,
            "page_name" to "feed"
        ))
    }
}
  1. 详情页的 click_favorite 埋点,首先需要在列表页点击卡片跳转的时候,把上下文信息通过跳转参数传递给详情页,然后详情页解析出参数,传给底部操作栏

class VideoViewHolder {
    var tabName
    var channelName
    var videoInfo

    fun clickJumpDetail() {
        intent.putExtra("from_tab_name", this.tabName)
        intent.putExtra("from_channel_name", this.channelName)
        intent.putExtra("from_page", "feed")
        intent.putExtra("video_id", this.videoInfo.id)
        startActivity(intent)
    }
}

class VideoDetailActivity {
    // 详情页还有其他埋点需要报这几个参数ÿ
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值