UNPKG

quanjiecc_sdk_ts

Version:

这是一个使用ts编写,可以用于web开发使用的埋点数据sdk(This is a buried data sdk written in typescript that can be used for web development)

341 lines (333 loc) 11.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.tracker = factory()); })(this, (function () { 'use strict'; var TrackerConfig; (function (TrackerConfig) { TrackerConfig["version"] = "1.1.0"; })(TrackerConfig || (TrackerConfig = {})); /* * @Author: quanjie * @Date: 2022-10-25 16:40:10 * @LastEditTime: 2022-10-25 18:06:43 * @LastEditors: quanjie * @Description: * @FilePath: /quanjiecc_sdk_ts/src/utils/brower.ts * 可以输入预定的版权声明、个性签名、空行等 */ // 获取浏览器类型 const getBrowserType = () => { // 获取浏览器 userAgent var ua = navigator.userAgent; // 是否为 Opera var isOpera = ua.indexOf('Opera') > -1; // 返回结果 if (isOpera) { return 'Opera'; } // 是否为 IE var isIE = (ua.indexOf('compatible') > -1) && (ua.indexOf('MSIE') > -1) && !isOpera; var isIE11 = (ua.indexOf('Trident') > -1) && (ua.indexOf("rv:11.0") > -1); // 返回结果 if (isIE11) { return 'IE11'; } else if (isIE) { // 检测是否匹配 var re = new RegExp('MSIE (\\d+\\.\\d+);'); re.test(ua); // 获取版本 var ver = parseFloat(RegExp["$1"]); // 返回结果 if (ver == 7) { return 'IE7'; } else if (ver == 8) { return 'IE8'; } else if (ver == 9) { return 'IE9'; } else if (ver == 10) { return 'IE10'; } else { return "IE"; } } // 是否为 Edge var isEdge = ua.indexOf("Edge") > -1; // 返回结果 if (isEdge) { return 'Edge'; } // 是否为 Firefox var isFirefox = ua.indexOf("Firefox") > -1; // 返回结果 if (isFirefox) { return 'Firefox'; } // 是否为 Safari var isSafari = (ua.indexOf("Safari") > -1) && (ua.indexOf("Chrome") == -1); // 返回结果 if (isSafari) { return "Safari"; } // 是否为 Chrome var isChrome = (ua.indexOf("Chrome") > -1) && (ua.indexOf("Safari") > -1) && (ua.indexOf("Edge") == -1); // 返回结果 if (isChrome) { return 'Chrome'; } // 是否为 UC var isUC = ua.indexOf("UBrowser") > -1; // 返回结果 if (isUC) { return 'UC'; } // 是否为 QQ ua.indexOf("QQBrowser") > -1; // 返回结果 if (isUC) { return 'QQ'; } // 都不是 return ''; }; // string function getLocalItem(key) { return localStorage.getItem(key); } // json function getLocalJson(key) { if (getLocalItem(key)) { return JSON.parse(getLocalItem(key) || ""); } else { return null; } } function setLocalItem(key, value) { localStorage.setItem(key, value); } const uuid_key = "sdk_uuid"; // 生成匿名id function getDistinctID() { // UUID格式 const distinct_id = getLocalItem(uuid_key); if (distinct_id) { return distinct_id; } else { let distinct_id = distinctID(); setLocalItem(uuid_key, distinct_id); return distinct_id; } } // 获取用户id function getUserID() { if (getLocalJson("userinfo")) { return getLocalJson("userinfo").id; } } // 生成匿名id function distinctID() { var d = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(36); }); return String(uuid); } // 获取session_id,没有生成一个 function getSessionID() { // UUID格式 const uuid_key = "sdk_sessionid"; const session_id = window.sessionStorage.getItem(uuid_key); if (session_id) { return session_id; } else { let session_id = uuid(10, 48); window.sessionStorage.setItem(uuid_key, session_id); return session_id; } } // 判断session是否存在 function flagHadSessionID() { // UUID格式 const uuid_key = "sdk_sessionid"; const session_id = window.sessionStorage.getItem(uuid_key); if (session_id) { return true; } else { return false; // 没有sessionid } } /** * @len:生成的uuid长度 * @radix:使用字符串的基数 **/ function uuid(len, radix) { var chars = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); var uuid = [], i; radix = radix || chars.length; if (len) { // Compact form for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]; } else { // rfc4122, version 4 form var r; // rfc4122 requires these characters uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; uuid[14] = '4'; // Fill in random data. At i==19 set the high bits of clock sequence as // per rfc4122, sec. 4.1.5 for (i = 0; i < 36; i++) { if (!uuid[i]) { r = 0 | Math.random() * 16; uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]; } } } return uuid.join(''); } const createHistoryEvnent = (type) => { const origin = history[type]; return function () { const res = origin.apply(this, arguments); var e = new Event(type); window.dispatchEvent(e); return res; }; }; const MouseEventList = ['click', 'dblclick', 'contextmenu', 'mousedown', 'mouseup', 'mouseenter', 'mouseout', 'mouseover']; class Tracker { // 初始化参数 constructor(options) { this.data = Object.assign(this.initDef(), options); this.installInnerTrack(); // 保证一次会话只有一个startApp事件 if (!flagHadSessionID()) { this.track("startApp"); } } initDef() { this.version = TrackerConfig.version; window.history['pushState'] = createHistoryEvnent("pushState"); window.history['replaceState'] = createHistoryEvnent('replaceState'); return { sdkVersion: this.version, historyTracker: false, hashTracker: false, domTracker: false, jsError: false }; } setUserId(user_id) { this.data.user_id = user_id; } /** * track * @event: 事件名称 * @property: 事件属性 */ track(event, property) { this.sendTracker(event, '', property); } // 手动触发发送操作 /** * 手动触发发送操作2 * */ sendTracker(event, targetKey, property) { // 添加系统预置属性 if (!property) { property = {}; } // 网页的宽度 property['bi_web_client_width'] = document.body.clientWidth; property["bi_web_client_height"] = document.body.clientHeight; // 浏览器名称 property["bi_browser_name"] = navigator.appName; property["bi_browser_version"] = navigator.appVersion; property["bi_browser_userAgent"] = navigator.userAgent; property["bi_browser_type"] = getBrowserType(); property["_from_uri"] = window.location.pathname; this.reportTracker({ event: event, property: property }); } captureEvents(MouseEventList, targetKey, data) { MouseEventList.forEach(event => { window.addEventListener(event, () => { this.sendTracker(event, targetKey, data); }); }); } // 发送数据 reportTracker(data) { const params = Object.assign(data, { event: data.event, session_id: getSessionID(), user_id: this.data.user_id || getUserID(), distinct_id: getDistinctID(), create_time: new Date(), property: data.property, }); let headers = { type: 'application/x-www-form-urlencoded' }; let blob = new Blob([JSON.stringify(params)], headers); navigator.sendBeacon(this.data.requestUrl, blob); } installInnerTrack() { if (this.data.historyTracker) { this.captureEvents(['pushState'], 'history-pv'); this.captureEvents(['replaceState'], 'history-pv'); this.captureEvents(['popstate'], 'history-pv'); } if (this.data.hashTracker) { this.captureEvents(['hashchange'], 'hash-pv'); } if (this.data.domTracker) { this.targetKeyReport(); } if (this.data.jsError) { this.jsError(); } } // dom操作上报 targetKeyReport() { MouseEventList.forEach(event => { window.addEventListener(event, (e) => { const target = e.target; const targetValue = target.getAttribute('target-key'); if (targetValue) { this.sendTracker(event, targetValue); } }); }); } jsError() { this.errorEvent(); this.promiseReject(); } errorEvent() { window.addEventListener('error', (e) => { this.sendTracker("error", "message", { message: e.message }); }); } promiseReject() { window.addEventListener('unhandledrejection', (event) => { event.promise.catch(error => { this.sendTracker("promise", "reject", { message: error }); }); }); } } return Tracker; }));