电商商城定制开发小满 前端埋点SDK 带你 从0 开发 并且发布npm

本章目录

就是 数据采集-数据处理-电商商城定制开发数据分析和挖掘,电商商城定制开发如用户停留时间,电商商城定制开发用户哪个按钮点的多,等

电商商城定制开发技术架构使用ts +

使用ts主要是在编译过程中发现问题,减少生产代码的错误,

使用rollup 应为 rollup打包干净,而webpack非常臃肿,可读性差,所以rollup非常适合开发SDK和一些框架,webpack 适合开发一些项目

1.目录结构设计

 2.安装开发依赖

  1. npm install rollup -D
  2. npm install rollup-plugin-dts -D
  3. npm install rollup-plugin-typescript2 -D
  4. npm install typescript -D

3.配置rollup config js

  1. import ts from 'rollup-plugin-typescript2'
  2. import path from 'path'
  3. import dts from 'rollup-plugin-dts';
  4. export default [{
  5. //入口文件
  6. input: "./src/core/index.ts",
  7. output: [
  8. //打包esModule
  9. {
  10. file: path.resolve(__dirname, './dist/index.esm.js'),
  11. format: "es"
  12. },
  13. //打包common js
  14. {
  15. file: path.resolve(__dirname, './dist/index.cjs.js'),
  16. format: "cjs"
  17. },
  18. //打包 AMD CMD UMD
  19. {
  20. input: "./src/core/index.ts",
  21. file: path.resolve(__dirname, './dist/index.js'),
  22. format: "umd",
  23. name: "tracker"
  24. }
  25. ],
  26. //配置ts
  27. plugins: [
  28. ts(),
  29. ]
  30. }, {
  31. //打包声明文件
  32. input: "./src/core/index.ts",
  33. output:{
  34. file: path.resolve(__dirname, './dist/index.d.ts'),
  35. format: "es",
  36. },
  37. plugins: [dts()]
  38. }]

4. src type 定义类型

  1. /**
  2. * @requestUrl 接口地址
  3. * @historyTracker history上报
  4. * @hashTracker hash上报
  5. * @domTracker 携带Tracker-key 点击事件上报
  6. * @sdkVersionsdk版本
  7. * @extra透传字段
  8. * @jsError js 和 promise 报错异常上报
  9. */
  10. export interface DefaultOptons {
  11. uuid: string | undefined,
  12. requestUrl: string | undefined,
  13. historyTracker: boolean,
  14. hashTracker: boolean,
  15. domTracker: boolean,
  16. sdkVersion: string | number,
  17. extra: Record<string, any> | undefined,
  18. jsError:boolean
  19. }
  20. //必传参数 requestUrl
  21. export interface Options extends Partial<DefaultOptons> {
  22. requestUrl: string,
  23. }
  24. //版本
  25. export enum TrackerConfig {
  26. version = '1.0.0'
  27. }
  28. //上报必传参数
  29. export type reportTrackerData = {
  30. [key: string]: any,
  31. event: string,
  32. targetKey: string
  33. }

5.src core 核心功能

PV:页面访问量,即PageView,用户每次对网站的访问均被记录

主要监听了 history 和 hash

history API  go back  forward pushState  replaceState  

history 无法通过 popstate 监听 pushState replaceState  只能重写其函数 在utils/pv

hash 使用hashchange 监听

UV(独立访客):即Unique Visitor,访问您网站的一台电脑客户端为一个访客

用户唯一表示 可以在登录之后通过接口返回的id 进行设置值 提供了setUserId

也可以使用canvas 指纹追踪技术 

本章重点 navigator.sendBeacon

为什么要使用这个去上报

这个上报的机制 跟 XMLHttrequest 对比  navigator.sendBeacon 即使页面关闭了 也会完成请求 而XMLHTTPRequest 不一定

DOM事件监听

主要是给需要监听的元素添加一个属性 用来区分是否需要监听 target-key

