quanjiecc_sdk_ts
Version:
这是一个使用ts编写,可以用于web开发使用的埋点数据sdk(This is a buried data sdk written in typescript that can be used for web development)
335 lines (328 loc) • 9.76 kB
JavaScript
'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 });
});
});
}
}
module.exports = Tracker;