惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
有赞技术团队
有赞技术团队
博客园 - 三生石上(FineUI控件)
博客园_首页
博客园 - 【当耐特】
WordPress大学
WordPress大学
月光博客
月光博客
博客园 - 叶小钗
S
SegmentFault 最新的问题
雷峰网
雷峰网
H
Help Net Security
宝玉的分享
宝玉的分享
A
About on SuperTechFans
IT之家
IT之家
J
Java Code Geeks
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
B
Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog

蚊子的前端博客

微说 | 有的人觉得只要不考XX,一定能考好!-蚊子的前端博客 微说 | 春天来了-蚊子的前端博客 明天和意外不知道哪个先来-蚊子的前端博客 微说 | 既然错过了路口,就及时止损,重新规划路线上路-蚊子的前端博客 微说 | 2025年的出生人口数是792万-蚊子的前端博客 微说 | 工作年终总结,让写对接的接口的数量?-蚊子的前端博客 微说 | 温家宝:没有政治体制改革的成功 经济体制改革不可能进行到底-蚊子的前端博客 微说 | 违法犯罪了该不该被禁言?-蚊子的前端博客 微说 | 不明白为什么在推荐去俄罗斯旅游-蚊子的前端博客 微说 | 易中天论骗子-蚊子的前端博客 微说 | 一场大风吹散了秋天-蚊子的前端博客 微说 | 既要、又要、还要、更要!-蚊子的前端博客 又是一年的国庆雨季-蚊子的前端博客 微说 | 预估下2025年的出生人口数据-蚊子的前端博客 微说 | 可惜了我那些小时候的书本-蚊子的前端博客 微说 | 牛马有的是,驴不够了!-蚊子的前端博客 微说 | 能否有一条非户口也能高考的路-蚊子的前端博客 微说 | 小聊中医-蚊子的前端博客 微说 | 将要制作的一款新产品-蚊子的前端博客 微说 | 做人要有信-蚊子的前端博客 微说 | 好一个正义联盟-蚊子的前端博客 微说 | 都是见过吃过的主儿-蚊子的前端博客 微说 | 追求8小时工作制有错吗?-蚊子的前端博客 微说 | 如果尖锐的批评完全消失-蚊子的前端博客 微说 | 很好!-蚊子的前端博客 微说 | 封禁用户可以,但要告知具体原因-蚊子的前端博客 微说 | 面朝大海,春暖花开-蚊子的前端博客 微说 | 程序员的悲哀是什么?-蚊子的前端博客 微说 | 2025年出生人口的预测-蚊子的前端博客 前端在 LiveKit 中如何获取所有的参与者-蚊子的前端博客
前端业务的监控与埋点数据的上报-蚊子的前端博客
author · 2020-08-17 · via 蚊子的前端博客

我曾经在 2018 年 12 月底的时候,发表过Vue 单页面中进行业务数据的上报,现在这 1 年多以来,我对此也有了更深的理解。

这里,我们还是主要探讨业务数据的上报,关于页面性能和错误日志的收集上报,不在此讨论范围内。

我们前端团队的业务数据上报功能,主要集中在新闻客户端内部,依赖于新闻客户端提供的特性,因此其他团队的前端上报组件是没办法适应我们的需求的,这里我本人基于之前上报的经验,开发了一套完整的前端业务埋点数据上报组件。

在开发这套组件之前,我们要先明确几个问题:

  1. 哪些数据是可以自行收集的,哪些数据需要开发者埋点上报;
  2. 开发者进行数据埋点的方式有哪些?
  3. 如何保障设备的唯一性;
  4. 跳转前的上报丢失如何处理;
  5. 在新闻客户端、微信、QQ 等环境都可以进行上报;
  6. 单页面应用中,切换页面时如何上报;
  7. 用户并未退出页面,而是切换了 APP,又重新切换回来怎么办?
  8. 是否支持自定义上报的方式?

上面的这些疑问,我们一一进行了解决。

1. 可以自行收集的信息与设备唯一性 #

很多信息都是可以自行收集,而不用每个开发者都收集一遍,例如基于新闻客户端提供的能力,可以拿到设备信息,已登录用户的个人信息,ua 等,都是可以自行收集的,然后存储起来。

不过在新闻客户端外,就无法拿到设备信息了。我在这里,通过前端生成一个尽量唯一 的码来标识设备,并存储到 cookie 和 localStorage 中,若存在则使用,若不存在则生成一个新的。以此来保证设备的唯一性。