js报错上报 error 事件  promise报错 unhandledrejection

  1. import { DefaultOptons, Options, TrackerConfig, reportTrackerData } from "../types/core";
  2. import { createHistoryEvnent } from "../utils/pv";
  3. const MouseEventList: string[] = ['click', 'dblclick', 'contextmenu', 'mousedown', 'mouseup', 'mouseenter', 'mouseout', 'mouseover']
  4. export default class Tracker {
  5. public data: Options;
  6. private version: string | undefined;
  7. public constructor(options: Options) {
  8. this.data = Object.assign(this.initDef(), options)
  9. this.installInnerTrack()
  10. }
  11. private initDef(): DefaultOptons {
  12. this.version = TrackerConfig.version;
  13. window.history['pushState'] = createHistoryEvnent("pushState")
  14. window.history['replaceState'] = createHistoryEvnent('replaceState')
  15. return <DefaultOptons>{
  16. sdkVersion: this.version,
  17. historyTracker: false,
  18. hashTracker: false,
  19. domTracker: false,
  20. jsError: false
  21. }
  22. }
  23. public setUserId<T extends DefaultOptons['uuid']>(uuid: T) {
  24. this.data.uuid = uuid;
  25. }
  26. public setExtra<T extends DefaultOptons['extra']>(extra: T) {
  27. this.data.extra = extra
  28. }
  29. public sendTracker<T extends reportTrackerData>(data: T) {
  30. this.reportTracker(data)
  31. }
  32. private captureEvents<T>(MouseEventList: string[], targetKey: string, data?: T) {
  33. MouseEventList.forEach(event => {
  34. window.addEventListener(event, () => {
  35. this.reportTracker({ event, targetKey, data })
  36. })
  37. })
  38. }
  39. private installInnerTrack() {
  40. if (this.data.historyTracker) {
  41. this.captureEvents(['pushState'], 'history-pv')
  42. this.captureEvents(['replaceState'], 'history-pv')
  43. this.captureEvents(['popstate'], 'history-pv')
  44. }
  45. if (this.data.hashTracker) {
  46. this.captureEvents(['hashchange'], 'hash-pv')
  47. }
  48. if (this.data.domTracker) {
  49. this.targetKeyReport()
  50. }
  51. if (this.data.jsError) {
  52. this.jsError()
  53. }
  54. }
  55. //dom 点击上报
  56. private targetKeyReport() {
  57. MouseEventList.forEach(event => {
  58. window.addEventListener(event, (e) => {
  59. const target = e.target as HTMLElement
  60. const targetValue = target.getAttribute('target-key')
  61. if (targetValue) {
  62. this.sendTracker({
  63. targetKey: targetValue,
  64. event
  65. })
  66. }
  67. })
  68. })
  69. }
  70. private jsError() {
  71. this.errorEvent()
  72. this.promiseReject()
  73. }
  74. //捕获js报错
  75. private errorEvent() {
  76. window.addEventListener('error', (e) => {
  77. this.sendTracker({
  78. targetKey: 'message',
  79. event: 'error',
  80. message: e.message
  81. })
  82. })
  83. }
  84. //捕获promise 错误
  85. private promiseReject() {
  86. window.addEventListener('unhandledrejection', (event) => {
  87. event.promise.catch(error => {
  88. this.sendTracker({
  89. targetKey: "reject",
  90. event: "promise",
  91. message: error
  92. })
  93. })
  94. })
  95. }
  96. //上报
  97. private reportTracker<T>(data: T) {
  98. const params = Object.assign(this.data, data, { time: new Date().getTime() })
  99. let headers = {
  100. type: 'application/x-www-form-urlencoded'
  101. };
  102. let blob = new Blob([JSON.stringify(params)], headers);
  103. navigator.sendBeacon(this.data.requestUrl, blob)
  104. }
  105. }

6.工具函数 src/utils/pv

  1. export const createHistoryEvnent = <T extends keyof History>(type: T): () => any => {
  2. const origin = history[type];
  3. return function (this: any) {
  4. const res = origin.apply(this, arguments)
  5. var e = new Event(type)
  6. window.dispatchEvent(e)
  7. return res;
  8. }
  9. }

7.设置package json 

main  module 分别设置对应的js文件

files 设置打包之后的目录 我这儿是dist 具体看rollup config .js

  1. {
  2. "name": "zmy-tracker",
  3. "version": "1.0.5",
  4. "description": "",
  5. "main": "dist/index.cjs.js",
  6. "module": "dist/index.esm.js",
  7. "browser":"dist/index.js",
  8. "scripts": {
  9. "test": "echo \"Error: no test specified\" && exit 1",
  10. "build": "rollup -c"
  11. },
  12. "keywords": ["前端","埋点","tracker"],
  13. "author": "",
  14. "files": ["dist"],
  15. "license": "ISC",
  16. "devDependencies": {
  17. "rollup": "^2.76.0",
  18. "rollup-plugin-dts": "^4.2.2",
  19. "rollup-plugin-typescript2": "^0.32.1",
  20. "typescript": "^4.7.4"
  21. }
  22. }

8.发布npm

tips:一定要使用npm 的源  不能使用淘宝镜像 否则 报错403

1.npm adduser

用户名 密码 邮箱 邮箱验证码

2. npm login  

输入刚才的 用户名 密码 邮箱 验证码

3.npm publish 发布

发布的时候403 有可能是名字重复注意一下

 4.npm 官网查看

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发