ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

amis 页面交互行为跟踪(tracker)实战指南:从采集到上报的完整方案

amis 页面交互行为跟踪(tracker)实战指南:从采集到上报的完整方案 amis 页面交互行为跟踪tracker实战指南从采集到上报的完整方案【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amisamis 从 1.5.0 版本起内置了用户交互行为采集功能通过渲染时注入的tracker函数即可统一收集 api 请求、按钮点击、弹框开关、表单修改、Tab 切换、页面生命周期等十余种行为事件。本文基于 tracker.md 文档结合 amis-core 源码深入讲解 tracker 的接入方式、事件数据结构、各事件触发场景与上报最佳实践读完即可在自己的 amis 应用中落地一套可分析、可检索的用户行为埋点体系。设计思想采集与存储解耦amis 的 tracker 遵循一条明确的分工原则amis 只负责采集对行为的存储和分析都由外部实现。也就是说amis 不内置任何埋点存储、上报队列或分析面板它只在你提供的回调函数中抛出标准化的行为事件对象至于如何持久化、如何聚合、如何可视化完全由接入方根据自身的数据平台决定。这一点从 amis-core 的源码可以得到印证在 factory.tsx 中默认环境的tracker是一个空函数tracker(eventTrack, props) {}而在 env.tsx 定义的RendererEnv接口中tracker的签名固定为tracker: (eventTrack: EventTrack, props?: PlainObject) void;调用方不实现该函数时所有事件都会被静默丢弃一旦实现amis 便会在各类交互节点自动调用它。这种采集框架 业务侧存储的组合让 amis 的埋点能力既能开箱即用又能无缝接入任意现有数据分析体系。使用方法通过 env 注入 tracker在使用 amis 渲染时第三个参数env中可以传递tracker函数。下面以 SDK 的amis.embed为例amis.embed( #root, { // amis schema }, { // 这里是初始 props }, { tracker: (eventTrack, props) { const blob new Blob([JSON.stringify(eventTrack)], { type: application/json }); navigator.sendBeacon(/tracker, blob); } } );其中四个参数依次是容器选择器、页面 schema、初始 props、环境配置 env。tracker就是 env 上的一个普通属性因此无论是 SDK、React通过Renderer组件的 env 属性还是其他嵌入方式注入方式完全一致。示例中用到了navigator.sendBeacon上报这是埋点场景的推荐做法它不阻塞页面卸载、不依赖 XHR 生命周期适合在页面关闭或跳转时兜底上报。官方文档也明确提示具体实现可以根据实际需求修改比如可以收集一段时间后再批量提交等——即可以在tracker内部做缓冲、去重、合并再按固定时间窗口批量发送以降低对服务端的请求压力。tracker 与 fetcher 的关系从源码看tracker并不是零散地挂在每个组件上而是被统一编织进请求链路。factory.tsx 中有这样一行options.fetcher wrapFetcher(options.fetcher, options.tracker) as any;wrapFetcher定义于 api.ts会对全局的 fetcher 做一层包装在每次真实请求发出前调用 tracker 并抛出api事件。这意味着只要某个组件最终走的是统一的 fetcher 通道包括所有组件的api/source配置、action 的 ajax 类型请求它的请求行为就一定会被采集无需为每个组件单独写埋点代码。参数类型EventTrack 的定义tracker第一个参数eventTrack的类型为EventTrack完整定义在 types.tsexport interface EventTrack { /** * 事件类型 */ eventType: | api | url | link | dialog | drawer | copy | reload | email | prev | next | cancel | close | submit | confirm | reset | reset-and-submit | formItemChange | tabChange | pageLoaded | pageHidden | pageVisible | string; /** * 事件数据 */ eventData?: PlainObject | Api; }与官方文档中的定义相比源码中的联合类型多了一个| string兜底eventType允许任意字符串同时eventData被声明为可选。实际接入时建议以文档列出的 21 种事件类型为准eventData的具体结构因事件类型而异下文逐类说明。tracker 的第二个参数 propstracker的第二个参数props源码中标注为PlainObject可以拿到触发事件组件的所有属性配置。当eventData无法区分两个行为完全相同的组件时这个参数是重要的补充判断依据——例如通过props中的字段判断事件来自哪个表单、哪个列表页。需要注意的是这个参数的具体内容随触发组件不同而变化应结合具体场景谨慎使用。区分相同的点击行为为组件添加 ideventData默认只包含组件的 schema 配置。当页面中存在两个配置完全相同的按钮时例如两个提交按钮[ { label: 提交, primary: true }, { label: 提交, primary: true } ]点击它们触发的事件内容是相同的{ eventType: submit, eventData: { primary: true, label: 提交 } }此时无法从eventData判断用户点击的是哪一个。解决办法是给组件加上id属性[ { id: button1, label: 提交, primary: true }, { id: button2, label: 提交, primary: true } ]这样事件中就会包含id字段从而精确区分{ eventType: submit, eventData: { id: button1, primary: true, label: 提交 } }同理表单项的formItemChange事件中如果表单项配置了id也会被透传到eventData中方便区分同名输入框。这是埋点分析中保证事件可区分性的两个核心手段之一另一个就是使用第二个参数props。事件详解以下是各事件类型的触发场景与数据示例。除了下面的文档说明还可以打开浏览器的控制台在debug分类下直接看到实际操作时的事件示例方便对照调试。apiapi事件的来源有两个方面一是各种组件的api及source配置二是 action 里的 ajax 类型请求。以 crud 为例GET 请求事件如下{ eventType: api, eventData: { method: get, url: /api/mock2/sample?page1perPage10, query: { page: 1, perPage: 10 } } }POST 请求事件类似{ eventType: api, eventData: { method: post, url: /api/mock2/form/saveForm } }注意为了避免信息泄露eventData中没有包含提交数据。这一设计在源码中有明确体现api.ts 中调用 tracker 时使用了omit(api, [config, data, body])即把可能包含敏感字段的config、data、body全部剔除后再抛出。如果业务确实需要提交数据的详情可以通过第二个参数拿到{ tracker: (eventTrack, data) { console.log(提交数据详情, data); const blob new Blob([JSON.stringify(eventTrack)], { type: application/json }); navigator.sendBeacon(/tracker, blob); }; }data即本次请求的完整提交数据。基于同样的隐私考虑建议在 api 类事件的落库策略中不记录数据提交内容详见下文 formItemChange 的说明。urlurl是打开外部链接事件。注意不要和link混淆link一般用于应用内相对地址的无刷新跳转而url对应的是新开页签或整页跳转的外部链接。Link 组件触发的示例{ eventType: url, eventData: { url: https://www.baidu.com, blank: true, label: 百度一下你就知道 } }Action 组件触发的示例Action 组件会多出level等数据{ eventType: url, eventData: { url: http://www.baidu.com, level: success, blank: true, label: 打开 Baidu } }linklink事件主要由 Action 和 Nav 组件触发用于应用内相对地址跳转。Action 触发的数据{ eventType: link, eventData: { label: 进入介绍页, level: info, link: ../index } }Nav 触发的数据{ eventType: link, eventData: { label: Nav 2-2, link: ?cat2-2 } }它们都有label及link字段可作为这类事件的通用解析约定。dialogdialog事件主要由 action 触发示例{ eventType: dialog, eventData: { dialog: { title: 提示, closeOnEsc: true, body: 这是个简单的弹框 }, label: 打开弹框 } }需要注意dialog里会包含弹框的全部 schema 配置schema 复杂时可能导致提交数据过大建议根据需求在落库前进行字段裁剪。drawerdrawer事件主要由 action 触发示例{ eventType: drawer, eventData: { drawer: { position: left, size: xs, title: 提示, body: 这是个简单的弹框 }, label: 左侧弹出-极小框 } }与 dialog 一样drawer数据中会包含所有抽屉配置可能内容过大需要根据需求过滤后再存储。copycopy事件由 action 触发在用户点击复制类 action 时上报示例{ eventType: copy, eventData: { content: http://www.baidu.com, label: 复制一段文本 } }reloadreload事件由 action 触发用于记录刷新/重载类操作示例{ eventType: reload, eventData: { label: 搜索, target: my_form.select } }其中target是本次 reload 的目标组件标识。emailemail事件由 action 触发用于记录发送邮件类操作示例{ eventType: email, eventData: { to: amisbaidu.com, cc: baidubaidu.com, subject: 这是邮件主题, body: 这是邮件正文, label: 发送邮件 } }prev / nextprev和next事件可能出现在两个地方Wizard 组件里的上一步/下一步以及 Dialog 里的上一个/下一个。示例{ eventType: next, eventData: { level: info, label: 下一个 } }cancelcancel是 action 里的取消事件示例{ eventType: cancel, eventData: { label: 关闭 } }closeclose是 action 里的关闭事件主要用于关闭弹框示例{ eventType: close, eventData: { label: 算了 } }submitsubmit是点击提交按钮的事件。需要注意这个事件可能还会同时触发api事件比如表单的提交按钮会先触发submit随后发出请求时再触发api。示例{ eventType: submit, eventData: { primary: true, label: 提交 } }confirmconfirm是 action 中的事件主要用于确认类操作如关闭弹框前的确认示例{ eventType: confirm, eventData: { primary: true, label: 确认 } }resetreset由 action 触发主要用于重置表单数据示例{ eventType: reset, eventData: { label: 重置 } }reset-and-submitreset-and-submit由 action 触发会重置表单并提交数据示例{ eventType: reset-and-submit, eventData: { label: 重置并提交 } }formItemChangeformItemChange在表单项数据变化时触发——即用户在表单里输入或修改任何数据时都会触发示例{ eventType: formItemChange, eventData: { name: name, label: 用户名, type: input-text, value: amis } }事件数据里主要是name、type和value。需要注意这个事件非常频繁只要修改内容就会触发落库时需要做频率控制和采样避免数据量爆炸有一个特例input-password类型的字段不会触发这个事件以避免隐私风险。这一行为在源码中有明确实现wrapControl.tsx 中调用 tracker 前判断了type ! input-password且事件携带id、name、label、type、value五个字段第二个参数传的是组件自身的this.props尽管密码字段不触发该事件在 api 事件中提交的数据里仍有可能包含隐私信息因此官方建议对 api 类事件同样不记录数据提交内容前文已说明 api 事件默认会剔除data/body与 action 类似给表单项加上id字段也会透传到这里方便区分同名输入框{ eventType: formItemChange, eventData: { id: name1, name: name, label: 用户名, type: input-text, value: amis } }tabChangetabChange是 Tab 切换事件示例{ eventType: tabChange, eventData: { key: tab2 } }默认情况下key的值从0开始如果 Tab 上设置了hash值就会用这个值。同样如果 Tabs 设置了id也会输出该id方便区分。pageHiddenpageHidden在 Tab 切换或者页面关闭时触发可以当成用户离开页面的时间点。从源码看RootRenderer.tsx该事件基于浏览器的visibilitychange事件实现当document.visibilityState hidden时抛出pageHidden。事件没有eventData需要配合时间戳使用。pageVisiblepageVisible在用户又切换回当前页面时触发可以当作重新访问的开始时间。同样基于visibilitychange事件当document.visibilityState visible时抛出见 RootRenderer.tsx。注意由于 amis 可能被嵌入到页面中amis 无法知晓页面首次打开的时间首次访问的开始时间需要接入方在宿主页面自行处理例如在页面初始化时记录一次自定义事件。pageLoadedpageLoaded在 Page 组件加载完成时触发可用于收集页面首次打开的时间。使用前提是当前页面必须有 Page 组件该事件在 2.8.0 以上版本支持在 types.ts 的EventTrack事件类型联合中也已包含pageLoaded。调试与最佳实践控制台 debug 日志开发调试时打开浏览器的控制台在debug分类下可以看到实际操作时触发的事件示例无需断点即可直观确认各类事件的字段是否符合预期。这是验证埋点配置是否生效的最快路径。上报策略建议综合文档与源码落地生产环境埋点时建议关注以下几点批量上报tracker回调内部可以缓冲事件按时间窗口如每 510 秒或条数阈值批量提交降低请求量兜底上报页面关闭、Tab 切换时触发的事件如pageHidden使用navigator.sendBeacon上报避免请求被浏览器取消字段裁剪dialog、drawer等事件可能携带完整 schemaformItemChange非常频繁都应在落库前裁剪或采样隐私保护api 事件的eventData默认已剔除config/data/body密码字段不触发formItemChange接入方在上报链路中应继续保持这一策略不额外记录敏感提交内容事件区分对行为相同的组件同名按钮、同名输入框配置id或利用第二个参数props补充上下文确保事件可归一到具体业务组件。总结amis 的 tracker 是一套一次注入、全站采集的行为跟踪方案接入方只需在 env 中提供一个函数即可获得 api、url、link、dialog、drawer、copy、reload、email、prev/next、cancel/close/submit/confirm、reset、reset-and-submit、formItemChange、tabChange 以及 pageHidden/pageVisible/pageLoaded 等完整的事件流。采集逻辑内置在 amis-core 的 fetcher 包装层api.ts、表单包装层wrapControl.tsx与根渲染器RootRenderer.tsx中类型定义集中在 types.ts默认空实现位于 factory.tsx。配合id区分、批量上报、字段裁剪与隐私保护策略即可构建一套稳定、可分析的用户行为数据体系。【免费下载链接】amis前端低代码框架通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表