let uid = cookie.getCookie('wzpuser') || localStorage.getItem('wzpuser');
if (!uid) {
    uid = 'gh' + Date.now() + (Math.random() + '').substr(-6);
    cookie.setCookie('wzpuser', uid, 360);
    localStorage.setItem('wzpuser', uid);
}
this.__data.uid = uid;
return Promise.resolve(this.__data);

开发者可以更加关注在页面和用户行为上。

2. 开发者进行数据埋点的方式有哪些? #

主要有 2 种方式,一个是开发者的主动上报:

reporter.send({
    pagename: 'mainpage',
    event_id: 'banner_click',
});

还有一种方式,是在 html 元素上添加data-reporter属性,然后进行事件冒泡,若遇到 data-reporter 后,则进行上报;若一直冒泡到 document 上都没有该属性,则不上报。

// 渲染每一个专场
const renderItem = (item: SpecialItem) => (
    <div
        data-reporter={JSON.stringify({
            pagename: 'mainpage',
            event_id: 'item_click',
        })}
    >
        <div
            className="cover"
            onClick={() => handleAnswer(item.ename, item.zhname, item)}
        >
    </div>
);

3. 跳转前的上报丢失如何处理 #

我们经常需要上报点击某个链接的 pv,但通常会存在上报还没有完成,页面已经卸载了,导致上报失败。

针对这种情况,我是在跳转前,先存储到本地,等下次重新回到这个页面时,将存储的数据进行上报。为了方便传入和存储,我对字段也进行了过滤,没有数据的字段全部去掉,只上报有数据的字段。

reporter.send(
    {
        pagename: 'mainpage',
        event_id: 'link_click',
    },
    'save'
); // 先进行存储
window.location.href = 'https://www.xiabingbao.com';

4. 在新闻客户端、微信、QQ 等环境都可以进行上报 #

新闻客户端中提供了一些获取设备信息和用户信息的能力,而微信、QQ、浏览器等环境,只能使用前端的一些骚操作了,例如分析 cookie 中的字段,ua 中的一些字段等等。

这里我也编写了一个工具方法https://github.com/wenzi0github/utils,将这些能力独立出来。欢迎 star。

5. 单页面应用中,切换页面时如何上报 #

这个问题没有很好地解决,虽然能监听到 history 路由和 hash 路由的变化(前端中的 hash 和 history 路由),但页面的名称需要提前定义好,而组件是不知道的,因此这里交给开发者开进行监听路由的变化并上报数据。

// 每个hash路由的PV上报
router.afterEach((to) => {
    // to为当前已打开的页面,to.name为在router/index.ts中设定的name
    reporter.send({
        pagename: to.name,
        event_id: 'pv',
    });
});

6. 用户并未退出页面,而是切换了 APP,又重新切换回来怎么办? #

用户没有退出页面,而是使用了系统级的 home 键,进行了 APP 的切换,其实用户也是真实的离开了,若用户重新回来,其实 page view 应该是要+1 的,然而页面没有刷新,会产生丢失 PV 的情况。

这里我们可以监听页面的可见性,当页面重新可见时,我们就把 pv+1。当然还有一种情况要考虑到:用户可能只是在多个 APP 中切换,当前页面只是其中的过客而已,而用户并没有真的进入到这个页面中。因此我们需要设置下重新上报 PV 的条件:

  • 距离上次可见时有 30 分钟左右;
  • 当前可见已有 5 秒以上;
let lastShowTime = 0; // 上次可见时的时间

const visibility = new PageVisibility();
visibility.visibilityChange((isShow) => {
    let timer;
    if (isShow && Date.now() - lastShowTime >= 1000 * 60 * 30) {
        // 页面可见时
        timer = setTimeout(() => {
            report.send({
                pagename: 'mainpage',
                event_id: 'pv',
            });
        }, 5000); // 5秒后上报
    } else {
        clearTimeout(timer);
    }
});

7. 是否支持自定义上报的方式 #

组件中提供了 img 标签上报和 post 方式的方式,如果这两种方式也不满足上报要求,可以自定义上报方式,并上报到对应的服务器上。

const report = new Report({
    actid: 56,
    adapter: (data) => {
        // 要上报的数据
        console.log(data);
    },
});

8. 总结 #

埋点数据上报

通过这次业务埋点数据的上报,也了解了很多基础功能的实现,同时还有如何提供自定义的能力。