2020 年下旬,Google Analytics 发布了 v4,数据收集接口迁移为向 analytics.google.com 发送 POST 请求,导致中国大陆不可用。于是因此就计划着开发了 Aofuji Analytics,作为一个超轻量级的自搭建数据收集工具,用于 GA 的简单替代。
作为我的第一个完全由自己构思的前端项目,同时作为一个我自己每天都需要用到的项目;从制定计划到完成 0.1 版本,我是如何完成 Aofuji Analytics 的开发的?
作为一个重要的 Vue.js 练手与应用项目,在前端的管理面板 (也就是数据展示面板) 自然是使用它了。在最初开始计划这个项目的时候,Vue 3 其本身以及新的组合式 API 的周边生态相对还不是很完善,因此项目选用了 Vue 2 作为前端的基础框架,但在编写代码时也同时考虑了 Vue 3 的升级兼容性。
在后端方便,为了开发的方便以及对 Vercel 的 serverless 功能的适配,选用了 express 作为基础框架。数据库则是选择了 MongoDB,对于一般的使用,MongoDB Atlas 提供的 500 连接数免费数据库非常简单方便,并且数据库本身由于 mongoose 的协助使用也十分便捷。
在 tracker 代码方面,借助 Babel 转译或是其他例如 rollup 之类的工具打包,只通过 terser 进行一次压缩并且避免使用过多现代 API 来尽可能的缩小文件大小。
代码规范分为两部分,格式与 lint。
在什么都没有的最初开发阶段,首要目标是先把 tracker 写完,DEBUG 则是直接将数据发送到 JSONPlaceholder。等到 tracker 完成了,再考虑后端的数据库结构设计。
使用类似 Google 的 Analytics Measurement Protocol 的 key 名向后端传送数据,请求将使用 Beacon API。以下是计划收集的数据:
基本数据:
t:数据种类,包含 view、leave 和 eventid:站点 IDsid:规避使用 cookie 引入的 session IDd:时间,Date.now()不同数据种类的特定数据:
view:页面访问r:document.referrerlng:用户语言leave:页面离开pvt:页面停留时间event:页面事件,在 window 上注册全局方法顾调用en:自定义事件名et:事件类型 (传入事件对象或事件名)为了避免在 tracker 中使用 cookie,view 类型的特殊处理:所有 view 类型请求将使用带回调的 XHR 发送,当服务器返回 201 (即 sid 未发送或不存在) 时设置 localStorage 存储新的 sid,当服务器返回 204 时无回调;同时,当发送除 view 类型以外的请求却未发送有效的 sid 时,请求将被 400 拒绝。
为 mongoose 设定以下 model:
Account:管理用户,初期版本仅提供单个 admin 用户Event:网页事件记录,关联 Website 和 SessionSession:数据收集的用户Share:记录分享页面Website:添加的站点,关联 UserView:网页浏览记录,关联 Website 和 Session完成 tracker 后,下一个任务是接收信息的基本路由。以下为该路由的处理进程:
/api/collect 的 GET 或 POST 请求sid 是否存在,若不存在,则新建 sessionview 类型:
path 和 ref 等数据,并且初始化 pvt 为 0language、screen、browser、system 和 locationleave 类型:
pvt 字段特殊注意点:
referrer,并更新 date 为最新时间pvt 的更新需要使用 $inc 从初值 0 增加而不是直接替换更新首先使用 Vue 完成了以下基本组件库:
AIcon...:图标,由 vue-svg-loader 提供AButton:按钮,包括普通、全宽以及全长ACard:卡片AInput:输入框ALabel:用于简单标注的小 tagAHeader:通用头部ARouterLink:对 GButton 的二次封装AList:多功能列表,最右一格可选控制或小图表组件库通过插件的 install 方法使用 Vue.use 进行安装。
/dashboard[?website=]:数据一览 (动态路由)/dashboard/[type][?website=]:数据一览 (动态路由)/realtime[?website=]:实时监控/settings:设置页 (动态组件)About:关于Account:用户设置WebsiteSettings:网站设置WebsiteEdit:网站编辑 (隐藏)/login:登录页 (登录前)使用 Vuex 模块定义多个 module:
MESSAGE:GMessage 组件相关数据THEME:主题切换相关数据COMMON:基本数据,如当前选择的网站、网站列表、登陆的账户等WEBSITE:/settings 设置页面相关数据鉴权检查:
站点选择路由 query 同步:
website queryBase (背景与导航栏) 组件中会有更新 query 的操作,因此无需再次检查/init:初始化/login:登录/metrics:数据展示/metrics/dashboard[?website=&type=]:实时页数据展示/metrics/realtime[?website=]:实时页数据展示/admin:设置页/admin/website:站点设置/admin/account:用户设置在请求 /login 登录时,首先请求 /init 获取初始化状态。若未初始化,则将第一次登录的用户密码存入数据库,否则直接登录。
密码方面,使用传统的 bcrypt + jsonwebtoken 组合,
以上计划不保证进度,可能在 1-2 年内全部完成。
2021-11-18 更新:项目完成了它的使命于是已删除