@fle-sdk/event-tracking-web 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.esm.js +1319 -1535
- package/lib/index.esm.min.js +1 -1
- package/lib/index.js +1319 -1535
- package/lib/index.min.js +1 -1
- package/lib/types/batch-sender.d.ts +50 -0
- package/lib/types/device-manager.d.ts +16 -0
- package/lib/types/exposure.d.ts +33 -0
- package/lib/types/index.d.ts +17 -225
- package/lib/types/page-duration.d.ts +23 -0
- package/lib/types/pending-requests.d.ts +45 -0
- package/lib/types/tools.d.ts +0 -15
- package/lib/types/type.d.ts +34 -18
- package/package.json +1 -1
package/lib/index.esm.js
CHANGED
|
@@ -865,11 +865,7 @@ function () {
|
|
|
865
865
|
|
|
866
866
|
fingerprint.canvas = _this.getCanvasFingerprint(); // 8. 音频上下文指纹
|
|
867
867
|
|
|
868
|
-
fingerprint.audio = _this.getAudioFingerprint(); //
|
|
869
|
-
|
|
870
|
-
fingerprint.fonts = _this.getFontFingerprint(); // 10. 插件信息
|
|
871
|
-
|
|
872
|
-
fingerprint.plugins = _this.getPluginsFingerprint(); // 11. 存储检测
|
|
868
|
+
fingerprint.audio = _this.getAudioFingerprint(); // 11. 存储检测
|
|
873
869
|
|
|
874
870
|
fingerprint.localStorage = _this.hasLocalStorage();
|
|
875
871
|
fingerprint.sessionStorage = _this.hasSessionStorage();
|
|
@@ -877,9 +873,7 @@ function () {
|
|
|
877
873
|
|
|
878
874
|
fingerprint.hardwareConcurrency = navigator.hardwareConcurrency;
|
|
879
875
|
fingerprint.deviceMemory = navigator.deviceMemory;
|
|
880
|
-
fingerprint.maxTouchPoints = navigator.maxTouchPoints;
|
|
881
|
-
|
|
882
|
-
fingerprint.connection = _this.getConnectionFingerprint();
|
|
876
|
+
fingerprint.maxTouchPoints = navigator.maxTouchPoints;
|
|
883
877
|
return fingerprint;
|
|
884
878
|
};
|
|
885
879
|
/**
|
|
@@ -951,75 +945,6 @@ function () {
|
|
|
951
945
|
return "error";
|
|
952
946
|
}
|
|
953
947
|
};
|
|
954
|
-
/**
|
|
955
|
-
* 获取字体指纹
|
|
956
|
-
* @returns 字体指纹字符串
|
|
957
|
-
*/
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
this.getFontFingerprint = function () {
|
|
961
|
-
try {
|
|
962
|
-
var baseFonts_1 = ["monospace", "sans-serif", "serif"];
|
|
963
|
-
var testString_1 = "mmmmmmmmmmlli";
|
|
964
|
-
var testSize_1 = "72px";
|
|
965
|
-
var canvas = document.createElement("canvas");
|
|
966
|
-
var ctx_1 = canvas.getContext("2d");
|
|
967
|
-
if (!ctx_1) return "not-supported";
|
|
968
|
-
var detectedFonts_1 = []; // 测试字体列表
|
|
969
|
-
|
|
970
|
-
var fonts = ["Arial", "Arial Black", "Comic Sans MS", "Courier New", "Georgia", "Helvetica", "Impact", "Times New Roman", "Trebuchet MS", "Verdana"]; // 获取基准宽度
|
|
971
|
-
|
|
972
|
-
var baseWidths_1 = {};
|
|
973
|
-
baseFonts_1.forEach(function (font) {
|
|
974
|
-
ctx_1.font = testSize_1 + " " + font;
|
|
975
|
-
baseWidths_1[font] = ctx_1.measureText(testString_1).width;
|
|
976
|
-
}); // 测试每个字体
|
|
977
|
-
|
|
978
|
-
fonts.forEach(function (font) {
|
|
979
|
-
var detected = false;
|
|
980
|
-
baseFonts_1.forEach(function (baseFont) {
|
|
981
|
-
ctx_1.font = testSize_1 + " '" + font + "', " + baseFont;
|
|
982
|
-
var width = ctx_1.measureText(testString_1).width;
|
|
983
|
-
|
|
984
|
-
if (width !== baseWidths_1[baseFont]) {
|
|
985
|
-
detected = true;
|
|
986
|
-
}
|
|
987
|
-
});
|
|
988
|
-
|
|
989
|
-
if (detected) {
|
|
990
|
-
detectedFonts_1.push(font);
|
|
991
|
-
}
|
|
992
|
-
});
|
|
993
|
-
return detectedFonts_1.join(",");
|
|
994
|
-
} catch (e) {
|
|
995
|
-
return "error";
|
|
996
|
-
}
|
|
997
|
-
};
|
|
998
|
-
/**
|
|
999
|
-
* 获取插件指纹
|
|
1000
|
-
* @returns 插件指纹字符串
|
|
1001
|
-
*/
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
this.getPluginsFingerprint = function () {
|
|
1005
|
-
try {
|
|
1006
|
-
var plugins = [];
|
|
1007
|
-
|
|
1008
|
-
if (navigator.plugins) {
|
|
1009
|
-
for (var i = 0; i < navigator.plugins.length; i++) {
|
|
1010
|
-
var plugin = navigator.plugins[i];
|
|
1011
|
-
|
|
1012
|
-
if (plugin) {
|
|
1013
|
-
plugins.push(plugin.name + "|" + plugin.description + "|" + plugin.filename);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
return plugins.join(";");
|
|
1019
|
-
} catch (e) {
|
|
1020
|
-
return "error";
|
|
1021
|
-
}
|
|
1022
|
-
};
|
|
1023
948
|
/**
|
|
1024
949
|
* 检测localStorage支持
|
|
1025
950
|
* @returns 是否支持localStorage
|
|
@@ -1061,22 +986,6 @@ function () {
|
|
|
1061
986
|
this.hasIndexedDB = function () {
|
|
1062
987
|
return "indexedDB" in window && indexedDB !== null;
|
|
1063
988
|
};
|
|
1064
|
-
/**
|
|
1065
|
-
* 获取网络连接指纹
|
|
1066
|
-
* @returns 网络连接指纹字符串
|
|
1067
|
-
*/
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
this.getConnectionFingerprint = function () {
|
|
1071
|
-
try {
|
|
1072
|
-
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
|
|
1073
|
-
if (!connection) return "not-supported"; // 只使用稳定的 effectiveType,不使用 downlink 和 rtt(会随网络状态变化导致指纹不一致)
|
|
1074
|
-
|
|
1075
|
-
return connection.effectiveType || "unknown";
|
|
1076
|
-
} catch (e) {
|
|
1077
|
-
return "error";
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
989
|
/**
|
|
1081
990
|
* 将指纹信息哈希为唯一ID
|
|
1082
991
|
* @param fingerprint 指纹信息
|
|
@@ -1230,1505 +1139,1579 @@ function () {
|
|
|
1230
1139
|
return WebTrackingTools;
|
|
1231
1140
|
}();
|
|
1232
1141
|
|
|
1233
|
-
var
|
|
1142
|
+
var ExposureTracker =
|
|
1234
1143
|
/** @class */
|
|
1235
|
-
function (
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1144
|
+
function () {
|
|
1145
|
+
function ExposureTracker(config, callbacks) {
|
|
1146
|
+
this.observer = null;
|
|
1147
|
+
this.mutationObserver = null;
|
|
1148
|
+
this.elementsMap = new Map();
|
|
1149
|
+
this.config = config;
|
|
1150
|
+
this.callbacks = callbacks;
|
|
1151
|
+
}
|
|
1241
1152
|
|
|
1242
|
-
|
|
1153
|
+
ExposureTracker.prototype.updateConfig = function (config) {
|
|
1154
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1155
|
+
};
|
|
1243
1156
|
|
|
1244
|
-
|
|
1157
|
+
ExposureTracker.prototype.init = function () {
|
|
1158
|
+
var _this = this;
|
|
1245
1159
|
|
|
1246
|
-
|
|
1160
|
+
if (!this.config.autoTrackExposure) {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1247
1163
|
|
|
1248
|
-
|
|
1164
|
+
if (!("IntersectionObserver" in window)) {
|
|
1165
|
+
if (this.config.showLog) {
|
|
1166
|
+
this.callbacks.printLog("当前浏览器不支持 IntersectionObserver,无法启用曝光埋点");
|
|
1167
|
+
}
|
|
1249
1168
|
|
|
1250
|
-
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1251
1171
|
|
|
1252
|
-
|
|
1172
|
+
this.observer = new IntersectionObserver(function (entries) {
|
|
1173
|
+
entries.forEach(function (entry) {
|
|
1174
|
+
var element = entry.target;
|
|
1253
1175
|
|
|
1254
|
-
|
|
1176
|
+
var elementInfo = _this.elementsMap.get(element);
|
|
1255
1177
|
|
|
1256
|
-
|
|
1178
|
+
if (!elementInfo) {
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1257
1181
|
|
|
1258
|
-
|
|
1182
|
+
var exposureTime = _this.config.exposureTime || 500;
|
|
1259
1183
|
|
|
1260
|
-
|
|
1184
|
+
if (entry.isIntersecting) {
|
|
1185
|
+
elementInfo.isVisible = true;
|
|
1186
|
+
elementInfo.visibleStartTime = _this.callbacks.getTimeStamp();
|
|
1261
1187
|
|
|
1262
|
-
|
|
1188
|
+
if (elementInfo.exposureTimer) {
|
|
1189
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1190
|
+
}
|
|
1263
1191
|
|
|
1264
|
-
|
|
1192
|
+
elementInfo.exposureTimer = window.setTimeout(function () {
|
|
1193
|
+
if (elementInfo.isVisible) {
|
|
1194
|
+
var exposureScreenIndex = _this.calculateexposureScreenIndex(element);
|
|
1265
1195
|
|
|
1266
|
-
|
|
1196
|
+
_this.callbacks.reportExposure(element, exposureScreenIndex);
|
|
1197
|
+
}
|
|
1198
|
+
}, exposureTime);
|
|
1199
|
+
} else {
|
|
1200
|
+
elementInfo.isVisible = false;
|
|
1267
1201
|
|
|
1268
|
-
|
|
1202
|
+
if (elementInfo.exposureTimer) {
|
|
1203
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1204
|
+
elementInfo.exposureTimer = null;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
}, {
|
|
1209
|
+
threshold: this.config.exposureThreshold || 0.5
|
|
1210
|
+
});
|
|
1211
|
+
this.observeExposureElements();
|
|
1212
|
+
this.initMutationObserver();
|
|
1213
|
+
};
|
|
1269
1214
|
|
|
1270
|
-
|
|
1215
|
+
ExposureTracker.prototype.stop = function () {
|
|
1216
|
+
if (this.observer) {
|
|
1217
|
+
this.observer.disconnect();
|
|
1218
|
+
this.observer = null;
|
|
1219
|
+
this.elementsMap.forEach(function (elementInfo) {
|
|
1220
|
+
if (elementInfo.exposureTimer) {
|
|
1221
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1222
|
+
}
|
|
1223
|
+
});
|
|
1224
|
+
this.elementsMap.clear();
|
|
1225
|
+
}
|
|
1271
1226
|
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
CustomTrack: "Web 自定义代码上报",
|
|
1277
|
-
WebExposure: "Web 元素曝光"
|
|
1278
|
-
};
|
|
1279
|
-
/**
|
|
1280
|
-
* @description 初始化函数
|
|
1281
|
-
* @param {object} InitParams [初始化参数]
|
|
1282
|
-
*/
|
|
1227
|
+
if (this.mutationObserver) {
|
|
1228
|
+
this.mutationObserver.disconnect();
|
|
1229
|
+
this.mutationObserver = null;
|
|
1230
|
+
}
|
|
1283
1231
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1232
|
+
if (this.config.showLog) {
|
|
1233
|
+
this.callbacks.printLog("曝光监听已停止");
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1286
1236
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1237
|
+
ExposureTracker.prototype.addExposureElement = function (element) {
|
|
1238
|
+
if (!this.elementsMap.has(element)) {
|
|
1239
|
+
this.elementsMap.set(element, {
|
|
1240
|
+
element: element,
|
|
1241
|
+
visibleStartTime: 0,
|
|
1242
|
+
exposureCount: 0,
|
|
1243
|
+
isVisible: false,
|
|
1244
|
+
exposureTimer: null
|
|
1245
|
+
});
|
|
1289
1246
|
|
|
1290
|
-
if (
|
|
1291
|
-
|
|
1292
|
-
_this.useCustomPageKey = true;
|
|
1293
|
-
} else {
|
|
1294
|
-
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
1295
|
-
_this.useCustomPageKey = false;
|
|
1247
|
+
if (this.observer) {
|
|
1248
|
+
this.observer.observe(element);
|
|
1296
1249
|
}
|
|
1250
|
+
}
|
|
1251
|
+
};
|
|
1297
1252
|
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
_this.deviceId = _this.getDeviceId(); // 如果传入了 userInfo,设置用户信息
|
|
1253
|
+
ExposureTracker.prototype.observeExposureElements = function () {
|
|
1254
|
+
var _this = this;
|
|
1301
1255
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1256
|
+
if (!this.observer) {
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1305
1259
|
|
|
1306
|
-
|
|
1260
|
+
var elements = document.querySelectorAll('[data-exposure="true"]');
|
|
1261
|
+
elements.forEach(function (element) {
|
|
1262
|
+
_this.addExposureElement(element);
|
|
1263
|
+
});
|
|
1307
1264
|
|
|
1265
|
+
if (this.config.showLog && elements.length > 0) {
|
|
1266
|
+
this.callbacks.printLog("\u5DF2\u76D1\u542C " + elements.length + " \u4E2A\u66DD\u5149\u5143\u7D20");
|
|
1267
|
+
}
|
|
1308
1268
|
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1269
|
+
if (!document.body) {
|
|
1270
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
1271
|
+
var deferredElements = document.querySelectorAll('[data-exposure="true"]');
|
|
1272
|
+
deferredElements.forEach(function (element) {
|
|
1273
|
+
_this.addExposureElement(element);
|
|
1274
|
+
});
|
|
1312
1275
|
|
|
1276
|
+
if (_this.config.showLog && deferredElements.length > 0) {
|
|
1277
|
+
_this.callbacks.printLog("DOMContentLoaded \u540E\u76D1\u542C " + deferredElements.length + " \u4E2A\u66DD\u5149\u5143\u7D20");
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1313
1282
|
|
|
1314
|
-
|
|
1283
|
+
ExposureTracker.prototype.initMutationObserver = function () {
|
|
1284
|
+
var _this = this;
|
|
1315
1285
|
|
|
1286
|
+
if (!("MutationObserver" in window)) {
|
|
1287
|
+
if (this.config.showLog) {
|
|
1288
|
+
this.callbacks.printLog("当前浏览器不支持 MutationObserver,无法监听动态添加的曝光元素");
|
|
1289
|
+
}
|
|
1316
1290
|
|
|
1317
|
-
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1318
1293
|
|
|
1294
|
+
this.mutationObserver = new MutationObserver(function (mutations) {
|
|
1295
|
+
mutations.forEach(function (mutation) {
|
|
1296
|
+
mutation.addedNodes.forEach(function (node) {
|
|
1297
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1298
|
+
var element = node;
|
|
1319
1299
|
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1300
|
+
if (element.hasAttribute("data-exposure") && element.getAttribute("data-exposure") === "true") {
|
|
1301
|
+
_this.addExposureElement(element);
|
|
1302
|
+
} else {
|
|
1303
|
+
var exposureElements = element.querySelectorAll('[data-exposure="true"]');
|
|
1304
|
+
exposureElements.forEach(function (exposureElement) {
|
|
1305
|
+
_this.addExposureElement(exposureElement);
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
});
|
|
1311
|
+
});
|
|
1323
1312
|
|
|
1313
|
+
if (document.body) {
|
|
1314
|
+
this.mutationObserver.observe(document.body, {
|
|
1315
|
+
childList: true,
|
|
1316
|
+
subtree: true
|
|
1317
|
+
});
|
|
1324
1318
|
|
|
1325
|
-
if (
|
|
1326
|
-
|
|
1319
|
+
if (this.config.showLog) {
|
|
1320
|
+
this.callbacks.printLog("MutationObserver 已启动,监听动态添加的曝光元素");
|
|
1327
1321
|
}
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1322
|
+
} else {
|
|
1323
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
1324
|
+
if (_this.mutationObserver && document.body) {
|
|
1325
|
+
_this.mutationObserver.observe(document.body, {
|
|
1326
|
+
childList: true,
|
|
1327
|
+
subtree: true
|
|
1328
|
+
});
|
|
1334
1329
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
// 处理 pageKey 特殊逻辑
|
|
1338
|
-
if (presetParams.pageKey !== undefined) {
|
|
1339
|
-
if (presetParams.pageKey === null || presetParams.pageKey === '') {
|
|
1340
|
-
// 恢复自动生成
|
|
1341
|
-
_this.useCustomPageKey = false;
|
|
1342
|
-
var pathname = window.location.pathname;
|
|
1343
|
-
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
1344
|
-
} else {
|
|
1345
|
-
_this.pageKey = presetParams.pageKey;
|
|
1346
|
-
_this.useCustomPageKey = true;
|
|
1330
|
+
if (_this.config.showLog) {
|
|
1331
|
+
_this.callbacks.printLog("MutationObserver 已启动,监听动态添加的曝光元素");
|
|
1347
1332
|
}
|
|
1348
1333
|
}
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1349
1337
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1338
|
+
ExposureTracker.prototype.calculateexposureScreenIndex = function (element) {
|
|
1339
|
+
var rect = element.getBoundingClientRect();
|
|
1340
|
+
var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
1341
|
+
var scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
1342
|
+
var elementPageTop = rect.top + scrollTop;
|
|
1353
1343
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1344
|
+
if (elementPageTop <= 0) {
|
|
1345
|
+
return 1;
|
|
1346
|
+
}
|
|
1357
1347
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
} else {
|
|
1361
|
-
_this.printLog("\u914D\u7F6E\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25: " + String(key) + " = " + val + ", \u539F\u56E0: " + validationResult.message);
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
});
|
|
1365
|
-
}
|
|
1348
|
+
return Math.ceil(elementPageTop / viewportHeight);
|
|
1349
|
+
};
|
|
1366
1350
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1351
|
+
ExposureTracker.prototype.getElementInfo = function (element) {
|
|
1352
|
+
return this.elementsMap.get(element);
|
|
1353
|
+
};
|
|
1369
1354
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1355
|
+
ExposureTracker.prototype.incrementExposureCount = function (element) {
|
|
1356
|
+
var elementInfo = this.elementsMap.get(element);
|
|
1372
1357
|
|
|
1358
|
+
if (elementInfo) {
|
|
1359
|
+
elementInfo.exposureCount++;
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1373
1362
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
_this.listener();
|
|
1377
|
-
} else {
|
|
1378
|
-
// 取消监听
|
|
1379
|
-
_this.unlistener();
|
|
1380
|
-
} // 处理定时上报配置
|
|
1363
|
+
ExposureTracker.prototype.clearExposureTimer = function (element) {
|
|
1364
|
+
var elementInfo = this.elementsMap.get(element);
|
|
1381
1365
|
|
|
1366
|
+
if (elementInfo && elementInfo.exposureTimer) {
|
|
1367
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1368
|
+
elementInfo.exposureTimer = null;
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1382
1371
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
} else {
|
|
1386
|
-
_this.stopPageDurationTimer();
|
|
1387
|
-
} // 处理曝光监听配置
|
|
1372
|
+
return ExposureTracker;
|
|
1373
|
+
}();
|
|
1388
1374
|
|
|
1375
|
+
var PageDurationTracker =
|
|
1376
|
+
/** @class */
|
|
1377
|
+
function () {
|
|
1378
|
+
function PageDurationTracker(config, callbacks) {
|
|
1379
|
+
this.timer = null;
|
|
1380
|
+
this.config = config;
|
|
1381
|
+
this.callbacks = callbacks;
|
|
1382
|
+
}
|
|
1389
1383
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
_this.stopExposureObserver();
|
|
1394
|
-
}
|
|
1395
|
-
};
|
|
1396
|
-
/**
|
|
1397
|
-
* @description 验证配置参数
|
|
1398
|
-
* @param key 参数名
|
|
1399
|
-
* @param value 参数值
|
|
1400
|
-
* @returns 验证结果
|
|
1401
|
-
*/
|
|
1384
|
+
PageDurationTracker.prototype.updateConfig = function (config) {
|
|
1385
|
+
var oldInterval = this.config.pageDurationInterval;
|
|
1386
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1402
1387
|
|
|
1388
|
+
if (config.pageDurationInterval !== undefined && config.pageDurationInterval !== oldInterval && this.timer !== null) {
|
|
1389
|
+
this.stop();
|
|
1390
|
+
this.start();
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1403
1393
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
case 'sampleRate':
|
|
1407
|
-
if (typeof value !== 'number' || value < 0 || value > 1) {
|
|
1408
|
-
return {
|
|
1409
|
-
valid: false,
|
|
1410
|
-
message: 'sampleRate 必须是 0-1 之间的数字'
|
|
1411
|
-
};
|
|
1412
|
-
}
|
|
1394
|
+
PageDurationTracker.prototype.start = function () {
|
|
1395
|
+
var _this = this;
|
|
1413
1396
|
|
|
1414
|
-
|
|
1397
|
+
this.stop();
|
|
1398
|
+
var interval = this.config.pageDurationInterval || 30000;
|
|
1415
1399
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
message: 'sendTimeout 必须是大于 0 的数字'
|
|
1421
|
-
};
|
|
1422
|
-
}
|
|
1400
|
+
if (interval <= 0) {
|
|
1401
|
+
if (this.config.showLog) {
|
|
1402
|
+
this.callbacks.printLog("定时上报间隔时间无效,已禁用定时上报");
|
|
1403
|
+
}
|
|
1423
1404
|
|
|
1424
|
-
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1425
1407
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1408
|
+
this.timer = window.setInterval(function () {
|
|
1409
|
+
if (document.visibilityState === "visible") {
|
|
1410
|
+
_this.callbacks.track(interval, {
|
|
1411
|
+
desc: "定时上报页面停留时长"
|
|
1412
|
+
}, true).catch(function (err) {
|
|
1413
|
+
if (_this.config.showLog) {
|
|
1414
|
+
_this.callbacks.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5931\u8D25: " + err);
|
|
1432
1415
|
}
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
}, interval);
|
|
1433
1419
|
|
|
1434
|
-
|
|
1420
|
+
if (this.config.showLog) {
|
|
1421
|
+
this.callbacks.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694: " + interval + "ms");
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1435
1424
|
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
message: 'batchMaxSize 必须是大于 0 的整数'
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1425
|
+
PageDurationTracker.prototype.stop = function () {
|
|
1426
|
+
if (this.timer !== null) {
|
|
1427
|
+
clearInterval(this.timer);
|
|
1428
|
+
this.timer = null;
|
|
1443
1429
|
|
|
1444
|
-
|
|
1430
|
+
if (this.config.showLog) {
|
|
1431
|
+
this.callbacks.printLog("定时上报页面停留时长已停止");
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
};
|
|
1445
1435
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
message: 'pendingRequestsMaxSize 必须是大于 0 的整数'
|
|
1451
|
-
};
|
|
1452
|
-
}
|
|
1436
|
+
PageDurationTracker.prototype.calculateDuration = function (customDuration) {
|
|
1437
|
+
if (customDuration !== undefined && customDuration !== null) {
|
|
1438
|
+
return Math.max(customDuration, 0);
|
|
1439
|
+
}
|
|
1453
1440
|
|
|
1454
|
-
|
|
1441
|
+
var time = this.callbacks.getCookie("retainedStartTime");
|
|
1442
|
+
var retainedStartTime = time ? +time : this.callbacks.getTimeStamp();
|
|
1443
|
+
var currentTime = this.callbacks.getTimeStamp();
|
|
1444
|
+
return Math.max(currentTime - retainedStartTime, 0);
|
|
1445
|
+
};
|
|
1455
1446
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
return {
|
|
1459
|
-
valid: false,
|
|
1460
|
-
message: 'pageDurationInterval 必须是大于 0 的数字'
|
|
1461
|
-
};
|
|
1462
|
-
}
|
|
1447
|
+
return PageDurationTracker;
|
|
1448
|
+
}();
|
|
1463
1449
|
|
|
1464
|
-
|
|
1450
|
+
var BATCH_QUEUE_STORAGE_KEY = "web_tracking_batch_queue";
|
|
1451
|
+
var MAX_STORAGE_SIZE = 4 * 1024 * 1024;
|
|
1465
1452
|
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1453
|
+
var BatchSender =
|
|
1454
|
+
/** @class */
|
|
1455
|
+
function () {
|
|
1456
|
+
function BatchSender(config, callbacks) {
|
|
1457
|
+
this.timer = null;
|
|
1458
|
+
this.isFlushingQueue = false;
|
|
1459
|
+
this.config = config;
|
|
1460
|
+
this.callbacks = callbacks;
|
|
1461
|
+
}
|
|
1473
1462
|
|
|
1474
|
-
|
|
1463
|
+
BatchSender.prototype.start = function () {
|
|
1464
|
+
var _this = this;
|
|
1475
1465
|
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
valid: false,
|
|
1480
|
-
message: 'exposureThreshold 必须是 0-1 之间的数字'
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1466
|
+
if (!this.config.batchSend) {
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1483
1469
|
|
|
1484
|
-
|
|
1470
|
+
this.clearTimer();
|
|
1471
|
+
this.timer = window.setInterval(function () {
|
|
1472
|
+
_this.flushQueue();
|
|
1473
|
+
}, this.config.batchInterval);
|
|
1474
|
+
};
|
|
1485
1475
|
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1476
|
+
BatchSender.prototype.updateConfig = function (config) {
|
|
1477
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1478
|
+
this.clearTimer();
|
|
1479
|
+
this.start();
|
|
1480
|
+
};
|
|
1493
1481
|
|
|
1494
|
-
|
|
1482
|
+
BatchSender.prototype.addToQueue = function (params) {
|
|
1483
|
+
if (!this.config.batchSend) {
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1495
1486
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
message: 'exposureNum 必须是大于 0 的整数或不限制'
|
|
1501
|
-
};
|
|
1502
|
-
}
|
|
1487
|
+
if (!this.callbacks.shouldSample()) {
|
|
1488
|
+
if (this.config.showLog) {
|
|
1489
|
+
this.callbacks.printLog("数据已采样跳过(批量模式)");
|
|
1490
|
+
}
|
|
1503
1491
|
|
|
1504
|
-
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1505
1494
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
case 'batchSend':
|
|
1510
|
-
case 'trackPartKeyClick':
|
|
1511
|
-
case 'autoTrackPageDurationInterval':
|
|
1512
|
-
if (typeof value !== 'boolean') {
|
|
1513
|
-
return {
|
|
1514
|
-
valid: false,
|
|
1515
|
-
message: key + " \u5FC5\u987B\u662F\u5E03\u5C14\u503C"
|
|
1516
|
-
};
|
|
1517
|
-
}
|
|
1495
|
+
var currentQueue = this.getQueueFromStorage();
|
|
1496
|
+
currentQueue.push(params);
|
|
1497
|
+
this.saveQueueToStorage(currentQueue);
|
|
1518
1498
|
|
|
1519
|
-
|
|
1499
|
+
if (currentQueue.length >= this.config.batchMaxSize) {
|
|
1500
|
+
this.flushQueue();
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1520
1504
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
};
|
|
1528
|
-
}
|
|
1505
|
+
BatchSender.prototype.clearTimer = function () {
|
|
1506
|
+
if (this.timer !== null) {
|
|
1507
|
+
clearInterval(this.timer);
|
|
1508
|
+
this.timer = null;
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1529
1511
|
|
|
1530
|
-
|
|
1512
|
+
BatchSender.prototype.clearQueue = function () {
|
|
1513
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, "[]");
|
|
1531
1514
|
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
message: 'contentType 必须是 application/json 或 application/x-www-form-urlencoded'
|
|
1537
|
-
};
|
|
1538
|
-
}
|
|
1515
|
+
if (this.config.showLog) {
|
|
1516
|
+
this.callbacks.printLog("批量队列已清空");
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1539
1519
|
|
|
1540
|
-
|
|
1520
|
+
BatchSender.prototype.restoreQueue = function () {
|
|
1521
|
+
var queue = this.getQueueFromStorage();
|
|
1541
1522
|
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
message: 'platform 必须是字符串'
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1523
|
+
if (queue.length > 0 && this.config.showLog) {
|
|
1524
|
+
this.callbacks.printLog("\u4ECE LocalStorage \u6062\u590D " + queue.length + " \u6761\u6279\u91CF\u6570\u636E");
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1549
1527
|
|
|
1550
|
-
|
|
1551
|
-
|
|
1528
|
+
BatchSender.prototype.getQueueFromStorage = function () {
|
|
1529
|
+
try {
|
|
1530
|
+
var storedQueue = this.callbacks.getLocalStorage(BATCH_QUEUE_STORAGE_KEY);
|
|
1552
1531
|
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
};
|
|
1556
|
-
};
|
|
1557
|
-
/**
|
|
1558
|
-
* 用户登录
|
|
1559
|
-
*/
|
|
1532
|
+
if (storedQueue) {
|
|
1533
|
+
var parsedQueue = JSON.parse(storedQueue);
|
|
1560
1534
|
|
|
1535
|
+
if (Array.isArray(parsedQueue)) {
|
|
1536
|
+
return parsedQueue;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
} catch (e) {
|
|
1540
|
+
this.callbacks.printLog("\u8BFB\u53D6\u6279\u91CF\u961F\u5217\u5931\u8D25: " + e);
|
|
1541
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, "[]");
|
|
1542
|
+
}
|
|
1561
1543
|
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
};
|
|
1565
|
-
/**
|
|
1566
|
-
* 获取设备唯一标识
|
|
1567
|
-
* @returns 设备唯一标识
|
|
1568
|
-
*/
|
|
1544
|
+
return [];
|
|
1545
|
+
};
|
|
1569
1546
|
|
|
1547
|
+
BatchSender.prototype.saveQueueToStorage = function (queue) {
|
|
1548
|
+
try {
|
|
1549
|
+
var queueString = JSON.stringify(queue);
|
|
1570
1550
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1551
|
+
if (queueString.length > MAX_STORAGE_SIZE) {
|
|
1552
|
+
var maxItems = Math.floor(queue.length * 0.8);
|
|
1553
|
+
var trimmedQueue = queue.slice(-maxItems);
|
|
1554
|
+
this.callbacks.printLog("\u961F\u5217\u8FC7\u5927\uFF0C\u5DF2\u622A\u65AD\u4FDD\u7559\u6700\u65B0 " + maxItems + " \u6761\u6570\u636E\uFF08\u9650\u5236: " + MAX_STORAGE_SIZE / 1024 / 1024 + "MB\uFF09");
|
|
1555
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, JSON.stringify(trimmedQueue));
|
|
1556
|
+
} else {
|
|
1557
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, queueString);
|
|
1558
|
+
}
|
|
1559
|
+
} catch (e) {
|
|
1560
|
+
this.callbacks.printLog("\u4FDD\u5B58\u6279\u91CF\u961F\u5217\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1576
1563
|
|
|
1564
|
+
BatchSender.prototype.flushQueue = function () {
|
|
1565
|
+
var _this = this;
|
|
1577
1566
|
|
|
1578
|
-
|
|
1567
|
+
if (this.isFlushingQueue) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1579
1570
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1571
|
+
var batchQueue = this.getQueueFromStorage();
|
|
1572
|
+
if (batchQueue.length === 0) return;
|
|
1573
|
+
var currentTime = this.callbacks.getTimeStamp();
|
|
1574
|
+
var readyToSend = batchQueue.filter(function (item) {
|
|
1575
|
+
if (!item._nextRetryTime) {
|
|
1576
|
+
return true;
|
|
1577
|
+
}
|
|
1584
1578
|
|
|
1579
|
+
return item._nextRetryTime <= currentTime;
|
|
1580
|
+
});
|
|
1585
1581
|
|
|
1586
|
-
|
|
1582
|
+
if (readyToSend.length === 0) {
|
|
1583
|
+
if (this.config.showLog) {
|
|
1584
|
+
this.callbacks.printLog("\u6279\u91CF\u961F\u5217\u4E2D\u6709 " + batchQueue.length + " \u6761\u6570\u636E\u7B49\u5F85\u91CD\u8BD5");
|
|
1585
|
+
}
|
|
1587
1586
|
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1588
1589
|
|
|
1589
|
-
|
|
1590
|
+
var remainingQueue = batchQueue.filter(function (item) {
|
|
1591
|
+
if (!item._nextRetryTime) {
|
|
1592
|
+
return false;
|
|
1593
|
+
}
|
|
1590
1594
|
|
|
1595
|
+
return item._nextRetryTime > currentTime;
|
|
1596
|
+
});
|
|
1597
|
+
this.saveQueueToStorage(remainingQueue);
|
|
1598
|
+
this.isFlushingQueue = true;
|
|
1599
|
+
this.sendBatchData(readyToSend, function () {
|
|
1600
|
+
_this.isFlushingQueue = false;
|
|
1601
|
+
});
|
|
1602
|
+
};
|
|
1591
1603
|
|
|
1592
|
-
|
|
1604
|
+
BatchSender.prototype.sendBatchData = function (data, onComplete) {
|
|
1605
|
+
var _this = this;
|
|
1593
1606
|
|
|
1607
|
+
var _a = this.config,
|
|
1608
|
+
serverUrl = _a.serverUrl,
|
|
1609
|
+
contentType = _a.contentType,
|
|
1610
|
+
showLog = _a.showLog,
|
|
1611
|
+
sendMethod = _a.sendMethod,
|
|
1612
|
+
initHeader = _a.header;
|
|
1613
|
+
|
|
1614
|
+
if (showLog) {
|
|
1615
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001 " + data.length + " \u6761\u6570\u636E");
|
|
1616
|
+
data.forEach(function (item) {
|
|
1617
|
+
return _this.callbacks.printLog(JSON.stringify(item));
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1594
1620
|
|
|
1595
|
-
|
|
1621
|
+
var shouldUseBeacon = this.callbacks.shouldUseBeacon(sendMethod, undefined, initHeader);
|
|
1596
1622
|
|
|
1597
|
-
|
|
1598
|
-
|
|
1623
|
+
var complete = function complete() {
|
|
1624
|
+
if (onComplete) {
|
|
1625
|
+
onComplete();
|
|
1626
|
+
}
|
|
1599
1627
|
};
|
|
1600
|
-
/**
|
|
1601
|
-
* 重置设备ID
|
|
1602
|
-
* 清除存储的设备ID并重新生成
|
|
1603
|
-
* @returns 新的设备ID
|
|
1604
|
-
*/
|
|
1605
|
-
|
|
1606
1628
|
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1629
|
+
if (shouldUseBeacon) {
|
|
1630
|
+
try {
|
|
1631
|
+
var blob = new Blob([JSON.stringify(data)], {
|
|
1632
|
+
type: contentType || "application/json"
|
|
1633
|
+
});
|
|
1634
|
+
var sent = navigator.sendBeacon(serverUrl, blob);
|
|
1613
1635
|
|
|
1614
|
-
|
|
1636
|
+
if (sent) {
|
|
1637
|
+
if (showLog) {
|
|
1638
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
1639
|
+
}
|
|
1615
1640
|
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1641
|
+
complete();
|
|
1642
|
+
} else {
|
|
1643
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: sendBeacon \u8FD4\u56DE false\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
1644
|
+
this.retryBatchData(data);
|
|
1645
|
+
complete();
|
|
1646
|
+
}
|
|
1647
|
+
} catch (e) {
|
|
1648
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + e + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
1649
|
+
this.retryBatchData(data);
|
|
1650
|
+
complete();
|
|
1651
|
+
}
|
|
1652
|
+
} else {
|
|
1653
|
+
this.callbacks.ajax({
|
|
1654
|
+
url: serverUrl,
|
|
1655
|
+
type: "POST",
|
|
1656
|
+
data: JSON.stringify({
|
|
1657
|
+
events: data
|
|
1658
|
+
}),
|
|
1659
|
+
contentType: contentType,
|
|
1660
|
+
credentials: false,
|
|
1661
|
+
timeout: this.config.sendTimeout,
|
|
1662
|
+
cors: true,
|
|
1663
|
+
success: function success() {
|
|
1664
|
+
if (_this.config.showLog) {
|
|
1665
|
+
_this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
1666
|
+
}
|
|
1623
1667
|
|
|
1668
|
+
complete();
|
|
1669
|
+
},
|
|
1670
|
+
error: function error(err) {
|
|
1671
|
+
_this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + err + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
1624
1672
|
|
|
1625
|
-
|
|
1626
|
-
var desc = _a.desc,
|
|
1627
|
-
pageKey = _a.pageKey,
|
|
1628
|
-
partkey = _a.partkey,
|
|
1629
|
-
business = _a.business,
|
|
1630
|
-
header = _a.header;
|
|
1673
|
+
_this.retryBatchData(data);
|
|
1631
1674
|
|
|
1632
|
-
|
|
1633
|
-
desc: desc,
|
|
1634
|
-
event: "CustomTrack",
|
|
1635
|
-
itemKey: _this.getItemKey(partkey, pageKey),
|
|
1636
|
-
privateParamMap: {
|
|
1637
|
-
business: business
|
|
1675
|
+
complete();
|
|
1638
1676
|
}
|
|
1639
1677
|
});
|
|
1678
|
+
}
|
|
1679
|
+
};
|
|
1640
1680
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
/**
|
|
1644
|
-
* @description 监听全埋点事件
|
|
1645
|
-
*/
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
_this.listener = function () {
|
|
1649
|
-
// 先移除旧的监听器,避免重复绑定
|
|
1650
|
-
_this.unlistener(); // 如果启用了全埋点,监听页面浏览事件
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
if (!!_this.initConfig.autoTrack) {
|
|
1654
|
-
if (!!_this.initConfig.isTrackSinglePage) {
|
|
1655
|
-
_this.rewriteHistory();
|
|
1681
|
+
BatchSender.prototype.retryBatchData = function (data) {
|
|
1682
|
+
var _this = this;
|
|
1656
1683
|
|
|
1657
|
-
|
|
1658
|
-
}
|
|
1684
|
+
var currentQueue = this.getQueueFromStorage();
|
|
1659
1685
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
} // 如果启用了全埋点或启用了 data-part-key 点击追踪,监听点击事件
|
|
1686
|
+
var getEventKey = function getEventKey(item) {
|
|
1687
|
+
return item.event + "_" + item.itemKey + "_" + item.requestTime;
|
|
1688
|
+
};
|
|
1664
1689
|
|
|
1690
|
+
var existingKeys = new Set(currentQueue.map(getEventKey));
|
|
1691
|
+
var maxRetryCount = 3;
|
|
1692
|
+
var currentTime = this.callbacks.getTimeStamp();
|
|
1693
|
+
var retryData = data.filter(function (item) {
|
|
1694
|
+
var key = getEventKey(item);
|
|
1665
1695
|
|
|
1666
|
-
if (
|
|
1667
|
-
|
|
1696
|
+
if (existingKeys.has(key)) {
|
|
1697
|
+
return false;
|
|
1668
1698
|
}
|
|
1669
|
-
};
|
|
1670
|
-
/**
|
|
1671
|
-
* @description 取消全埋点事件
|
|
1672
|
-
*/
|
|
1673
1699
|
|
|
1700
|
+
var retryCount = (item._retryCount || 0) + 1;
|
|
1674
1701
|
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1702
|
+
if (retryCount > maxRetryCount) {
|
|
1703
|
+
if (_this.config.showLog) {
|
|
1704
|
+
_this.callbacks.printLog("\u6570\u636E\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u653E\u5F03\u91CD\u8BD5: " + key);
|
|
1705
|
+
}
|
|
1679
1706
|
|
|
1680
|
-
|
|
1681
|
-
_this.removeEventListener(window, historyName, _this.onPageViewCallback);
|
|
1682
|
-
});
|
|
1707
|
+
return false;
|
|
1683
1708
|
}
|
|
1684
1709
|
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1710
|
+
item._retryCount = retryCount;
|
|
1711
|
+
item._nextRetryTime = currentTime + Math.pow(2, retryCount) * 1000;
|
|
1712
|
+
existingKeys.add(key);
|
|
1713
|
+
return true;
|
|
1714
|
+
});
|
|
1688
1715
|
|
|
1689
|
-
|
|
1716
|
+
var retryQueue = __spreadArray(__spreadArray([], retryData), currentQueue);
|
|
1690
1717
|
|
|
1718
|
+
var maxSize = this.config.batchMaxSize * 2;
|
|
1719
|
+
var trimmedQueue = retryQueue.length > maxSize ? retryQueue.slice(0, maxSize) : retryQueue;
|
|
1720
|
+
this.saveQueueToStorage(trimmedQueue);
|
|
1691
1721
|
|
|
1692
|
-
|
|
1722
|
+
if (this.config.showLog) {
|
|
1723
|
+
this.callbacks.printLog("\u5DF2\u5C06 " + retryData.length + " \u6761\u6570\u636E\u52A0\u5165\u91CD\u8BD5\u961F\u5217");
|
|
1724
|
+
}
|
|
1725
|
+
};
|
|
1693
1726
|
|
|
1727
|
+
return BatchSender;
|
|
1728
|
+
}();
|
|
1694
1729
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1730
|
+
var DeviceManager =
|
|
1731
|
+
/** @class */
|
|
1732
|
+
function () {
|
|
1733
|
+
function DeviceManager(callbacks) {
|
|
1734
|
+
this.deviceId = "";
|
|
1735
|
+
this.callbacks = callbacks;
|
|
1736
|
+
}
|
|
1700
1737
|
|
|
1738
|
+
DeviceManager.prototype.getDeviceId = function () {
|
|
1739
|
+
if (this.deviceId) {
|
|
1740
|
+
return this.deviceId;
|
|
1741
|
+
}
|
|
1701
1742
|
|
|
1702
|
-
|
|
1703
|
-
if (_this.batchTimer !== null) {
|
|
1704
|
-
clearTimeout(_this.batchTimer);
|
|
1705
|
-
_this.batchTimer = null;
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
1708
|
-
/**
|
|
1709
|
-
* @description 清空批量队列(包括 LocalStorage 中的数据)
|
|
1710
|
-
*/
|
|
1743
|
+
var storedDeviceId = this.callbacks.getCookie("device_id") || this.callbacks.getLocalStorage("device_id");
|
|
1711
1744
|
|
|
1745
|
+
if (storedDeviceId) {
|
|
1746
|
+
this.deviceId = storedDeviceId;
|
|
1747
|
+
return this.deviceId;
|
|
1748
|
+
}
|
|
1712
1749
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1750
|
+
var fingerprint = this.callbacks.collectFingerprint();
|
|
1751
|
+
var deviceId = this.callbacks.hashFingerprint(fingerprint);
|
|
1752
|
+
this.callbacks.setCookie("device_id", deviceId, 365 * 2);
|
|
1753
|
+
this.callbacks.setLocalStorage("device_id", deviceId);
|
|
1754
|
+
this.deviceId = deviceId;
|
|
1755
|
+
return this.deviceId;
|
|
1756
|
+
};
|
|
1715
1757
|
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1758
|
+
DeviceManager.prototype.resetDeviceId = function () {
|
|
1759
|
+
document.cookie = "device_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
|
|
1760
|
+
localStorage.removeItem("device_id");
|
|
1761
|
+
this.deviceId = "";
|
|
1762
|
+
var newDeviceId = this.getDeviceId();
|
|
1763
|
+
return newDeviceId;
|
|
1764
|
+
};
|
|
1765
|
+
|
|
1766
|
+
return DeviceManager;
|
|
1767
|
+
}();
|
|
1724
1768
|
|
|
1769
|
+
var PENDING_REQUESTS_STORAGE_KEY = "web_tracking_pending_requests";
|
|
1770
|
+
var DEFAULT_PENDING_REQUESTS_MAX_SIZE = 50;
|
|
1725
1771
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1772
|
+
var PendingRequestsManager =
|
|
1773
|
+
/** @class */
|
|
1774
|
+
function () {
|
|
1775
|
+
function PendingRequestsManager(config, callbacks) {
|
|
1776
|
+
this.isFlushingPendingData = false;
|
|
1777
|
+
this.isUnloadListenerSetup = false;
|
|
1778
|
+
this.config = config;
|
|
1779
|
+
this.callbacks = callbacks;
|
|
1780
|
+
}
|
|
1729
1781
|
|
|
1730
|
-
|
|
1731
|
-
|
|
1782
|
+
PendingRequestsManager.prototype.updateConfig = function (config) {
|
|
1783
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1784
|
+
};
|
|
1732
1785
|
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
} catch (e) {
|
|
1738
|
-
_this.printLog("\u8BFB\u53D6\u6279\u91CF\u961F\u5217\u5931\u8D25: " + e); // 如果解析失败,清除损坏的数据
|
|
1786
|
+
PendingRequestsManager.prototype.addToQueue = function (params) {
|
|
1787
|
+
var currentRequests = this.getQueueFromStorage();
|
|
1788
|
+
currentRequests.push(params);
|
|
1789
|
+
var maxSize = this.config.pendingRequestsMaxSize || DEFAULT_PENDING_REQUESTS_MAX_SIZE;
|
|
1739
1790
|
|
|
1791
|
+
if (currentRequests.length > maxSize) {
|
|
1792
|
+
var trimmedRequests = currentRequests.slice(-maxSize);
|
|
1740
1793
|
|
|
1741
|
-
|
|
1794
|
+
if (this.config.showLog) {
|
|
1795
|
+
this.callbacks.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u961F\u5217\u5DF2\u6EE1\uFF0C\u5DF2\u79FB\u9664\u6700\u65E7\u7684\u6570\u636E\uFF08\u6700\u5927\u9650\u5236: " + maxSize + "\uFF09");
|
|
1742
1796
|
}
|
|
1743
1797
|
|
|
1744
|
-
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
*/
|
|
1798
|
+
this.saveQueueToStorage(trimmedRequests);
|
|
1799
|
+
} else {
|
|
1800
|
+
this.saveQueueToStorage(currentRequests);
|
|
1801
|
+
}
|
|
1802
|
+
};
|
|
1750
1803
|
|
|
1804
|
+
PendingRequestsManager.prototype.restoreQueue = function () {
|
|
1805
|
+
var pendingRequests = this.getQueueFromStorage();
|
|
1751
1806
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1807
|
+
if (pendingRequests.length > 0) {
|
|
1808
|
+
if (this.config.showLog) {
|
|
1809
|
+
this.callbacks.printLog("\u4ECE LocalStorage \u6062\u590D " + pendingRequests.length + " \u6761\u5F85\u53D1\u9001\u8BF7\u6C42");
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1755
1813
|
|
|
1756
|
-
|
|
1757
|
-
|
|
1814
|
+
PendingRequestsManager.prototype.flushQueue = function () {
|
|
1815
|
+
var _this = this;
|
|
1758
1816
|
|
|
1759
|
-
|
|
1817
|
+
var pendingRequests = this.getQueueFromStorage();
|
|
1760
1818
|
|
|
1761
|
-
|
|
1819
|
+
if (pendingRequests.length === 0) {
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1762
1822
|
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1823
|
+
this.saveQueueToStorage([]);
|
|
1824
|
+
var _a = this.config,
|
|
1825
|
+
serverUrl = _a.serverUrl,
|
|
1826
|
+
sendTimeout = _a.sendTimeout,
|
|
1827
|
+
contentType = _a.contentType,
|
|
1828
|
+
showLog = _a.showLog,
|
|
1829
|
+
initHeader = _a.header;
|
|
1830
|
+
pendingRequests.forEach(function (params) {
|
|
1831
|
+
if (!_this.callbacks.shouldSample()) {
|
|
1832
|
+
if (showLog) {
|
|
1833
|
+
_this.callbacks.printLog("待发送请求已采样跳过");
|
|
1766
1834
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
_this.printLog("\u4FDD\u5B58\u6279\u91CF\u961F\u5217\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
1835
|
+
|
|
1836
|
+
return;
|
|
1770
1837
|
}
|
|
1771
|
-
};
|
|
1772
|
-
/**
|
|
1773
|
-
* @description 从 LocalStorage 获取待发送请求队列
|
|
1774
|
-
* @returns 待发送请求队列数组
|
|
1775
|
-
*/
|
|
1776
1838
|
|
|
1839
|
+
if (showLog) {
|
|
1840
|
+
_this.callbacks.printLog(JSON.stringify(params));
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
_this.callbacks.ajax({
|
|
1844
|
+
url: serverUrl,
|
|
1845
|
+
type: "POST",
|
|
1846
|
+
data: JSON.stringify(params),
|
|
1847
|
+
contentType: contentType,
|
|
1848
|
+
header: initHeader,
|
|
1849
|
+
credentials: false,
|
|
1850
|
+
timeout: sendTimeout,
|
|
1851
|
+
cors: true,
|
|
1852
|
+
success: function success() {
|
|
1853
|
+
if (showLog) {
|
|
1854
|
+
_this.callbacks.printLog("待发送请求发送成功");
|
|
1855
|
+
}
|
|
1856
|
+
},
|
|
1857
|
+
error: function error(err) {
|
|
1858
|
+
if (showLog) {
|
|
1859
|
+
_this.callbacks.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u53D1\u9001\u5931\u8D25\uFF08\u4E0D\u518D\u91CD\u8BD5\uFF09: " + err);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
});
|
|
1864
|
+
};
|
|
1777
1865
|
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
var storedRequests = _this.getLocalStorage(_this.PENDING_REQUESTS_STORAGE_KEY);
|
|
1866
|
+
PendingRequestsManager.prototype.flushQueueWithBeacon = function () {
|
|
1867
|
+
var _this = this;
|
|
1781
1868
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1869
|
+
if (this.isFlushingPendingData) {
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1784
1872
|
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
} catch (e) {
|
|
1790
|
-
_this.printLog("\u8BFB\u53D6\u5F85\u53D1\u9001\u8BF7\u6C42\u5931\u8D25: " + e); // 如果解析失败,清除损坏的数据
|
|
1873
|
+
this.isFlushingPendingData = true;
|
|
1874
|
+
var pendingRequests = this.getQueueFromStorage();
|
|
1791
1875
|
|
|
1876
|
+
if (pendingRequests.length === 0) {
|
|
1877
|
+
this.isFlushingPendingData = false;
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1792
1880
|
|
|
1793
|
-
|
|
1881
|
+
var _a = this.config,
|
|
1882
|
+
serverUrl = _a.serverUrl,
|
|
1883
|
+
contentType = _a.contentType,
|
|
1884
|
+
showLog = _a.showLog;
|
|
1885
|
+
var successCount = 0;
|
|
1886
|
+
var failureCount = 0;
|
|
1887
|
+
pendingRequests.forEach(function (params) {
|
|
1888
|
+
if (_this.sendWithBeacon(params, serverUrl, contentType)) {
|
|
1889
|
+
successCount++;
|
|
1890
|
+
} else {
|
|
1891
|
+
failureCount++;
|
|
1794
1892
|
}
|
|
1893
|
+
});
|
|
1795
1894
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
* @description 保存待发送请求队列到 LocalStorage
|
|
1800
|
-
* @param requests 待发送请求队列数组
|
|
1801
|
-
*/
|
|
1895
|
+
if (showLog) {
|
|
1896
|
+
this.callbacks.printLog("\u9875\u9762\u5378\u8F7D\u65F6\u53D1\u9001\u5F85\u8BF7\u6C42\u6570\u636E: \u6210\u529F " + successCount + " \u6761\uFF0C\u5931\u8D25 " + failureCount + " \u6761");
|
|
1897
|
+
}
|
|
1802
1898
|
|
|
1899
|
+
this.isFlushingPendingData = false;
|
|
1900
|
+
};
|
|
1803
1901
|
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
_this.setLocalStorage(_this.PENDING_REQUESTS_STORAGE_KEY, JSON.stringify(requests));
|
|
1807
|
-
} catch (e) {
|
|
1808
|
-
// LocalStorage 可能已满或不可用
|
|
1809
|
-
_this.printLog("\u4FDD\u5B58\u5F85\u53D1\u9001\u8BF7\u6C42\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
1810
|
-
}
|
|
1811
|
-
};
|
|
1812
|
-
/**
|
|
1813
|
-
* @description 设置自定义页面唯一标识
|
|
1814
|
-
* @param pageKey 页面唯一标识,如果传入 null 或空字符串,则恢复自动生成
|
|
1815
|
-
* @param autoUpdate 路由变化时是否自动更新(默认:false,使用自定义值后不再自动更新)
|
|
1816
|
-
*/
|
|
1902
|
+
PendingRequestsManager.prototype.setupUnloadListener = function () {
|
|
1903
|
+
var _this = this;
|
|
1817
1904
|
|
|
1905
|
+
if (this.isUnloadListenerSetup) {
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1818
1908
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1909
|
+
this.isUnloadListenerSetup = true;
|
|
1910
|
+
document.addEventListener("visibilitychange", function () {
|
|
1911
|
+
if (_this.isPageUnloading()) {
|
|
1912
|
+
_this.flushQueueWithBeacon();
|
|
1822
1913
|
}
|
|
1914
|
+
});
|
|
1915
|
+
window.addEventListener("beforeunload", function () {
|
|
1916
|
+
_this.flushQueueWithBeacon();
|
|
1917
|
+
});
|
|
1918
|
+
window.addEventListener("pagehide", function () {
|
|
1919
|
+
_this.flushQueueWithBeacon();
|
|
1920
|
+
});
|
|
1921
|
+
};
|
|
1823
1922
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
var pathname = window.location.pathname;
|
|
1828
|
-
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
1923
|
+
PendingRequestsManager.prototype.getQueueFromStorage = function () {
|
|
1924
|
+
try {
|
|
1925
|
+
var storedRequests = this.callbacks.getLocalStorage(PENDING_REQUESTS_STORAGE_KEY);
|
|
1829
1926
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
}
|
|
1833
|
-
} else {
|
|
1834
|
-
_this.pageKey = pageKey;
|
|
1835
|
-
_this.useCustomPageKey = !autoUpdate;
|
|
1927
|
+
if (storedRequests) {
|
|
1928
|
+
var parsedRequests = JSON.parse(storedRequests);
|
|
1836
1929
|
|
|
1837
|
-
if (
|
|
1838
|
-
|
|
1930
|
+
if (Array.isArray(parsedRequests)) {
|
|
1931
|
+
return parsedRequests;
|
|
1839
1932
|
}
|
|
1840
1933
|
}
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
*/
|
|
1846
|
-
|
|
1934
|
+
} catch (e) {
|
|
1935
|
+
this.callbacks.printLog("\u8BFB\u53D6\u5F85\u53D1\u9001\u8BF7\u6C42\u5931\u8D25: " + e);
|
|
1936
|
+
this.callbacks.setLocalStorage(PENDING_REQUESTS_STORAGE_KEY, "[]");
|
|
1937
|
+
}
|
|
1847
1938
|
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
};
|
|
1939
|
+
return [];
|
|
1940
|
+
};
|
|
1851
1941
|
|
|
1852
|
-
|
|
1853
|
-
|
|
1942
|
+
PendingRequestsManager.prototype.saveQueueToStorage = function (requests) {
|
|
1943
|
+
try {
|
|
1944
|
+
this.callbacks.setLocalStorage(PENDING_REQUESTS_STORAGE_KEY, JSON.stringify(requests));
|
|
1945
|
+
} catch (e) {
|
|
1946
|
+
this.callbacks.printLog("\u4FDD\u5B58\u5F85\u53D1\u9001\u8BF7\u6C42\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
1947
|
+
}
|
|
1948
|
+
};
|
|
1854
1949
|
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
var id = target.id;
|
|
1859
|
-
var className = target.className;
|
|
1860
|
-
var nodeName = target.nodeName;
|
|
1861
|
-
var targetEle = {
|
|
1862
|
-
id: id,
|
|
1863
|
-
nodeName: nodeName,
|
|
1864
|
-
className: className,
|
|
1865
|
-
position: position
|
|
1866
|
-
};
|
|
1950
|
+
PendingRequestsManager.prototype.isPageUnloading = function () {
|
|
1951
|
+
return document.visibilityState === "hidden";
|
|
1952
|
+
};
|
|
1867
1953
|
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
privateParamMap: {
|
|
1873
|
-
targetEle: targetEle,
|
|
1874
|
-
pointerType: e.pointerType,
|
|
1875
|
-
currentUrl: _this.currentUrl,
|
|
1876
|
-
elementSelector: _this.getDomSelector(target) || ""
|
|
1877
|
-
}
|
|
1954
|
+
PendingRequestsManager.prototype.sendWithBeacon = function (params, serverUrl, contentType) {
|
|
1955
|
+
try {
|
|
1956
|
+
var blob = new Blob([JSON.stringify(params)], {
|
|
1957
|
+
type: contentType || "application/json"
|
|
1878
1958
|
});
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
* @description 路由触发事件
|
|
1884
|
-
*/
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
_this.onPageViewCallback = function (e) {
|
|
1888
|
-
var _a, _b; // 在路由变化前,先发送待发送的数据(避免被取消)
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
var pendingRequests = _this.getPendingRequestsFromStorage();
|
|
1892
|
-
|
|
1893
|
-
var batchQueue = _this.initConfig.batchSend ? _this.getBatchQueueFromStorage() : [];
|
|
1894
|
-
|
|
1895
|
-
if (pendingRequests.length > 0 || batchQueue.length > 0) {
|
|
1896
|
-
_this.flushPendingData();
|
|
1959
|
+
return navigator.sendBeacon(serverUrl, blob);
|
|
1960
|
+
} catch (e) {
|
|
1961
|
+
if (this.config.showLog) {
|
|
1962
|
+
this.callbacks.printLog("sendBeacon \u53D1\u9001\u5931\u8D25: " + e);
|
|
1897
1963
|
}
|
|
1898
1964
|
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
event: "PageView",
|
|
1903
|
-
desc: _this.eventDescMap["PageView"],
|
|
1904
|
-
privateParamMap: {
|
|
1905
|
-
currentUrl: _this.currentUrl,
|
|
1906
|
-
targetUrl: ((_a = e.arguments) === null || _a === void 0 ? void 0 : _a[2]) ? ORGIN + ((_b = e.arguments) === null || _b === void 0 ? void 0 : _b[2]) : null
|
|
1907
|
-
}
|
|
1908
|
-
});
|
|
1909
|
-
|
|
1910
|
-
_this.currentUrl = window.location.href; // 如果使用自定义 pageKey,路由变化时不自动更新
|
|
1911
|
-
|
|
1912
|
-
if (!_this.useCustomPageKey) {
|
|
1913
|
-
_this.pageKey = window.location.pathname.replace(/\//g, "_").substring(1);
|
|
1914
|
-
} // 路由变化时,如果启用了定时上报,需要重启定时器
|
|
1915
|
-
|
|
1965
|
+
return false;
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1916
1968
|
|
|
1917
|
-
|
|
1918
|
-
|
|
1969
|
+
return PendingRequestsManager;
|
|
1970
|
+
}();
|
|
1919
1971
|
|
|
1920
|
-
|
|
1921
|
-
|
|
1972
|
+
var WebTracking =
|
|
1973
|
+
/** @class */
|
|
1974
|
+
function (_super) {
|
|
1975
|
+
__extends(WebTracking, _super);
|
|
1922
1976
|
|
|
1923
|
-
|
|
1977
|
+
function WebTracking() {
|
|
1978
|
+
var _this = _super.call(this) || this;
|
|
1924
1979
|
|
|
1925
|
-
|
|
1980
|
+
_this.useCustomPageKey = false;
|
|
1981
|
+
_this.userInfo = null;
|
|
1982
|
+
_this.currentUrl = "";
|
|
1983
|
+
_this.pageKey = "";
|
|
1984
|
+
_this.deviceId = "";
|
|
1985
|
+
_this.eventDescMap = {
|
|
1986
|
+
PageView: "Web 浏览页面",
|
|
1987
|
+
WebClick: "Web 元素点击",
|
|
1988
|
+
PageRetained: "Web 页面浏览时长",
|
|
1989
|
+
CustomTrack: "Web 自定义代码上报",
|
|
1990
|
+
WebExposure: "Web 元素曝光"
|
|
1926
1991
|
};
|
|
1927
1992
|
|
|
1928
|
-
_this.
|
|
1929
|
-
|
|
1930
|
-
desc = _a.desc,
|
|
1931
|
-
_b = _a.privateParamMap,
|
|
1932
|
-
privateParamMap = _b === void 0 ? {} : _b,
|
|
1933
|
-
itemKey = _a.itemKey;
|
|
1934
|
-
var business = _this.initConfig.business;
|
|
1935
|
-
var pageWidth = window.innerWidth;
|
|
1936
|
-
var pageHeight = window.innerHeight;
|
|
1937
|
-
var screenWidth = window.screen.width;
|
|
1938
|
-
var screenHeight = window.screen.height; // 过滤敏感数据
|
|
1939
|
-
|
|
1940
|
-
var filteredBusiness = _this.filterSensitiveData(business || {});
|
|
1941
|
-
|
|
1942
|
-
var filteredUserInfo = _this.filterSensitiveData(_this.userInfo || {});
|
|
1943
|
-
|
|
1944
|
-
var filteredPrivateParamMap = _this.filterSensitiveData(privateParamMap || {});
|
|
1945
|
-
|
|
1946
|
-
var filteredUrlParams = _this.filterSensitiveData(_this.getQueryValue() || {}); // 创建私有参数对象
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
var privateParamMapData = {
|
|
1950
|
-
currentUrl: filteredPrivateParamMap.currentUrl || _this.currentUrl,
|
|
1951
|
-
business: Object.assign({}, filteredBusiness, filteredPrivateParamMap.business || {}),
|
|
1952
|
-
pageWidth: pageWidth,
|
|
1953
|
-
pageHeight: pageHeight,
|
|
1954
|
-
screenWidth: screenWidth,
|
|
1955
|
-
screenHeight: screenHeight,
|
|
1956
|
-
sdkVersion: _this.sdkVersion,
|
|
1957
|
-
systemsInfo: _this.systemsInfo,
|
|
1958
|
-
urlParams: filteredUrlParams,
|
|
1959
|
-
userInfo: filteredUserInfo,
|
|
1960
|
-
deviceId: _this.deviceId // 添加设备ID
|
|
1993
|
+
_this.init = function (initParams) {
|
|
1994
|
+
_this.preset(initParams);
|
|
1961
1995
|
|
|
1962
|
-
|
|
1996
|
+
var pathname = window.location.pathname;
|
|
1997
|
+
_this.currentUrl = window.location.href;
|
|
1963
1998
|
|
|
1964
|
-
if (
|
|
1965
|
-
|
|
1999
|
+
if (initParams.pageKey) {
|
|
2000
|
+
_this.pageKey = initParams.pageKey;
|
|
2001
|
+
_this.useCustomPageKey = true;
|
|
2002
|
+
} else {
|
|
2003
|
+
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2004
|
+
_this.useCustomPageKey = false;
|
|
1966
2005
|
}
|
|
1967
2006
|
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
}
|
|
2007
|
+
_this.systemsInfo = _this.getSystemsInfo(initParams.platform);
|
|
2008
|
+
_this.deviceId = _this.deviceManager.getDeviceId();
|
|
1971
2009
|
|
|
1972
|
-
if (
|
|
1973
|
-
|
|
2010
|
+
if (initParams.userInfo && _this.isObject(initParams.userInfo)) {
|
|
2011
|
+
_this.userInfo = initParams.userInfo;
|
|
1974
2012
|
}
|
|
1975
2013
|
|
|
1976
|
-
|
|
1977
|
-
privateParamMapData.elementSelector = filteredPrivateParamMap.elementSelector;
|
|
1978
|
-
}
|
|
2014
|
+
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
1979
2015
|
|
|
1980
|
-
if (
|
|
1981
|
-
|
|
2016
|
+
if (_this.initConfig.batchSend) {
|
|
2017
|
+
_this.batchSender.restoreQueue();
|
|
1982
2018
|
}
|
|
1983
2019
|
|
|
1984
|
-
|
|
1985
|
-
event: event,
|
|
1986
|
-
desc: desc,
|
|
1987
|
-
itemKey: itemKey || _this.getItemKey(),
|
|
1988
|
-
requestTime: _this.getTimeStamp(),
|
|
1989
|
-
privateParamMap: privateParamMapData
|
|
1990
|
-
};
|
|
1991
|
-
};
|
|
1992
|
-
/**
|
|
1993
|
-
* 数据采样判断
|
|
1994
|
-
* @returns 是否应该采样
|
|
1995
|
-
*/
|
|
2020
|
+
_this.pendingRequestsManager.restoreQueue();
|
|
1996
2021
|
|
|
2022
|
+
_this.pendingRequestsManager.setupUnloadListener();
|
|
1997
2023
|
|
|
1998
|
-
|
|
1999
|
-
var sampleRate = _this.initConfig.sampleRate;
|
|
2000
|
-
if (sampleRate >= 1) return true;
|
|
2001
|
-
if (sampleRate <= 0) return false;
|
|
2002
|
-
return Math.random() < sampleRate;
|
|
2003
|
-
};
|
|
2004
|
-
/**
|
|
2005
|
-
* 批量发送数据
|
|
2006
|
-
*/
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
_this.flushBatchQueue = function () {
|
|
2010
|
-
var batchQueue = _this.getBatchQueueFromStorage();
|
|
2011
|
-
|
|
2012
|
-
if (batchQueue.length === 0) return;
|
|
2013
|
-
|
|
2014
|
-
var currentTime = _this.getTimeStamp(); // 过滤出可以发送的数据(未到重试时间的不发送)
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
var readyToSend = batchQueue.filter(function (item) {
|
|
2018
|
-
if (!item._nextRetryTime) {
|
|
2019
|
-
return true;
|
|
2020
|
-
}
|
|
2024
|
+
var autoTrackConfig = _this.getAutoTrackConfig();
|
|
2021
2025
|
|
|
2022
|
-
|
|
2023
|
-
});
|
|
2026
|
+
_this.currentAutoTrackConfig = autoTrackConfig;
|
|
2024
2027
|
|
|
2025
|
-
if (
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
return;
|
|
2031
|
-
} // 从队列中移除已准备发送的数据
|
|
2028
|
+
if (autoTrackConfig.retained) {
|
|
2029
|
+
_this.pageDurationTracker.start();
|
|
2030
|
+
}
|
|
2032
2031
|
|
|
2032
|
+
if (autoTrackConfig.exposure) {
|
|
2033
|
+
_this.exposureTracker.init();
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2033
2036
|
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
+
_this.preset = function (presetParams) {
|
|
2038
|
+
if (presetParams instanceof Object) {
|
|
2039
|
+
if (presetParams.pageKey !== undefined) {
|
|
2040
|
+
if (presetParams.pageKey === null || presetParams.pageKey === "") {
|
|
2041
|
+
_this.useCustomPageKey = false;
|
|
2042
|
+
var pathname = window.location.pathname;
|
|
2043
|
+
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2044
|
+
} else {
|
|
2045
|
+
_this.pageKey = presetParams.pageKey;
|
|
2046
|
+
_this.useCustomPageKey = true;
|
|
2047
|
+
}
|
|
2037
2048
|
}
|
|
2038
2049
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
_this.saveBatchQueueToStorage(remainingQueue); // 发送批量数据
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
_this.sendBatchData(readyToSend);
|
|
2046
|
-
};
|
|
2047
|
-
/**
|
|
2048
|
-
* 发送批量数据
|
|
2049
|
-
* @param data 批量数据
|
|
2050
|
-
*/
|
|
2051
|
-
|
|
2050
|
+
_this.each(presetParams, function (val, key) {
|
|
2051
|
+
if (key === "pageKey") return;
|
|
2052
2052
|
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
initHeader = _a.header;
|
|
2053
|
+
if (key === "autoTrack" && _typeof(val) === "object" && val !== null) {
|
|
2054
|
+
var newAutoTrackConfig = val;
|
|
2055
|
+
_this.initConfig.autoTrack = __assign(__assign({}, _this.currentAutoTrackConfig), newAutoTrackConfig);
|
|
2056
|
+
_this.currentAutoTrackConfig = _this.getAutoTrackConfig();
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2060
2059
|
|
|
2061
|
-
|
|
2062
|
-
|
|
2060
|
+
if (_this.initConfig.hasOwnProperty(key)) {
|
|
2061
|
+
var validationResult = _this.validateConfigParam(String(key), val);
|
|
2063
2062
|
|
|
2064
|
-
|
|
2065
|
-
|
|
2063
|
+
if (validationResult.valid) {
|
|
2064
|
+
_this.initConfig[key] = val;
|
|
2065
|
+
} else {
|
|
2066
|
+
console.warn("\u914D\u7F6E\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25: " + String(key) + " = " + val + ", \u539F\u56E0: " + validationResult.message);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2066
2069
|
});
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2070
|
+
}
|
|
2069
2071
|
|
|
2070
|
-
|
|
2072
|
+
if (!/^(((ht|f)tps?):\/\/)?[\w\-]+(\.[\w\-]+)+([\w\-\.,@?^=%&:/~+#\(\)]*[\w\-\.,@?^=%&/~+#\(\)])?$/.test(_this.initConfig["serverUrl"])) {
|
|
2073
|
+
console.warn("当前 server_url 为空或不正确,只在控制台打印日志,network 中不会发数据,请配置正确的 server_url!");
|
|
2074
|
+
}
|
|
2071
2075
|
|
|
2076
|
+
if (!!_this.initConfig["autoTrack"] || !!_this.initConfig["trackPartKeyClick"]) {
|
|
2077
|
+
_this.listener();
|
|
2078
|
+
} else {
|
|
2079
|
+
_this.unlistener();
|
|
2080
|
+
}
|
|
2072
2081
|
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2082
|
+
_this.batchSender.updateConfig({
|
|
2083
|
+
batchSend: _this.initConfig.batchSend,
|
|
2084
|
+
batchInterval: _this.initConfig.batchInterval,
|
|
2085
|
+
batchMaxSize: _this.initConfig.batchMaxSize,
|
|
2086
|
+
sendTimeout: _this.initConfig.sendTimeout,
|
|
2087
|
+
serverUrl: _this.initConfig.serverUrl,
|
|
2088
|
+
contentType: _this.initConfig.contentType,
|
|
2089
|
+
showLog: _this.initConfig.showLog,
|
|
2090
|
+
sendMethod: _this.initConfig.sendMethod,
|
|
2091
|
+
header: _this.initConfig.header
|
|
2092
|
+
});
|
|
2079
2093
|
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2094
|
+
_this.pendingRequestsManager.updateConfig({
|
|
2095
|
+
pendingRequestsMaxSize: _this.initConfig.pendingRequestsMaxSize,
|
|
2096
|
+
sendTimeout: _this.initConfig.sendTimeout,
|
|
2097
|
+
serverUrl: _this.initConfig.serverUrl,
|
|
2098
|
+
contentType: _this.initConfig.contentType,
|
|
2099
|
+
showLog: _this.initConfig.showLog,
|
|
2100
|
+
header: _this.initConfig.header
|
|
2101
|
+
});
|
|
2083
2102
|
|
|
2084
|
-
|
|
2085
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
2086
|
-
}
|
|
2087
|
-
} else {
|
|
2088
|
-
// sendBeacon 返回 false,重新加入队列以便重试
|
|
2089
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: sendBeacon \u8FD4\u56DE false\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
2103
|
+
var autoTrackConfig = _this.getAutoTrackConfig();
|
|
2090
2104
|
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2105
|
+
if (autoTrackConfig.retained) {
|
|
2106
|
+
_this.pageDurationTracker.updateConfig({
|
|
2107
|
+
pageDurationInterval: _this.initConfig.pageDurationInterval,
|
|
2108
|
+
showLog: _this.initConfig.showLog
|
|
2109
|
+
});
|
|
2096
2110
|
|
|
2097
|
-
|
|
2098
|
-
}
|
|
2111
|
+
_this.pageDurationTracker.start();
|
|
2099
2112
|
} else {
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
url: serverUrl,
|
|
2103
|
-
type: "POST",
|
|
2104
|
-
data: JSON.stringify({
|
|
2105
|
-
events: data
|
|
2106
|
-
}),
|
|
2107
|
-
contentType: contentType,
|
|
2108
|
-
credentials: false,
|
|
2109
|
-
timeout: _this.initConfig.sendTimeout,
|
|
2110
|
-
cors: true,
|
|
2111
|
-
success: function success() {
|
|
2112
|
-
// 批量发送成功,确保 LocalStorage 已清空
|
|
2113
|
-
// flushBatchQueue 在发送前已清空 LocalStorage,这里再次确认
|
|
2114
|
-
_this.saveBatchQueueToStorage([]);
|
|
2115
|
-
|
|
2116
|
-
if (_this.initConfig.showLog) {
|
|
2117
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
2118
|
-
}
|
|
2119
|
-
},
|
|
2120
|
-
error: function error(err) {
|
|
2121
|
-
// 批量发送失败,重新加入队列以便重试
|
|
2122
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + err + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
2113
|
+
_this.pageDurationTracker.stop();
|
|
2114
|
+
}
|
|
2123
2115
|
|
|
2124
|
-
|
|
2125
|
-
|
|
2116
|
+
if (autoTrackConfig.exposure) {
|
|
2117
|
+
_this.exposureTracker.updateConfig({
|
|
2118
|
+
autoTrackExposure: true,
|
|
2119
|
+
exposureThreshold: _this.initConfig.exposureThreshold,
|
|
2120
|
+
exposureTime: _this.initConfig.exposureTime,
|
|
2121
|
+
exposureNum: _this.initConfig.exposureNum,
|
|
2122
|
+
showLog: _this.initConfig.showLog
|
|
2126
2123
|
});
|
|
2124
|
+
|
|
2125
|
+
_this.exposureTracker.init();
|
|
2126
|
+
} else {
|
|
2127
|
+
_this.exposureTracker.stop();
|
|
2127
2128
|
}
|
|
2128
2129
|
};
|
|
2129
|
-
/**
|
|
2130
|
-
* @description 批量数据重试逻辑
|
|
2131
|
-
* @param data 批量数据
|
|
2132
|
-
*/
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
_this.retryBatchData = function (data) {
|
|
2136
|
-
// 获取当前队列
|
|
2137
|
-
var currentQueue = _this.getBatchQueueFromStorage(); // 去重:基于事件类型、itemKey、requestTime 生成唯一键
|
|
2138
2130
|
|
|
2131
|
+
_this.validateConfigParam = function (key, value) {
|
|
2132
|
+
switch (key) {
|
|
2133
|
+
case "sampleRate":
|
|
2134
|
+
if (typeof value !== "number" || value < 0 || value > 1) {
|
|
2135
|
+
return {
|
|
2136
|
+
valid: false,
|
|
2137
|
+
message: "sampleRate 必须是 0-1 之间的数字"
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2139
2140
|
|
|
2140
|
-
|
|
2141
|
-
return item.event + "_" + item.itemKey + "_" + item.requestTime;
|
|
2142
|
-
};
|
|
2143
|
-
|
|
2144
|
-
var existingKeys = new Set(currentQueue.map(getEventKey));
|
|
2145
|
-
var maxRetryCount = 3; // 最大重试次数
|
|
2141
|
+
break;
|
|
2146
2142
|
|
|
2147
|
-
|
|
2143
|
+
case "sendTimeout":
|
|
2144
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2145
|
+
return {
|
|
2146
|
+
valid: false,
|
|
2147
|
+
message: "sendTimeout 必须是大于 0 的数字"
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2148
2150
|
|
|
2151
|
+
break;
|
|
2149
2152
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2153
|
+
case "batchInterval":
|
|
2154
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2155
|
+
return {
|
|
2156
|
+
valid: false,
|
|
2157
|
+
message: "batchInterval 必须是大于 0 的数字"
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2152
2160
|
|
|
2153
|
-
|
|
2154
|
-
return false;
|
|
2155
|
-
} // 检查重试次数
|
|
2161
|
+
break;
|
|
2156
2162
|
|
|
2163
|
+
case "batchMaxSize":
|
|
2164
|
+
if (typeof value !== "number" || value <= 0 || !Number.isInteger(value)) {
|
|
2165
|
+
return {
|
|
2166
|
+
valid: false,
|
|
2167
|
+
message: "batchMaxSize 必须是大于 0 的整数"
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2157
2170
|
|
|
2158
|
-
|
|
2171
|
+
break;
|
|
2159
2172
|
|
|
2160
|
-
|
|
2161
|
-
if (
|
|
2162
|
-
|
|
2173
|
+
case "pendingRequestsMaxSize":
|
|
2174
|
+
if (typeof value !== "number" || value <= 0 || !Number.isInteger(value)) {
|
|
2175
|
+
return {
|
|
2176
|
+
valid: false,
|
|
2177
|
+
message: "pendingRequestsMaxSize 必须是大于 0 的整数"
|
|
2178
|
+
};
|
|
2163
2179
|
}
|
|
2164
2180
|
|
|
2165
|
-
|
|
2166
|
-
} // 更新重试信息
|
|
2181
|
+
break;
|
|
2167
2182
|
|
|
2183
|
+
case "pageDurationInterval":
|
|
2184
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2185
|
+
return {
|
|
2186
|
+
valid: false,
|
|
2187
|
+
message: "pageDurationInterval 必须是大于 0 的数字"
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2168
2190
|
|
|
2169
|
-
|
|
2191
|
+
break;
|
|
2170
2192
|
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2193
|
+
case "sendMethod":
|
|
2194
|
+
if (typeof value !== "string" || !["auto", "xhr", "beacon"].includes(value)) {
|
|
2195
|
+
return {
|
|
2196
|
+
valid: false,
|
|
2197
|
+
message: "sendMethod 必须是 auto、xhr 或 beacon"
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2175
2200
|
|
|
2176
|
-
|
|
2201
|
+
break;
|
|
2177
2202
|
|
|
2203
|
+
case "exposureThreshold":
|
|
2204
|
+
if (typeof value !== "number" || value < 0 || value > 1) {
|
|
2205
|
+
return {
|
|
2206
|
+
valid: false,
|
|
2207
|
+
message: "exposureThreshold 必须是 0-1 之间的数字"
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2178
2210
|
|
|
2179
|
-
|
|
2180
|
-
var trimmedQueue = retryQueue.length > maxSize ? retryQueue.slice(0, maxSize) : retryQueue; // 保存失败的数据到 LocalStorage,确保数据不丢失
|
|
2211
|
+
break;
|
|
2181
2212
|
|
|
2182
|
-
|
|
2213
|
+
case "exposureTime":
|
|
2214
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2215
|
+
return {
|
|
2216
|
+
valid: false,
|
|
2217
|
+
message: "exposureTime 必须是大于 0 的数字"
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2183
2220
|
|
|
2184
|
-
|
|
2185
|
-
_this.printLog("\u5DF2\u5C06 " + retryData.length + " \u6761\u6570\u636E\u52A0\u5165\u91CD\u8BD5\u961F\u5217");
|
|
2186
|
-
}
|
|
2187
|
-
};
|
|
2188
|
-
/**
|
|
2189
|
-
* 添加到批量队列
|
|
2190
|
-
* @param params 数据参数
|
|
2191
|
-
*/
|
|
2221
|
+
break;
|
|
2192
2222
|
|
|
2223
|
+
case "exposureNum":
|
|
2224
|
+
if (value !== undefined && (typeof value !== "number" || value <= 0 || !Number.isInteger(value))) {
|
|
2225
|
+
return {
|
|
2226
|
+
valid: false,
|
|
2227
|
+
message: "exposureNum 必须是大于 0 的整数或不限制"
|
|
2228
|
+
};
|
|
2229
|
+
}
|
|
2193
2230
|
|
|
2194
|
-
|
|
2195
|
-
var _a = _this.initConfig,
|
|
2196
|
-
batchInterval = _a.batchInterval,
|
|
2197
|
-
batchMaxSize = _a.batchMaxSize; // 数据采样判断(在添加到队列前判断)
|
|
2231
|
+
break;
|
|
2198
2232
|
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2233
|
+
case "showLog":
|
|
2234
|
+
case "isTrackSinglePage":
|
|
2235
|
+
case "batchSend":
|
|
2236
|
+
if (typeof value !== "boolean") {
|
|
2237
|
+
return {
|
|
2238
|
+
valid: false,
|
|
2239
|
+
message: key + " \u5FC5\u987B\u662F\u5E03\u5C14\u503C"
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2203
2242
|
|
|
2204
|
-
|
|
2205
|
-
} // 从 LocalStorage 获取当前队列
|
|
2243
|
+
break;
|
|
2206
2244
|
|
|
2245
|
+
case "autoTrack":
|
|
2246
|
+
if (typeof value !== "boolean" && _typeof(value) !== "object") {
|
|
2247
|
+
return {
|
|
2248
|
+
valid: false,
|
|
2249
|
+
message: "autoTrack 必须是布尔值或对象"
|
|
2250
|
+
};
|
|
2251
|
+
}
|
|
2207
2252
|
|
|
2208
|
-
|
|
2253
|
+
if (_typeof(value) === "object" && value !== null) {
|
|
2254
|
+
var autoTrackConfig = value;
|
|
2255
|
+
var validKeys = ["view", "click", "exposure", "retained"];
|
|
2209
2256
|
|
|
2257
|
+
for (var k in autoTrackConfig) {
|
|
2258
|
+
if (!validKeys.includes(k)) {
|
|
2259
|
+
return {
|
|
2260
|
+
valid: false,
|
|
2261
|
+
message: "autoTrack \u5BF9\u8C61\u4E2D\u5305\u542B\u65E0\u6548\u7684\u5C5E\u6027: " + k
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2210
2264
|
|
|
2211
|
-
|
|
2265
|
+
if (typeof autoTrackConfig[k] !== "boolean") {
|
|
2266
|
+
return {
|
|
2267
|
+
valid: false,
|
|
2268
|
+
message: "autoTrack." + k + " \u5FC5\u987B\u662F\u5E03\u5C14\u503C"
|
|
2269
|
+
};
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2212
2273
|
|
|
2213
|
-
|
|
2274
|
+
break;
|
|
2214
2275
|
|
|
2276
|
+
case "business":
|
|
2277
|
+
case "header":
|
|
2278
|
+
if (value !== null && _typeof(value) !== "object") {
|
|
2279
|
+
return {
|
|
2280
|
+
valid: false,
|
|
2281
|
+
message: key + " \u5FC5\u987B\u662F\u5BF9\u8C61\u6216 null"
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2215
2284
|
|
|
2216
|
-
|
|
2217
|
-
_this.flushBatchQueue();
|
|
2285
|
+
break;
|
|
2218
2286
|
|
|
2219
|
-
|
|
2220
|
-
|
|
2287
|
+
case "contentType":
|
|
2288
|
+
if (value !== "application/json" && value !== "application/x-www-form-urlencoded") {
|
|
2289
|
+
return {
|
|
2290
|
+
valid: false,
|
|
2291
|
+
message: "contentType 必须是 application/json 或 application/x-www-form-urlencoded"
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2221
2294
|
|
|
2295
|
+
break;
|
|
2222
2296
|
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2297
|
+
case "platform":
|
|
2298
|
+
if (typeof value !== "string") {
|
|
2299
|
+
return {
|
|
2300
|
+
valid: false,
|
|
2301
|
+
message: "platform 必须是字符串"
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2226
2304
|
|
|
2227
|
-
|
|
2228
|
-
}, batchInterval);
|
|
2305
|
+
break;
|
|
2229
2306
|
}
|
|
2307
|
+
|
|
2308
|
+
return {
|
|
2309
|
+
valid: true
|
|
2310
|
+
};
|
|
2230
2311
|
};
|
|
2231
|
-
/**
|
|
2232
|
-
* 从 LocalStorage 恢复批量队列
|
|
2233
|
-
*/
|
|
2234
2312
|
|
|
2313
|
+
_this.getAutoTrackConfig = function () {
|
|
2314
|
+
var _a, _b, _c, _d;
|
|
2235
2315
|
|
|
2236
|
-
|
|
2237
|
-
var batchQueue = _this.getBatchQueueFromStorage();
|
|
2316
|
+
var autoTrack = _this.initConfig.autoTrack;
|
|
2238
2317
|
|
|
2239
|
-
if (
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2318
|
+
if (typeof autoTrack === "boolean") {
|
|
2319
|
+
return {
|
|
2320
|
+
view: autoTrack,
|
|
2321
|
+
click: autoTrack,
|
|
2322
|
+
exposure: autoTrack,
|
|
2323
|
+
retained: autoTrack
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2243
2326
|
|
|
2327
|
+
if (_typeof(autoTrack) === "object" && autoTrack !== null) {
|
|
2328
|
+
return {
|
|
2329
|
+
view: (_a = autoTrack.view) !== null && _a !== void 0 ? _a : false,
|
|
2330
|
+
click: (_b = autoTrack.click) !== null && _b !== void 0 ? _b : false,
|
|
2331
|
+
exposure: (_c = autoTrack.exposure) !== null && _c !== void 0 ? _c : false,
|
|
2332
|
+
retained: (_d = autoTrack.retained) !== null && _d !== void 0 ? _d : false
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2244
2335
|
|
|
2245
|
-
|
|
2336
|
+
return {
|
|
2337
|
+
view: false,
|
|
2338
|
+
click: false,
|
|
2339
|
+
exposure: false,
|
|
2340
|
+
retained: false
|
|
2341
|
+
};
|
|
2342
|
+
};
|
|
2246
2343
|
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
// 设置定时发送
|
|
2251
|
-
var batchInterval = _this.initConfig.batchInterval;
|
|
2344
|
+
_this.login = function (userInfo) {
|
|
2345
|
+
if (_this.isObject(userInfo)) _this.userInfo = userInfo;
|
|
2346
|
+
};
|
|
2252
2347
|
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2348
|
+
_this.getDeviceId = function () {
|
|
2349
|
+
return _this.deviceManager.getDeviceId();
|
|
2350
|
+
};
|
|
2256
2351
|
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2352
|
+
_this.resetDeviceId = function () {
|
|
2353
|
+
return _this.deviceManager.resetDeviceId();
|
|
2262
2354
|
};
|
|
2263
|
-
/**
|
|
2264
|
-
* 添加到待发送请求队列
|
|
2265
|
-
* @param params 数据参数
|
|
2266
|
-
*/
|
|
2267
2355
|
|
|
2356
|
+
_this.track = function (_a) {
|
|
2357
|
+
var desc = _a.desc,
|
|
2358
|
+
pageKey = _a.pageKey,
|
|
2359
|
+
partKey = _a.partKey,
|
|
2360
|
+
business = _a.business,
|
|
2361
|
+
header = _a.header;
|
|
2268
2362
|
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2363
|
+
var params = _this.getParams({
|
|
2364
|
+
desc: desc,
|
|
2365
|
+
event: "CustomTrack",
|
|
2366
|
+
itemKey: _this.getItemKey(partKey, pageKey),
|
|
2367
|
+
privateParamMap: {
|
|
2368
|
+
business: business
|
|
2369
|
+
}
|
|
2370
|
+
});
|
|
2272
2371
|
|
|
2372
|
+
return _this.sendData(params, header);
|
|
2373
|
+
};
|
|
2273
2374
|
|
|
2274
|
-
|
|
2375
|
+
_this.listener = function () {
|
|
2376
|
+
_this.unlistener();
|
|
2275
2377
|
|
|
2276
|
-
var
|
|
2378
|
+
var autoTrackConfig = _this.getAutoTrackConfig();
|
|
2277
2379
|
|
|
2278
|
-
if (
|
|
2279
|
-
|
|
2380
|
+
if (autoTrackConfig.view) {
|
|
2381
|
+
if (!!_this.initConfig.isTrackSinglePage) {
|
|
2382
|
+
_this.rewriteHistory();
|
|
2280
2383
|
|
|
2281
|
-
|
|
2282
|
-
_this.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u961F\u5217\u5DF2\u6EE1\uFF0C\u5DF2\u79FB\u9664\u6700\u65E7\u7684\u6570\u636E\uFF08\u6700\u5927\u9650\u5236: " + maxSize + "\uFF09");
|
|
2384
|
+
_this.addSinglePageEvent(_this.onPageViewCallback);
|
|
2283
2385
|
}
|
|
2284
2386
|
|
|
2285
|
-
_this.
|
|
2286
|
-
|
|
2287
|
-
|
|
2387
|
+
_this.each(["load", "beforeunload"], function (historyType) {
|
|
2388
|
+
_this.addEventListener(window, historyType, _this.onPageViewCallback);
|
|
2389
|
+
});
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
if (autoTrackConfig.click) {
|
|
2393
|
+
_this.addEventListener(window, "click", _this.onClickCallback);
|
|
2288
2394
|
}
|
|
2289
2395
|
};
|
|
2290
|
-
/**
|
|
2291
|
-
* 从 LocalStorage 恢复待发送请求
|
|
2292
|
-
*/
|
|
2293
2396
|
|
|
2397
|
+
_this.unlistener = function () {
|
|
2398
|
+
if (!!_this.initConfig.isTrackSinglePage) {
|
|
2399
|
+
var historyPushState = window.history.pushState;
|
|
2400
|
+
var singlePageEvent = !!historyPushState ? "popstate" : "hashchange";
|
|
2401
|
+
|
|
2402
|
+
_this.each(["pushState", "replaceState", singlePageEvent], function (historyName) {
|
|
2403
|
+
_this.removeEventListener(window, historyName, _this.onPageViewCallback);
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
_this.each(["load", "beforeunload"], function (historyType) {
|
|
2408
|
+
_this.removeEventListener(window, historyType, _this.onPageViewCallback);
|
|
2409
|
+
});
|
|
2294
2410
|
|
|
2295
|
-
|
|
2296
|
-
var pendingRequests = _this.getPendingRequestsFromStorage();
|
|
2411
|
+
_this.removeEventListener(window, "click", _this.onClickCallback);
|
|
2297
2412
|
|
|
2298
|
-
|
|
2299
|
-
if (_this.initConfig.showLog) {
|
|
2300
|
-
_this.printLog("\u4ECE LocalStorage \u6062\u590D " + pendingRequests.length + " \u6761\u5F85\u53D1\u9001\u8BF7\u6C42");
|
|
2301
|
-
} // 注意:恢复后不立即发送,避免重复
|
|
2302
|
-
// 数据会留在 LocalStorage 中,等待下次正常发送或页面卸载时发送
|
|
2303
|
-
// 这样可以避免与批量队列冲突
|
|
2413
|
+
_this.batchSender.clearTimer();
|
|
2304
2414
|
|
|
2305
|
-
|
|
2415
|
+
_this.pageDurationTracker.stop();
|
|
2306
2416
|
};
|
|
2307
|
-
/**
|
|
2308
|
-
* 检查页面是否即将卸载
|
|
2309
|
-
* @returns 如果页面即将卸载返回 true,否则返回 false
|
|
2310
|
-
*/
|
|
2311
2417
|
|
|
2418
|
+
_this.clearBatchTimer = function () {
|
|
2419
|
+
_this.batchSender.clearTimer();
|
|
2420
|
+
};
|
|
2312
2421
|
|
|
2313
|
-
_this.
|
|
2314
|
-
|
|
2422
|
+
_this.clearBatchQueue = function () {
|
|
2423
|
+
_this.batchSender.clearQueue();
|
|
2315
2424
|
};
|
|
2316
|
-
/**
|
|
2317
|
-
* 使用 sendBeacon 发送数据(页面卸载时的备用方案)
|
|
2318
|
-
* @param params 数据参数
|
|
2319
|
-
* @param serverUrl 服务器地址
|
|
2320
|
-
* @param contentType 内容类型
|
|
2321
|
-
* @returns 是否发送成功
|
|
2322
|
-
*/
|
|
2323
2425
|
|
|
2426
|
+
_this.setPageKey = function (pageKey, autoUpdate) {
|
|
2427
|
+
if (autoUpdate === void 0) {
|
|
2428
|
+
autoUpdate = false;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
if (pageKey === null || pageKey === "") {
|
|
2432
|
+
_this.useCustomPageKey = false;
|
|
2433
|
+
var pathname = window.location.pathname;
|
|
2434
|
+
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2324
2435
|
|
|
2325
|
-
_this.sendWithBeacon = function (params, serverUrl, contentType) {
|
|
2326
|
-
try {
|
|
2327
|
-
var blob = new Blob([JSON.stringify(params)], {
|
|
2328
|
-
type: contentType || "application/json"
|
|
2329
|
-
});
|
|
2330
|
-
return navigator.sendBeacon(serverUrl, blob);
|
|
2331
|
-
} catch (e) {
|
|
2332
2436
|
if (_this.initConfig.showLog) {
|
|
2333
|
-
_this.printLog("
|
|
2437
|
+
_this.printLog("\u9875\u9762\u6807\u8BC6\u5DF2\u6062\u590D\u81EA\u52A8\u751F\u6210: " + _this.pageKey);
|
|
2334
2438
|
}
|
|
2439
|
+
} else {
|
|
2440
|
+
_this.pageKey = pageKey;
|
|
2441
|
+
_this.useCustomPageKey = !autoUpdate;
|
|
2335
2442
|
|
|
2336
|
-
|
|
2443
|
+
if (_this.initConfig.showLog) {
|
|
2444
|
+
_this.printLog("\u9875\u9762\u6807\u8BC6\u5DF2\u8BBE\u7F6E\u4E3A: " + pageKey + ", \u81EA\u52A8\u66F4\u65B0: " + autoUpdate);
|
|
2445
|
+
}
|
|
2337
2446
|
}
|
|
2338
2447
|
};
|
|
2339
|
-
/**
|
|
2340
|
-
* 刷新待发送的单个请求(正常情况下的发送)
|
|
2341
|
-
* 注意:这个方法会直接使用 ajax 发送,避免通过 sendData 导致重复
|
|
2342
|
-
*/
|
|
2343
2448
|
|
|
2449
|
+
_this.getPageKey = function () {
|
|
2450
|
+
return _this.pageKey;
|
|
2451
|
+
};
|
|
2344
2452
|
|
|
2345
|
-
_this.
|
|
2346
|
-
var
|
|
2453
|
+
_this.onClickCallback = function (e) {
|
|
2454
|
+
var _a;
|
|
2347
2455
|
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2456
|
+
var target = e.target;
|
|
2457
|
+
if (!((_a = target === null || target === void 0 ? void 0 : target.dataset) === null || _a === void 0 ? void 0 : _a.partKey)) return;
|
|
2458
|
+
var position = [e.pageX, e.pageY];
|
|
2459
|
+
var id = target.id;
|
|
2460
|
+
var className = target.className;
|
|
2351
2461
|
|
|
2462
|
+
var business = _this.extractDataAttributes(target);
|
|
2352
2463
|
|
|
2353
|
-
_this.
|
|
2464
|
+
var desc = target.getAttribute("data-desc") || _this.eventDescMap["WebClick"];
|
|
2354
2465
|
|
|
2466
|
+
var partKey = target.getAttribute("data-part-key");
|
|
2467
|
+
var pageKey = target.getAttribute("data-page-key") || undefined;
|
|
2355
2468
|
|
|
2356
|
-
var
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2469
|
+
var params = _this.getParams({
|
|
2470
|
+
event: "WebClick",
|
|
2471
|
+
desc: desc,
|
|
2472
|
+
itemKey: _this.getItemKey(partKey, pageKey),
|
|
2473
|
+
privateParamMap: {
|
|
2474
|
+
business: business,
|
|
2475
|
+
targetEle: {
|
|
2476
|
+
nodeName: target.nodeName,
|
|
2477
|
+
id: id,
|
|
2478
|
+
className: className,
|
|
2479
|
+
position: position
|
|
2367
2480
|
}
|
|
2368
|
-
|
|
2369
|
-
return;
|
|
2370
2481
|
}
|
|
2371
|
-
|
|
2372
|
-
if (showLog) {
|
|
2373
|
-
_this.printLog(params);
|
|
2374
|
-
} // 直接使用 ajax 发送
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
_this.ajax({
|
|
2378
|
-
header: initHeader,
|
|
2379
|
-
url: serverUrl,
|
|
2380
|
-
type: "POST",
|
|
2381
|
-
data: JSON.stringify(params),
|
|
2382
|
-
contentType: contentType,
|
|
2383
|
-
credentials: false,
|
|
2384
|
-
timeout: sendTimeout,
|
|
2385
|
-
cors: true,
|
|
2386
|
-
success: function success() {
|
|
2387
|
-
if (showLog) {
|
|
2388
|
-
_this.printLog("待发送请求发送成功");
|
|
2389
|
-
}
|
|
2390
|
-
},
|
|
2391
|
-
error: function error(err) {
|
|
2392
|
-
if (showLog) {
|
|
2393
|
-
_this.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u53D1\u9001\u5931\u8D25\uFF08\u4E0D\u518D\u91CD\u8BD5\uFF09: " + err);
|
|
2394
|
-
}
|
|
2395
|
-
}
|
|
2396
|
-
});
|
|
2397
2482
|
});
|
|
2398
|
-
};
|
|
2399
|
-
/**
|
|
2400
|
-
* 设置页面卸载监听器,确保数据发送
|
|
2401
|
-
*/
|
|
2402
2483
|
|
|
2484
|
+
_this.sendData(params);
|
|
2485
|
+
};
|
|
2403
2486
|
|
|
2404
|
-
_this.
|
|
2405
|
-
|
|
2406
|
-
if (_this.isUnloadListenerSetup) {
|
|
2407
|
-
return;
|
|
2408
|
-
}
|
|
2487
|
+
_this.onPageViewCallback = function (e) {
|
|
2488
|
+
var _a, _b;
|
|
2409
2489
|
|
|
2410
|
-
|
|
2490
|
+
var ORGIN = window.location.origin;
|
|
2411
2491
|
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2492
|
+
var params = _this.getParams({
|
|
2493
|
+
event: "PageView",
|
|
2494
|
+
desc: _this.eventDescMap["PageView"],
|
|
2495
|
+
privateParamMap: {
|
|
2496
|
+
currentUrl: _this.currentUrl,
|
|
2497
|
+
targetUrl: ((_a = e.arguments) === null || _a === void 0 ? void 0 : _a[2]) ? ORGIN + ((_b = e.arguments) === null || _b === void 0 ? void 0 : _b[2]) : null
|
|
2415
2498
|
}
|
|
2416
|
-
}); // 使用 beforeunload 事件作为备用(页面关闭/刷新)
|
|
2417
|
-
|
|
2418
|
-
window.addEventListener("beforeunload", function () {
|
|
2419
|
-
_this.flushPendingData();
|
|
2420
|
-
}); // 使用 pagehide 事件(更可靠,支持移动端)
|
|
2421
|
-
|
|
2422
|
-
window.addEventListener("pagehide", function () {
|
|
2423
|
-
_this.flushPendingData();
|
|
2424
2499
|
});
|
|
2425
|
-
}; // 标记是否正在刷新待发送数据,避免重复发送
|
|
2426
|
-
|
|
2427
2500
|
|
|
2428
|
-
|
|
2429
|
-
/**
|
|
2430
|
-
* 刷新待发送数据(在页面卸载/跳转时调用)
|
|
2431
|
-
*/
|
|
2501
|
+
_this.currentUrl = window.location.href;
|
|
2432
2502
|
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
return;
|
|
2437
|
-
} // 页面卸载时停止定时器
|
|
2503
|
+
if (!_this.useCustomPageKey) {
|
|
2504
|
+
_this.pageKey = window.location.pathname.replace(/\//g, "_").substring(1);
|
|
2505
|
+
}
|
|
2438
2506
|
|
|
2507
|
+
var autoTrackConfig = _this.getAutoTrackConfig();
|
|
2439
2508
|
|
|
2440
|
-
|
|
2509
|
+
if (autoTrackConfig.retained) {
|
|
2510
|
+
_this.pageDurationTracker.stop();
|
|
2441
2511
|
|
|
2512
|
+
_this.pageDurationTracker.start();
|
|
2513
|
+
}
|
|
2442
2514
|
|
|
2443
|
-
|
|
2515
|
+
_this.sendData(params);
|
|
2516
|
+
};
|
|
2444
2517
|
|
|
2445
|
-
|
|
2518
|
+
_this.getParams = function (_a) {
|
|
2519
|
+
var event = _a.event,
|
|
2520
|
+
desc = _a.desc,
|
|
2521
|
+
_b = _a.privateParamMap,
|
|
2522
|
+
privateParamMap = _b === void 0 ? {} : _b,
|
|
2523
|
+
itemKey = _a.itemKey;
|
|
2524
|
+
var business = _this.initConfig.business;
|
|
2525
|
+
var pageWidth = window.innerWidth;
|
|
2526
|
+
var pageHeight = window.innerHeight;
|
|
2527
|
+
var screenWidth = window.screen.width;
|
|
2528
|
+
var screenHeight = window.screen.height;
|
|
2446
2529
|
|
|
2447
|
-
|
|
2448
|
-
allPendingData.push.apply(allPendingData, batchQueue);
|
|
2449
|
-
} // 如果有待发送的单个请求,也添加到列表
|
|
2530
|
+
var filteredBusiness = _this.filterSensitiveData(business || {});
|
|
2450
2531
|
|
|
2532
|
+
var filteredUserInfo = _this.filterSensitiveData(_this.userInfo || {});
|
|
2451
2533
|
|
|
2452
|
-
var
|
|
2534
|
+
var filteredPrivateParamMap = _this.filterSensitiveData(privateParamMap || {});
|
|
2453
2535
|
|
|
2454
|
-
|
|
2455
|
-
allPendingData.push.apply(allPendingData, pendingRequests);
|
|
2456
|
-
}
|
|
2536
|
+
var filteredUrlParams = _this.filterSensitiveData(_this.getQueryValue() || {});
|
|
2457
2537
|
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2538
|
+
var privateParamMapData = {
|
|
2539
|
+
currentUrl: filteredPrivateParamMap.currentUrl || _this.currentUrl,
|
|
2540
|
+
business: Object.assign({}, filteredBusiness, filteredPrivateParamMap.business || {}),
|
|
2541
|
+
pageWidth: pageWidth,
|
|
2542
|
+
pageHeight: pageHeight,
|
|
2543
|
+
screenWidth: screenWidth,
|
|
2544
|
+
screenHeight: screenHeight,
|
|
2545
|
+
sdkVersion: _this.sdkVersion,
|
|
2546
|
+
systemsInfo: _this.systemsInfo,
|
|
2547
|
+
urlParams: filteredUrlParams,
|
|
2548
|
+
userInfo: filteredUserInfo,
|
|
2549
|
+
deviceId: _this.deviceId
|
|
2550
|
+
};
|
|
2461
2551
|
|
|
2552
|
+
if (filteredPrivateParamMap.targetEle) {
|
|
2553
|
+
privateParamMapData.targetEle = filteredPrivateParamMap.targetEle;
|
|
2554
|
+
}
|
|
2462
2555
|
|
|
2463
|
-
|
|
2556
|
+
if (filteredPrivateParamMap.targetUrl) {
|
|
2557
|
+
privateParamMapData.targetUrl = filteredPrivateParamMap.targetUrl;
|
|
2558
|
+
}
|
|
2464
2559
|
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
} else {
|
|
2469
|
-
_this.setLocalStorage(_this.PENDING_REQUESTS_STORAGE_KEY, JSON.stringify(allPendingData));
|
|
2470
|
-
}
|
|
2471
|
-
} catch (e) {
|
|
2472
|
-
if (_this.initConfig.showLog) {
|
|
2473
|
-
_this.printLog("\u4FDD\u5B58\u5F85\u53D1\u9001\u8BF7\u6C42\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
2474
|
-
}
|
|
2475
|
-
} // 使用 sendBeacon 发送数据(最可靠的方式)
|
|
2560
|
+
if (filteredPrivateParamMap.pointerType) {
|
|
2561
|
+
privateParamMapData.pointerType = filteredPrivateParamMap.pointerType;
|
|
2562
|
+
}
|
|
2476
2563
|
|
|
2564
|
+
if (filteredPrivateParamMap.elementSelector) {
|
|
2565
|
+
privateParamMapData.elementSelector = filteredPrivateParamMap.elementSelector;
|
|
2566
|
+
}
|
|
2477
2567
|
|
|
2478
|
-
if (
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
var dataToSend = allPendingData.length === 1 ? allPendingData[0] : allPendingData;
|
|
2482
|
-
var blob = new Blob([JSON.stringify(dataToSend)], {
|
|
2483
|
-
type: _this.initConfig.contentType || "application/json"
|
|
2484
|
-
});
|
|
2485
|
-
var sent = navigator.sendBeacon(_this.initConfig.serverUrl, blob);
|
|
2568
|
+
if (filteredPrivateParamMap.retainedDuration) {
|
|
2569
|
+
privateParamMapData.retainedDuration = filteredPrivateParamMap.retainedDuration;
|
|
2570
|
+
}
|
|
2486
2571
|
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2572
|
+
if (filteredPrivateParamMap.exposureScreenNo !== undefined) {
|
|
2573
|
+
privateParamMapData.exposureScreenNo = filteredPrivateParamMap.exposureScreenNo;
|
|
2574
|
+
}
|
|
2490
2575
|
|
|
2491
|
-
|
|
2576
|
+
return {
|
|
2577
|
+
event: event,
|
|
2578
|
+
desc: desc,
|
|
2579
|
+
itemKey: itemKey || _this.getItemKey(),
|
|
2580
|
+
requestTime: _this.getTimeStamp(),
|
|
2581
|
+
privateParamMap: privateParamMapData
|
|
2582
|
+
};
|
|
2583
|
+
};
|
|
2492
2584
|
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
_this.printLog("sendBeacon \u8FD4\u56DE false\uFF0C\u6570\u636E\u5DF2\u4FDD\u5B58\u5230 LocalStorage \u7B49\u5F85\u4E0B\u6B21\u6062\u590D");
|
|
2500
|
-
}
|
|
2501
|
-
}
|
|
2502
|
-
} catch (e) {
|
|
2503
|
-
// sendBeacon 失败,数据已在 LocalStorage 中,等待下次恢复
|
|
2504
|
-
if (_this.initConfig.showLog) {
|
|
2505
|
-
_this.printLog("\u9875\u9762\u5378\u8F7D\u65F6\u53D1\u9001\u6570\u636E\u5931\u8D25: " + e + "\uFF0C\u6570\u636E\u5DF2\u4FDD\u5B58\u5230 LocalStorage");
|
|
2506
|
-
}
|
|
2507
|
-
} finally {
|
|
2508
|
-
// 重置标记
|
|
2509
|
-
_this.isFlushingPendingData = false;
|
|
2510
|
-
}
|
|
2511
|
-
} else {
|
|
2512
|
-
// 不支持 sendBeacon,数据已在 LocalStorage 中,等待下次恢复
|
|
2513
|
-
if (_this.initConfig.showLog) {
|
|
2514
|
-
_this.printLog("\u4E0D\u652F\u6301 sendBeacon\uFF0C\u6570\u636E\u5DF2\u4FDD\u5B58\u5230 LocalStorage \u7B49\u5F85\u4E0B\u6B21\u6062\u590D");
|
|
2515
|
-
} // 重置标记
|
|
2585
|
+
_this.shouldSample = function () {
|
|
2586
|
+
var sampleRate = _this.initConfig.sampleRate;
|
|
2587
|
+
if (sampleRate >= 1) return true;
|
|
2588
|
+
if (sampleRate <= 0) return false;
|
|
2589
|
+
return Math.random() < sampleRate;
|
|
2590
|
+
};
|
|
2516
2591
|
|
|
2592
|
+
_this.shouldUseBeacon = function (sendMethod, header, initHeader) {
|
|
2593
|
+
if (sendMethod === "beacon") return true;
|
|
2594
|
+
if (sendMethod === "xhr") return false;
|
|
2517
2595
|
|
|
2518
|
-
|
|
2596
|
+
if (header || initHeader) {
|
|
2597
|
+
return false;
|
|
2519
2598
|
}
|
|
2520
|
-
};
|
|
2521
|
-
/**
|
|
2522
|
-
* 发送数据通用函数
|
|
2523
|
-
*/
|
|
2524
2599
|
|
|
2600
|
+
return typeof navigator.sendBeacon === "function";
|
|
2601
|
+
};
|
|
2525
2602
|
|
|
2526
2603
|
_this.sendData = function (params, header) {
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
});
|
|
2533
|
-
}
|
|
2604
|
+
return new Promise(function (resolve, reject) {
|
|
2605
|
+
if (!_this.shouldSample()) {
|
|
2606
|
+
if (_this.initConfig.showLog) {
|
|
2607
|
+
_this.printLog("数据已采样跳过");
|
|
2608
|
+
}
|
|
2534
2609
|
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
batchSend = _a.batchSend,
|
|
2542
|
-
sendMethod = _a.sendMethod;
|
|
2543
|
-
if (!!showLog) _this.printLog(params); // 如果启用批量发送
|
|
2610
|
+
resolve({
|
|
2611
|
+
success: false,
|
|
2612
|
+
message: "数据已采样跳过"
|
|
2613
|
+
});
|
|
2614
|
+
return;
|
|
2615
|
+
}
|
|
2544
2616
|
|
|
2545
|
-
|
|
2546
|
-
|
|
2617
|
+
if (_this.initConfig.showLog) {
|
|
2618
|
+
_this.printLog(params);
|
|
2619
|
+
}
|
|
2547
2620
|
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
message: "已添加到批量队列"
|
|
2551
|
-
});
|
|
2552
|
-
} // 判断是否使用 sendBeacon
|
|
2621
|
+
if (_this.initConfig.batchSend) {
|
|
2622
|
+
_this.batchSender.addToQueue(params);
|
|
2553
2623
|
|
|
2624
|
+
resolve({
|
|
2625
|
+
success: true,
|
|
2626
|
+
message: "数据已加入批量队列"
|
|
2627
|
+
});
|
|
2628
|
+
return;
|
|
2629
|
+
}
|
|
2554
2630
|
|
|
2555
|
-
|
|
2631
|
+
var _a = _this.initConfig,
|
|
2632
|
+
serverUrl = _a.serverUrl,
|
|
2633
|
+
sendTimeout = _a.sendTimeout,
|
|
2634
|
+
contentType = _a.contentType,
|
|
2635
|
+
showLog = _a.showLog,
|
|
2636
|
+
initHeader = _a.header;
|
|
2556
2637
|
|
|
2638
|
+
var useBeacon = _this.shouldUseBeacon(_this.initConfig.sendMethod, header, initHeader);
|
|
2557
2639
|
|
|
2558
|
-
|
|
2559
|
-
// 检查页面是否即将卸载,如果是,直接使用 sendBeacon 发送,避免被取消
|
|
2560
|
-
if (_this.isPageUnloading()) {
|
|
2640
|
+
if (useBeacon) {
|
|
2561
2641
|
var sent = _this.sendWithBeacon(params, serverUrl, contentType);
|
|
2562
2642
|
|
|
2563
2643
|
if (sent) {
|
|
2564
|
-
|
|
2644
|
+
resolve({
|
|
2565
2645
|
success: true,
|
|
2566
|
-
message: "
|
|
2646
|
+
message: "数据发送成功"
|
|
2567
2647
|
});
|
|
2568
2648
|
} else {
|
|
2569
|
-
|
|
2570
|
-
_this.addToPendingRequests(params);
|
|
2649
|
+
_this.pendingRequestsManager.addToQueue(params);
|
|
2571
2650
|
|
|
2572
|
-
|
|
2573
|
-
success:
|
|
2574
|
-
message: "
|
|
2651
|
+
resolve({
|
|
2652
|
+
success: false,
|
|
2653
|
+
message: "sendBeacon 发送失败,数据已加入待发送队列"
|
|
2575
2654
|
});
|
|
2576
2655
|
}
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
return _this.sendBeacon({
|
|
2581
|
-
contentType: contentType,
|
|
2582
|
-
url: serverUrl,
|
|
2583
|
-
data: params
|
|
2584
|
-
}).catch(function (err) {
|
|
2585
|
-
// sendBeacon 失败,添加到待发送队列,避免数据丢失
|
|
2586
|
-
_this.addToPendingRequests(params);
|
|
2587
|
-
|
|
2588
|
-
return Promise.resolve({
|
|
2589
|
-
success: true,
|
|
2590
|
-
message: "sendBeacon 失败,已添加到待发送队列"
|
|
2591
|
-
});
|
|
2592
|
-
});
|
|
2593
|
-
} else {
|
|
2594
|
-
// 使用 XMLHttpRequest 发送
|
|
2595
|
-
return new Promise(function (resolve, reject) {
|
|
2596
|
-
// 如果页面即将卸载且配置为 auto,尝试使用 sendBeacon 作为备用
|
|
2597
|
-
if (_this.isPageUnloading() && sendMethod === 'auto' && _this.isSupportBeaconSend() && !header && !initHeader) {
|
|
2598
|
-
var sent = _this.sendWithBeacon(params, serverUrl, contentType);
|
|
2599
|
-
|
|
2600
|
-
if (sent) {
|
|
2601
|
-
resolve({
|
|
2602
|
-
success: true,
|
|
2603
|
-
message: "页面卸载时使用 sendBeacon 发送成功"
|
|
2604
|
-
});
|
|
2605
|
-
return;
|
|
2606
|
-
} // sendBeacon 失败,继续使用 XMLHttpRequest
|
|
2607
|
-
|
|
2608
|
-
}
|
|
2609
|
-
|
|
2656
|
+
} else {
|
|
2610
2657
|
_this.ajax({
|
|
2611
|
-
header: header || initHeader,
|
|
2612
2658
|
url: serverUrl,
|
|
2613
2659
|
type: "POST",
|
|
2614
2660
|
data: JSON.stringify(params),
|
|
2615
2661
|
contentType: contentType,
|
|
2662
|
+
header: header || initHeader,
|
|
2616
2663
|
credentials: false,
|
|
2617
2664
|
timeout: sendTimeout,
|
|
2618
2665
|
cors: true,
|
|
2619
|
-
success: function success(
|
|
2620
|
-
|
|
2666
|
+
success: function success(data) {
|
|
2667
|
+
if (showLog) {
|
|
2668
|
+
_this.printLog("数据发送成功", data);
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
resolve({
|
|
2621
2672
|
success: true,
|
|
2622
|
-
data:
|
|
2673
|
+
data: data
|
|
2623
2674
|
});
|
|
2624
2675
|
},
|
|
2625
|
-
error: function error(err
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
var sent = _this.sendWithBeacon(params, serverUrl, contentType);
|
|
2629
|
-
|
|
2630
|
-
if (sent) {
|
|
2631
|
-
resolve({
|
|
2632
|
-
success: true,
|
|
2633
|
-
message: "XMLHttpRequest 失败,已使用 sendBeacon 发送"
|
|
2634
|
-
});
|
|
2635
|
-
return;
|
|
2636
|
-
}
|
|
2676
|
+
error: function error(err) {
|
|
2677
|
+
if (showLog) {
|
|
2678
|
+
_this.printLog("数据发送失败", err);
|
|
2637
2679
|
}
|
|
2638
2680
|
|
|
2681
|
+
_this.pendingRequestsManager.addToQueue(params);
|
|
2682
|
+
|
|
2639
2683
|
reject({
|
|
2640
2684
|
success: false,
|
|
2641
|
-
message:
|
|
2642
|
-
|
|
2685
|
+
message: "数据发送失败",
|
|
2686
|
+
error: err
|
|
2643
2687
|
});
|
|
2644
2688
|
}
|
|
2645
2689
|
});
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
};
|
|
2649
|
-
/**
|
|
2650
|
-
* @description 判断是否应该使用 sendBeacon
|
|
2651
|
-
* @param sendMethod 配置的发送方式
|
|
2652
|
-
* @param header 自定义 header
|
|
2653
|
-
* @param initHeader 初始化配置的 header
|
|
2654
|
-
* @returns 是否使用 sendBeacon
|
|
2655
|
-
*/
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
_this.shouldUseBeacon = function (sendMethod, header, initHeader) {
|
|
2659
|
-
// 如果配置为 xhr,不使用 beacon
|
|
2660
|
-
if (sendMethod === 'xhr') {
|
|
2661
|
-
return false;
|
|
2662
|
-
} // 如果配置为 beacon,检查是否支持
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
if (sendMethod === 'beacon') {
|
|
2666
|
-
return _this.isSupportBeaconSend() === true;
|
|
2667
|
-
} // 如果配置为 auto(默认),使用原有逻辑
|
|
2668
|
-
// 只有在支持 sendBeacon 且没有自定义 header 时才使用
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
return _this.isSupportBeaconSend() === true && !header && !initHeader;
|
|
2672
|
-
};
|
|
2673
|
-
/**
|
|
2674
|
-
* @description 留存时长上报
|
|
2675
|
-
* @param type
|
|
2676
|
-
*/
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
_this.sendRetained = function (type) {
|
|
2680
|
-
var params = _this.getParams({
|
|
2681
|
-
event: "PageRetained",
|
|
2682
|
-
desc: _this.eventDescMap["PageRetained"]
|
|
2690
|
+
}
|
|
2683
2691
|
});
|
|
2692
|
+
};
|
|
2684
2693
|
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
var retainedData = __assign(__assign({}, params), {
|
|
2691
|
-
privateParamMap: __assign(__assign({}, params.privateParamMap), {
|
|
2692
|
-
retainedDuration: Math.max(params.requestTime - retainedStartTime, 0)
|
|
2693
|
-
})
|
|
2694
|
+
_this.sendWithBeacon = function (params, serverUrl, contentType) {
|
|
2695
|
+
try {
|
|
2696
|
+
var blob = new Blob([JSON.stringify(params)], {
|
|
2697
|
+
type: contentType || "application/json"
|
|
2694
2698
|
});
|
|
2699
|
+
return navigator.sendBeacon(serverUrl, blob);
|
|
2700
|
+
} catch (e) {
|
|
2701
|
+
if (_this.initConfig.showLog) {
|
|
2702
|
+
_this.printLog("sendBeacon \u53D1\u9001\u5931\u8D25: " + e);
|
|
2703
|
+
}
|
|
2695
2704
|
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
2705
|
+
return false;
|
|
2699
2706
|
}
|
|
2700
2707
|
};
|
|
2701
|
-
/**
|
|
2702
|
-
* @description 用户主动上报页面停留时长
|
|
2703
|
-
* @param duration 自定义停留时长(毫秒),如果不传则自动计算从页面加载(或上次调用)到当前的时长
|
|
2704
|
-
* @param options 可选参数,包括自定义描述、业务参数等
|
|
2705
|
-
* @param resetStartTime 是否重置起始时间,默认 true(手动上报后重置,定时上报不重置)
|
|
2706
|
-
* @returns Promise<TrackingResponse> 上报结果
|
|
2707
|
-
*/
|
|
2708
|
-
|
|
2709
2708
|
|
|
2710
2709
|
_this.trackPageDuration = function (duration, options, resetStartTime) {
|
|
2711
2710
|
if (resetStartTime === void 0) {
|
|
2712
2711
|
resetStartTime = true;
|
|
2713
|
-
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
var retainedDuration;
|
|
2717
|
-
|
|
2718
|
-
if (duration !== undefined && duration !== null) {
|
|
2719
|
-
// 使用自定义时长
|
|
2720
|
-
retainedDuration = Math.max(duration, 0);
|
|
2721
|
-
} else {
|
|
2722
|
-
// 自动计算时长
|
|
2723
|
-
var __time = _this.getCookie("retainedStartTime");
|
|
2724
|
-
|
|
2725
|
-
var retainedStartTime = __time ? +__time : _this.getTimeStamp();
|
|
2726
|
-
|
|
2727
|
-
var currentTime = _this.getTimeStamp();
|
|
2728
|
-
|
|
2729
|
-
retainedDuration = Math.max(currentTime - retainedStartTime, 0);
|
|
2730
|
-
} // 构建参数
|
|
2712
|
+
}
|
|
2731
2713
|
|
|
2714
|
+
var retainedDuration = _this.pageDurationTracker.calculateDuration(duration);
|
|
2732
2715
|
|
|
2733
2716
|
var desc = (options === null || options === void 0 ? void 0 : options.desc) || _this.eventDescMap["PageRetained"];
|
|
2734
2717
|
var pageKey = (options === null || options === void 0 ? void 0 : options.pageKey) || _this.pageKey;
|
|
@@ -2743,12 +2726,9 @@ function (_super) {
|
|
|
2743
2726
|
business: business,
|
|
2744
2727
|
retainedDuration: retainedDuration
|
|
2745
2728
|
}
|
|
2746
|
-
});
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
var result = _this.sendData(params, header); // 根据 resetStartTime 参数决定是否重置起始时间
|
|
2750
|
-
// 手动上报后重置起始时间,定时上报不重置(累积计算)
|
|
2729
|
+
});
|
|
2751
2730
|
|
|
2731
|
+
var result = _this.sendData(params, header);
|
|
2752
2732
|
|
|
2753
2733
|
if (resetStartTime) {
|
|
2754
2734
|
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
@@ -2756,230 +2736,41 @@ function (_super) {
|
|
|
2756
2736
|
|
|
2757
2737
|
return result;
|
|
2758
2738
|
};
|
|
2759
|
-
/**
|
|
2760
|
-
* @description 启动定时上报页面停留时长的定时器
|
|
2761
|
-
*/
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
_this.startPageDurationTimer = function () {
|
|
2765
|
-
// 先停止现有的定时器(避免重复启动)
|
|
2766
|
-
_this.stopPageDurationTimer();
|
|
2767
|
-
|
|
2768
|
-
var interval = _this.initConfig.pageDurationInterval || 30000; // 检查间隔时间是否有效
|
|
2769
|
-
|
|
2770
|
-
if (interval <= 0) {
|
|
2771
|
-
if (_this.initConfig.showLog) {
|
|
2772
|
-
_this.printLog("定时上报间隔时间无效,已禁用定时上报");
|
|
2773
|
-
}
|
|
2774
|
-
|
|
2775
|
-
return;
|
|
2776
|
-
} // 启动定时器
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
_this.pageDurationTimer = window.setInterval(function () {
|
|
2780
|
-
// 只在页面可见时上报(避免后台上报)
|
|
2781
|
-
if (document.visibilityState === "visible") {
|
|
2782
|
-
// 定时上报:retainedDuration 直接使用上报间隔时间,数据工程师会清洗数据
|
|
2783
|
-
_this.trackPageDuration(interval, {
|
|
2784
|
-
desc: "定时上报页面停留时长",
|
|
2785
|
-
business: {
|
|
2786
|
-
reportType: "interval",
|
|
2787
|
-
interval: interval
|
|
2788
|
-
}
|
|
2789
|
-
}, true).catch(function (err) {
|
|
2790
|
-
if (_this.initConfig.showLog) {
|
|
2791
|
-
_this.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5931\u8D25: " + err);
|
|
2792
|
-
}
|
|
2793
|
-
});
|
|
2794
|
-
}
|
|
2795
|
-
}, interval);
|
|
2796
|
-
|
|
2797
|
-
if (_this.initConfig.showLog) {
|
|
2798
|
-
_this.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694: " + interval + "ms");
|
|
2799
|
-
}
|
|
2800
|
-
};
|
|
2801
|
-
/**
|
|
2802
|
-
* @description 停止定时上报页面停留时长的定时器
|
|
2803
|
-
*/
|
|
2804
2739
|
|
|
2740
|
+
_this.getItemKey = function (partKey, pageKey) {
|
|
2741
|
+
var _pageKey = pageKey !== undefined ? pageKey : _this.pageKey;
|
|
2805
2742
|
|
|
2806
|
-
|
|
2807
|
-
if (_this.pageDurationTimer !== null) {
|
|
2808
|
-
clearInterval(_this.pageDurationTimer);
|
|
2809
|
-
_this.pageDurationTimer = null;
|
|
2743
|
+
var _partKey = partKey !== undefined ? partKey : "";
|
|
2810
2744
|
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
}
|
|
2745
|
+
if (_partKey) {
|
|
2746
|
+
return _this.initConfig.appKey + "." + _pageKey + "." + _partKey;
|
|
2814
2747
|
}
|
|
2815
|
-
};
|
|
2816
|
-
/**
|
|
2817
|
-
* @description 获取 itemKey
|
|
2818
|
-
* @param {[string]} partkey [控件/自定义事件的唯一标识]
|
|
2819
|
-
* @return {[string]}
|
|
2820
|
-
*/
|
|
2821
|
-
|
|
2822
2748
|
|
|
2823
|
-
|
|
2824
|
-
var appKey = _this.initConfig.appKey;
|
|
2825
|
-
var keys = [appKey, (pageKey || _this.pageKey).toString(), partkey ? partkey.toString() : undefined].filter(function (key) {
|
|
2826
|
-
return !!key;
|
|
2827
|
-
});
|
|
2828
|
-
return keys.reduce(function (str, key) {
|
|
2829
|
-
return str + ("" + (str.length ? "." : "")) + key;
|
|
2830
|
-
}, "");
|
|
2749
|
+
return _this.initConfig.appKey + "." + _pageKey;
|
|
2831
2750
|
};
|
|
2832
|
-
/**
|
|
2833
|
-
* @description 从元素或其祖先节点提取 data-* 属性
|
|
2834
|
-
* @param element 目标元素
|
|
2835
|
-
* @returns 提取的业务参数对象
|
|
2836
|
-
*/
|
|
2837
|
-
|
|
2838
2751
|
|
|
2839
2752
|
_this.extractDataAttributes = function (element) {
|
|
2840
2753
|
var business = {};
|
|
2841
|
-
var currentElement = element;
|
|
2842
|
-
|
|
2843
|
-
while (currentElement) {
|
|
2844
|
-
var attributes = currentElement.attributes;
|
|
2845
|
-
|
|
2846
|
-
for (var i = 0; i < attributes.length; i++) {
|
|
2847
|
-
var attr = attributes[i];
|
|
2848
|
-
var name_1 = attr.name;
|
|
2849
|
-
|
|
2850
|
-
if (name_1.startsWith('data-') && name_1 !== 'data-exposure' && name_1 !== 'data-part-key' && name_1 !== 'data-desc') {
|
|
2851
|
-
var value = attr.value;
|
|
2852
|
-
|
|
2853
|
-
if (value) {
|
|
2854
|
-
var camelCaseKey = name_1.replace(/^data-/, '').split('-').map(function (part, index) {
|
|
2855
|
-
return index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1);
|
|
2856
|
-
}).join('');
|
|
2857
|
-
business[camelCaseKey] = value;
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
|
-
}
|
|
2861
2754
|
|
|
2862
|
-
|
|
2755
|
+
for (var i = 0; i < element.attributes.length; i++) {
|
|
2756
|
+
var name_1 = element.attributes[i].name;
|
|
2863
2757
|
|
|
2864
|
-
if (
|
|
2865
|
-
|
|
2758
|
+
if (name_1.startsWith("data-") && name_1 !== "data-exposure" && name_1 !== "data-part-key" && name_1 !== "data-desc" && name_1 !== "data-page-key") {
|
|
2759
|
+
var key = name_1.replace("data-", "").replace(/-([a-z])/g, function (_, letter) {
|
|
2760
|
+
return letter.toUpperCase();
|
|
2761
|
+
});
|
|
2762
|
+
business[key] = element.getAttribute(name_1);
|
|
2866
2763
|
}
|
|
2867
2764
|
}
|
|
2868
2765
|
|
|
2869
2766
|
return business;
|
|
2870
2767
|
};
|
|
2871
|
-
/**
|
|
2872
|
-
* @description 初始化曝光监听
|
|
2873
|
-
*/
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
_this.initExposureObserver = function () {
|
|
2877
|
-
if (!_this.initConfig.autoTrackExposure) {
|
|
2878
|
-
return;
|
|
2879
|
-
}
|
|
2880
|
-
|
|
2881
|
-
if (!('IntersectionObserver' in window)) {
|
|
2882
|
-
if (_this.initConfig.showLog) {
|
|
2883
|
-
_this.printLog('当前浏览器不支持 IntersectionObserver,无法启用曝光埋点');
|
|
2884
|
-
}
|
|
2885
|
-
|
|
2886
|
-
return;
|
|
2887
|
-
}
|
|
2888
|
-
|
|
2889
|
-
var threshold = _this.initConfig.exposureThreshold || 0.5;
|
|
2890
|
-
_this.exposureObserver = new IntersectionObserver(function (entries) {
|
|
2891
|
-
entries.forEach(function (entry) {
|
|
2892
|
-
var element = entry.target;
|
|
2893
|
-
|
|
2894
|
-
var elementInfo = _this.exposureElementsMap.get(element);
|
|
2895
|
-
|
|
2896
|
-
if (!elementInfo) {
|
|
2897
|
-
return;
|
|
2898
|
-
}
|
|
2899
|
-
|
|
2900
|
-
var exposureTime = _this.initConfig.exposureTime || 500;
|
|
2901
|
-
|
|
2902
|
-
if (entry.isIntersecting) {
|
|
2903
|
-
elementInfo.isVisible = true;
|
|
2904
|
-
elementInfo.visibleStartTime = _this.getTimeStamp();
|
|
2905
|
-
|
|
2906
|
-
if (elementInfo.exposureTimer) {
|
|
2907
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
2908
|
-
}
|
|
2909
|
-
|
|
2910
|
-
elementInfo.exposureTimer = window.setTimeout(function () {
|
|
2911
|
-
if (elementInfo.isVisible) {
|
|
2912
|
-
_this.reportExposure(element);
|
|
2913
|
-
}
|
|
2914
|
-
}, exposureTime);
|
|
2915
|
-
} else {
|
|
2916
|
-
elementInfo.isVisible = false;
|
|
2917
|
-
|
|
2918
|
-
if (elementInfo.exposureTimer) {
|
|
2919
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
2920
|
-
elementInfo.exposureTimer = null;
|
|
2921
|
-
}
|
|
2922
|
-
}
|
|
2923
|
-
});
|
|
2924
|
-
}, {
|
|
2925
|
-
threshold: threshold
|
|
2926
|
-
});
|
|
2927
|
-
|
|
2928
|
-
_this.observeExposureElements();
|
|
2929
|
-
|
|
2930
|
-
_this.initMutationObserver();
|
|
2931
|
-
};
|
|
2932
|
-
/**
|
|
2933
|
-
* @description 添加单个曝光元素到监听
|
|
2934
|
-
* @param element 曝光元素
|
|
2935
|
-
*/
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
_this.addExposureElement = function (element) {
|
|
2939
|
-
if (!_this.exposureElementsMap.has(element)) {
|
|
2940
|
-
_this.exposureElementsMap.set(element, {
|
|
2941
|
-
element: element,
|
|
2942
|
-
visibleStartTime: 0,
|
|
2943
|
-
exposureCount: 0,
|
|
2944
|
-
isVisible: false,
|
|
2945
|
-
exposureTimer: null
|
|
2946
|
-
});
|
|
2947
|
-
|
|
2948
|
-
if (_this.exposureObserver) {
|
|
2949
|
-
_this.exposureObserver.observe(element);
|
|
2950
|
-
}
|
|
2951
|
-
}
|
|
2952
|
-
};
|
|
2953
|
-
/**
|
|
2954
|
-
* @description 监听页面上的曝光元素
|
|
2955
|
-
*/
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
_this.observeExposureElements = function () {
|
|
2959
|
-
if (!_this.exposureObserver) {
|
|
2960
|
-
return;
|
|
2961
|
-
}
|
|
2962
|
-
|
|
2963
|
-
var elements = document.querySelectorAll('[data-exposure="true"]');
|
|
2964
|
-
elements.forEach(function (element) {
|
|
2965
|
-
_this.addExposureElement(element);
|
|
2966
|
-
});
|
|
2967
|
-
|
|
2968
|
-
if (_this.initConfig.showLog && elements.length > 0) {
|
|
2969
|
-
_this.printLog("\u5DF2\u76D1\u542C " + elements.length + " \u4E2A\u66DD\u5149\u5143\u7D20");
|
|
2970
|
-
}
|
|
2971
|
-
};
|
|
2972
|
-
/**
|
|
2973
|
-
* @description 上报曝光事件
|
|
2974
|
-
* @param element 曝光元素
|
|
2975
|
-
*/
|
|
2976
|
-
|
|
2977
2768
|
|
|
2978
|
-
_this.
|
|
2979
|
-
var elementInfo = _this.
|
|
2769
|
+
_this.handleExposureReport = function (element, exposureScreenIndex) {
|
|
2770
|
+
var elementInfo = _this.exposureTracker.getElementInfo(element);
|
|
2980
2771
|
|
|
2981
2772
|
if (!elementInfo) {
|
|
2982
|
-
return;
|
|
2773
|
+
return Promise.resolve();
|
|
2983
2774
|
}
|
|
2984
2775
|
|
|
2985
2776
|
var exposureNum = _this.initConfig.exposureNum;
|
|
@@ -2989,34 +2780,33 @@ function (_super) {
|
|
|
2989
2780
|
_this.printLog("\u5143\u7D20\u5DF2\u8FBE\u5230\u6700\u5927\u66DD\u5149\u6B21\u6570\u9650\u5236: " + exposureNum);
|
|
2990
2781
|
}
|
|
2991
2782
|
|
|
2992
|
-
return;
|
|
2783
|
+
return Promise.resolve();
|
|
2993
2784
|
}
|
|
2994
2785
|
|
|
2995
2786
|
var business = _this.extractDataAttributes(element);
|
|
2996
2787
|
|
|
2997
|
-
var desc = element.getAttribute(
|
|
2788
|
+
var desc = element.getAttribute("data-desc") || _this.eventDescMap["WebExposure"];
|
|
2998
2789
|
|
|
2999
|
-
var
|
|
2790
|
+
var partKey = element.getAttribute("data-part-key") || "exposure";
|
|
2791
|
+
var pageKey = element.getAttribute("data-page-key") || undefined;
|
|
3000
2792
|
|
|
3001
2793
|
var params = _this.getParams({
|
|
3002
|
-
event:
|
|
2794
|
+
event: "WebExposure",
|
|
3003
2795
|
desc: desc,
|
|
3004
|
-
itemKey: _this.getItemKey(
|
|
2796
|
+
itemKey: _this.getItemKey(partKey, pageKey),
|
|
3005
2797
|
privateParamMap: {
|
|
3006
|
-
business: business
|
|
2798
|
+
business: business,
|
|
2799
|
+
exposureScreenNo: exposureScreenIndex
|
|
3007
2800
|
}
|
|
3008
2801
|
});
|
|
3009
2802
|
|
|
3010
|
-
_this.sendData(params).then(function () {
|
|
3011
|
-
|
|
2803
|
+
return _this.sendData(params).then(function () {
|
|
2804
|
+
_this.exposureTracker.incrementExposureCount(element);
|
|
3012
2805
|
|
|
3013
|
-
|
|
3014
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
3015
|
-
elementInfo.exposureTimer = null;
|
|
3016
|
-
}
|
|
2806
|
+
_this.exposureTracker.clearExposureTimer(element);
|
|
3017
2807
|
|
|
3018
2808
|
if (_this.initConfig.showLog) {
|
|
3019
|
-
_this.printLog("\u66DD\u5149\u4E0A\u62A5\u6210\u529F\uFF0C\u5F53\u524D\u66DD\u5149\u6B21\u6570: " + elementInfo.exposureCount);
|
|
2809
|
+
_this.printLog("\u66DD\u5149\u4E0A\u62A5\u6210\u529F\uFF0C\u5F53\u524D\u66DD\u5149\u6B21\u6570: " + (elementInfo.exposureCount + 1));
|
|
3020
2810
|
}
|
|
3021
2811
|
}).catch(function (err) {
|
|
3022
2812
|
if (_this.initConfig.showLog) {
|
|
@@ -3024,81 +2814,8 @@ function (_super) {
|
|
|
3024
2814
|
}
|
|
3025
2815
|
});
|
|
3026
2816
|
};
|
|
3027
|
-
/**
|
|
3028
|
-
* @description 初始化 MutationObserver 监听动态添加的元素
|
|
3029
|
-
*/
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
_this.initMutationObserver = function () {
|
|
3033
|
-
if (!('MutationObserver' in window)) {
|
|
3034
|
-
if (_this.initConfig.showLog) {
|
|
3035
|
-
_this.printLog('当前浏览器不支持 MutationObserver,无法监听动态添加的曝光元素');
|
|
3036
|
-
}
|
|
3037
|
-
|
|
3038
|
-
return;
|
|
3039
|
-
}
|
|
3040
|
-
|
|
3041
|
-
_this.mutationObserver = new MutationObserver(function (mutations) {
|
|
3042
|
-
mutations.forEach(function (mutation) {
|
|
3043
|
-
mutation.addedNodes.forEach(function (node) {
|
|
3044
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
3045
|
-
var element = node;
|
|
3046
|
-
|
|
3047
|
-
if (element.hasAttribute('data-exposure') && element.getAttribute('data-exposure') === 'true') {
|
|
3048
|
-
_this.addExposureElement(element);
|
|
3049
|
-
} else {
|
|
3050
|
-
var exposureElements = element.querySelectorAll('[data-exposure="true"]');
|
|
3051
|
-
exposureElements.forEach(function (exposureElement) {
|
|
3052
|
-
_this.addExposureElement(exposureElement);
|
|
3053
|
-
});
|
|
3054
|
-
}
|
|
3055
|
-
}
|
|
3056
|
-
});
|
|
3057
|
-
});
|
|
3058
|
-
});
|
|
3059
|
-
|
|
3060
|
-
_this.mutationObserver.observe(document.body, {
|
|
3061
|
-
childList: true,
|
|
3062
|
-
subtree: true
|
|
3063
|
-
});
|
|
3064
|
-
|
|
3065
|
-
if (_this.initConfig.showLog) {
|
|
3066
|
-
_this.printLog('MutationObserver 已启动,监听动态添加的曝光元素');
|
|
3067
|
-
}
|
|
3068
|
-
};
|
|
3069
|
-
/**
|
|
3070
|
-
* @description 停止曝光监听
|
|
3071
|
-
*/
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
_this.stopExposureObserver = function () {
|
|
3075
|
-
if (_this.exposureObserver) {
|
|
3076
|
-
_this.exposureObserver.disconnect();
|
|
3077
|
-
|
|
3078
|
-
_this.exposureObserver = null;
|
|
3079
|
-
|
|
3080
|
-
_this.exposureElementsMap.forEach(function (elementInfo) {
|
|
3081
|
-
if (elementInfo.exposureTimer) {
|
|
3082
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
3083
|
-
}
|
|
3084
|
-
});
|
|
3085
|
-
|
|
3086
|
-
_this.exposureElementsMap.clear();
|
|
3087
|
-
}
|
|
3088
|
-
|
|
3089
|
-
if (_this.mutationObserver) {
|
|
3090
|
-
_this.mutationObserver.disconnect();
|
|
3091
|
-
|
|
3092
|
-
_this.mutationObserver = null;
|
|
3093
|
-
}
|
|
3094
|
-
|
|
3095
|
-
if (_this.initConfig.showLog) {
|
|
3096
|
-
_this.printLog('曝光监听已停止');
|
|
3097
|
-
}
|
|
3098
|
-
};
|
|
3099
|
-
|
|
3100
|
-
_this.sdkVersion = "1.2.4"; // sdk版本
|
|
3101
2817
|
|
|
2818
|
+
_this.sdkVersion = "1.2.7";
|
|
3102
2819
|
_this.initConfig = {
|
|
3103
2820
|
appKey: "",
|
|
3104
2821
|
platform: undefined,
|
|
@@ -3114,26 +2831,93 @@ function (_super) {
|
|
|
3114
2831
|
batchSend: false,
|
|
3115
2832
|
batchInterval: 5000,
|
|
3116
2833
|
batchMaxSize: 10,
|
|
3117
|
-
trackPartKeyClick: false,
|
|
3118
2834
|
pendingRequestsMaxSize: 50,
|
|
3119
|
-
autoTrackPageDurationInterval: false,
|
|
3120
2835
|
pageDurationInterval: 30000,
|
|
3121
2836
|
sendMethod: "auto",
|
|
3122
|
-
autoTrackExposure: false,
|
|
3123
2837
|
exposureThreshold: 0.5,
|
|
3124
2838
|
exposureTime: 500,
|
|
3125
|
-
exposureNum: undefined
|
|
3126
|
-
|
|
3127
|
-
}; // 系统信息
|
|
3128
|
-
|
|
2839
|
+
exposureNum: undefined
|
|
2840
|
+
};
|
|
3129
2841
|
_this.systemsInfo = {};
|
|
2842
|
+
_this.deviceManager = new DeviceManager({
|
|
2843
|
+
getCookie: _this.getCookie.bind(_this),
|
|
2844
|
+
setCookie: _this.setCookie.bind(_this),
|
|
2845
|
+
getLocalStorage: _this.getLocalStorage.bind(_this),
|
|
2846
|
+
setLocalStorage: _this.setLocalStorage.bind(_this),
|
|
2847
|
+
collectFingerprint: _this.collectFingerprint.bind(_this),
|
|
2848
|
+
hashFingerprint: _this.hashFingerprint.bind(_this)
|
|
2849
|
+
});
|
|
2850
|
+
_this.batchSender = new BatchSender({
|
|
2851
|
+
batchSend: false,
|
|
2852
|
+
batchInterval: 5000,
|
|
2853
|
+
batchMaxSize: 10,
|
|
2854
|
+
sendTimeout: 3000,
|
|
2855
|
+
serverUrl: "",
|
|
2856
|
+
contentType: "application/json",
|
|
2857
|
+
showLog: false,
|
|
2858
|
+
sendMethod: "auto",
|
|
2859
|
+
header: undefined
|
|
2860
|
+
}, {
|
|
2861
|
+
getLocalStorage: _this.getLocalStorage.bind(_this),
|
|
2862
|
+
setLocalStorage: _this.setLocalStorage.bind(_this),
|
|
2863
|
+
getTimeStamp: _this.getTimeStamp.bind(_this),
|
|
2864
|
+
ajax: _this.ajax.bind(_this),
|
|
2865
|
+
shouldSample: _this.shouldSample.bind(_this),
|
|
2866
|
+
shouldUseBeacon: _this.shouldUseBeacon.bind(_this),
|
|
2867
|
+
printLog: _this.printLog.bind(_this)
|
|
2868
|
+
});
|
|
2869
|
+
_this.pendingRequestsManager = new PendingRequestsManager({
|
|
2870
|
+
pendingRequestsMaxSize: 50,
|
|
2871
|
+
sendTimeout: 3000,
|
|
2872
|
+
serverUrl: "",
|
|
2873
|
+
contentType: "application/json",
|
|
2874
|
+
showLog: false,
|
|
2875
|
+
header: undefined
|
|
2876
|
+
}, {
|
|
2877
|
+
getLocalStorage: _this.getLocalStorage.bind(_this),
|
|
2878
|
+
setLocalStorage: _this.setLocalStorage.bind(_this),
|
|
2879
|
+
shouldSample: _this.shouldSample.bind(_this),
|
|
2880
|
+
ajax: _this.ajax.bind(_this),
|
|
2881
|
+
printLog: _this.printLog.bind(_this)
|
|
2882
|
+
});
|
|
2883
|
+
_this.pageDurationTracker = new PageDurationTracker({
|
|
2884
|
+
pageDurationInterval: 30000,
|
|
2885
|
+
showLog: false
|
|
2886
|
+
}, {
|
|
2887
|
+
getCookie: _this.getCookie.bind(_this),
|
|
2888
|
+
setCookie: _this.setCookie.bind(_this),
|
|
2889
|
+
getTimeStamp: _this.getTimeStamp.bind(_this),
|
|
2890
|
+
track: _this.trackPageDuration.bind(_this),
|
|
2891
|
+
printLog: _this.printLog.bind(_this)
|
|
2892
|
+
});
|
|
2893
|
+
_this.exposureTracker = new ExposureTracker({
|
|
2894
|
+
autoTrackExposure: false,
|
|
2895
|
+
exposureThreshold: 0.5,
|
|
2896
|
+
exposureTime: 500,
|
|
2897
|
+
exposureNum: undefined,
|
|
2898
|
+
showLog: false
|
|
2899
|
+
}, {
|
|
2900
|
+
reportExposure: _this.handleExposureReport.bind(_this),
|
|
2901
|
+
printLog: _this.printLog.bind(_this),
|
|
2902
|
+
getTimeStamp: _this.getTimeStamp.bind(_this),
|
|
2903
|
+
extractDataAttributes: _this.extractDataAttributes.bind(_this)
|
|
2904
|
+
});
|
|
3130
2905
|
return _this;
|
|
3131
2906
|
}
|
|
3132
|
-
/**
|
|
3133
|
-
* @description 添加单页面监听事件
|
|
3134
|
-
* @param callback
|
|
3135
|
-
*/
|
|
3136
2907
|
|
|
2908
|
+
WebTracking.prototype.printLog = function () {
|
|
2909
|
+
var rest = [];
|
|
2910
|
+
|
|
2911
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2912
|
+
rest[_i] = arguments[_i];
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
if (!this.initConfig.showLog) {
|
|
2916
|
+
return;
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
_super.prototype.printLog.apply(this, rest);
|
|
2920
|
+
};
|
|
3137
2921
|
|
|
3138
2922
|
WebTracking.prototype.addSinglePageEvent = function (callback) {
|
|
3139
2923
|
var _this = this;
|