@firesoon/log-sdk
v3.0.0-beta.14
Published
监听点击事件进行埋点
Downloads
21
Maintainers
Keywords
Readme
@firesoon/log-sdk
Usage
安装
yarn add @firesoon/log-sdk
// 使用
import track from '@firesoon/log-sdk';
const autoClickHandle = (e) => {
const activeTabKey = sessionStorage.getItem('activeTabKey');
const menuUuid = sessionStorage.getItem('uuid');
// 获取单击数据
const log: boolean | object = track.getLogData(e);
if (log) {
track.sendBeacon('/beacon', {
...log,
menuNo: activeTabKey,
menuUuid,
});
}
};
// 绑定单击事件监听
track.listener.on(document.body, 'click', autoClickHandle);
在 umi 搭建的项目中使用
global.ts
import track from '@firesoon/log-sdk';
const autoClickHandle = (e) => {
const activeTabKey = sessionStorage.getItem('activeTabKey');
const menuUuid = sessionStorage.getItem('uuid');
// 获取单击数据
const log = track.getLogData(e);
try {
if (log) {
const logData = {
...log,
menuNo: activeTabKey,
menuUuid,
};
// 上报数据或做缓存
track.sendBeacon('/beacon', logData);
}
} catch (e) {
// 错误处理
}
};
// 绑定单击事件监听
track.listener.on(document.body, 'click', autoClickHandle);
app.ts
import { generateUUID } from '@/utils/utils';
// 生成UUID
let uuid = generateUUID();
let lasePathName;
export function onRouteChange(params) {
const {
action,
location: { pathname },
} = params;
// query变化时不重新生成
if (action != null && pathname !== lasePathName) {
uuid = generateUUID();
sessionStorage.setItem('uuid', uuid);
lasePathName = pathname;
}
}
models/global.ts
import track from '@firesoon/log-sdk';
* queryUserInfo(_, { ... }) {
// 可以在获取用户信息的回调里配置通用埋点属性
track.config({
baseInfo: {
hospitalCode,
appVersion,
sid,
roleType,
userId,
departmentName,
appCode: 'drgsmsfl',
},
})
}
utils.ts
export function generateUUID() {
let d = new Date().getTime();
if (window.performance && typeof window.performance.now === 'function') {
d += performance.now(); //use high-precision timer if available
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
}
采集规则
- 所有的
button
点击都会自动采集 - 采集通过
classConfig
配置的classname
的节点及其子节点
个性化
data-auto-track
是否自动上报的节点(优先级最高)
- Type: boolean
- Default: 无值, 全部自动上报
只要点击元素或其父元素包含此属性为 false,则都不会自动埋点。设为 true 没有意义,不会采集无法进入 classname 或者 xpath 的 dom 节点。 该属性存在的意义即对复杂组合做个性化的埋点需求时,关闭自动埋点规则。
data-name
需要记录名称的操作
获取当前节点或其父节点第一个出现的 data-name 的值,保存到 value 中.
- Type: string
// 普通节点使用
<button data-name="下载科室病例明细">下载</button>
// {..., value: '下载科室病例明细', ... }
// 在下拉框中使用, 组件库需封装一层
// CustomSelect.tsx
<div data-name={props.label}>
<label>{props.label}</label>
<Select {...props}></Select>
</div>
// index.tsx
<CustomSelect label="出院科室" />
// { ..., value: '出院科室', content: '妇科' }
select 等浮窗需要设置挂载到 trigger 或 trigger.parentNode 下, 否则 data-name 不在其父元素上无法获取
<ConfigProvider
- getPopupContainer={triggerNode => triggerNode.parentNode}
+ getPopupContainer={node => {
+ if (node) {
+ return node.parentNode;
+ }
+ return document.body;
+ }}
>
<App />
</ConfigProvider>
config
全局配置
配置获取
type IConfigName = 'baseInfo' | 'autoTrackCls' | 'useInnerTextCls';
// 获取baseInfo的配置
track.config('baseInfo');
track.config({
classname: 'my-custom-class',
canUseInnerTextCls: 'my-custom-inner-text',
route: {
api: '/api/track/report',
onChange: (data) => console.log(data),
exclude: ['/'],
},
baseInfo: {
app: 'mrbp',
},
});
classname
允许埋点的节点 classname(对点击元素和其父元素们判断)
- Type: string[] | string;
- Default
[
'ant-input-suffix', // Search的suffix
'ant-calendar-cell', // DatePicker
'ant-calendar-footer-btn',
'ant-calendar-month-panel-cell', // MonthPicker
'ant-tabs-tab', // Tabs
'ant-select-dropdown-menu-item', // Select下拉框
'ant-checkbox-wrapper', // CheckBox
'ant-radio-wrapper', // Radio
'ant-radio-button-wrapper', // RadioButton
'fs-select-dropdown-menu-item', // ant-ui QuarterPicker'
'auto-track', // 需要自动埋点元素使用
'auto-track-inner-text', // 需要自动埋点且获取innerText作为value的元素使用
];
建议普通点击元素都使用 button 触发自动采集。若有必要配置 classname, 可配置一个通用的(如'auto-track'), 所有需要自动采集的节点都使用该 classname.
使用 classname 注意事项
1. 使用配置 classname 作为数据自动采集过滤条件时,为避免采集到无效点击,必须保证添加有点击事件的节点 classname,而不是父容器的
2. 普通元素由于数据敏感性,不会获取 innerText,只有 button 获取。所以普通标签配置了 classname 如果不自动埋点,需要配置 data-name(或 title)
// 去掉所有默认的 传入空数组或者空字符串
track.config({
classname: 'my-custom-xx',
});
canUseInnerTextCls
使用 innerText 作为 value 的元素 class 配置(并不是设置了就一定取 innerText, 有优先级)
- Type: string[] | string;
- Default
[
'ant-tabs-tab', // Tabs
'track-inner-text', // 获取innerText作为value的元素使用
'auto-track-inner-text', // 需要自动埋点且获取innerText作为value的元素使用
];
// { value: '兄弟萌埋它' }
<p className="auto-track-inner-text">
兄弟萌埋它
</p>
// 或许会有这种使用场景(有更好的使用方式, 只是为了举例)
<div className="auto-track">
<p>这个点击不会埋</p>
<p className="track-inner-text">
不用auto-track埋不了
</p>
<p className="track-inner-text">
需要搭配auto-track使用
</p>
</div>
baseInfo
通用的上报数据配置
- Type: object;
- Default: { version };
~~默认不包含操作系统相关信息, 可通过使用{ includePlatform: true }
添加相关信息~~
操作系统相关信息统一使用 Nginx 去获取
route (测试功能)
路由变化时触发, 不使用则不需要配置
api
和onChange
二选一, 没有 onChange 会根据 api 自动上报{pathname, time}
type IData = {
pathname: string;
stamp: number;
};
interface IRouteChange {
api?: string; // 上报地址
onChange?: (data: IData) => void; // 路由变化回调
exclude?: string[]; // 不需要采集的pathname
}
track.config({
route: {
api: '', // 上报地址
exclude: ['/'],
},
});
优先级
自动采集
data-auto-track=false
button
,track.classConfig
数据获取
value
data-name
,Elememt.getAttribute('placeholder')
Elememt.getAttribute('title')
Element.getInnerText
待改进
- 数据采集
radio, checkbox 的文字获取采用
nextElementSibling.innerText
获取,依赖 dom 结构考虑是够支持
data-auto-track=true
则自动埋点. (考虑可以通过 classname 配置, 如果支持此功能会有重复)
- 数据上报
普通的数据上报采用 Image Beacon, unload 和 beforeUnLoad 使用
track.sendBeacon
上报接口服务端返回'204 No Content'作为响应,节省服务器资源
LICENSE
ISC
FAQs
- 为什么配置了 classname 不生效?