@fle-sdk/event-tracking-web 1.2.3 → 1.2.5
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/README.md +122 -2
- package/lib/index.esm.js +324 -4
- package/lib/index.esm.min.js +1 -1
- package/lib/index.js +324 -4
- package/lib/index.min.js +1 -1
- package/lib/types/index.d.ts +36 -1
- package/lib/types/type.d.ts +46 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
> **构建用户数据体系,让用户行为数据发挥深远的价值。**
|
|
2
2
|
|
|
3
|
-
**当前版本**: v1.2.
|
|
3
|
+
**当前版本**: v1.2.4
|
|
4
4
|
|
|
5
5
|
## 前言
|
|
6
6
|
|
|
@@ -209,6 +209,10 @@ WebTracking
|
|
|
209
209
|
| sendMethod | string | 数据发送方式:auto(自动选择)、xhr(XMLHttpRequest)、beacon(sendBeacon) | 否 | auto |
|
|
210
210
|
| autoTrackPageDurationInterval | boolean | 是否定时上报页面停留时长 | 否 | false |
|
|
211
211
|
| pageDurationInterval | number | 定时上报页面停留时长的间隔时间(毫秒) | 否 | 30000 |
|
|
212
|
+
| autoTrackExposure | boolean | 是否启用曝光埋点 | 否 | false |
|
|
213
|
+
| exposureThreshold | number | 曝光进入可视区判定阈值(0-1之间) | 否 | 0.5 |
|
|
214
|
+
| exposureTime | number | 曝光可见停留时长阈值(毫秒) | 否 | 500 |
|
|
215
|
+
| exposureNum | number | 同一元素允许上报的最大曝光次数(不传则不限制) | 否 | 不限制 |
|
|
212
216
|
| pageKey | string | 自定义页面唯一标识,如果不传则自动从路由获取 | 否 | 自动生成 |
|
|
213
217
|
|
|
214
218
|
#### 例子
|
|
@@ -276,6 +280,10 @@ export default App;
|
|
|
276
280
|
| sendMethod | string | 数据发送方式:auto(自动选择)、xhr(XMLHttpRequest)、beacon(sendBeacon) | 否 | auto |
|
|
277
281
|
| autoTrackPageDurationInterval | boolean | 是否定时上报页面停留时长 | 否 | false |
|
|
278
282
|
| pageDurationInterval | number | 定时上报页面停留时长的间隔时间(毫秒) | 否 | 30000 |
|
|
283
|
+
| autoTrackExposure | boolean | 是否启用曝光埋点 | 否 | false |
|
|
284
|
+
| exposureThreshold | number | 曝光进入可视区判定阈值(0-1之间) | 否 | 0.5 |
|
|
285
|
+
| exposureTime | number | 曝光可见停留时长阈值(毫秒) | 否 | 500 |
|
|
286
|
+
| exposureNum | number | 同一元素允许上报的最大曝光次数(不传则不限制) | 否 | 不限制 |
|
|
279
287
|
| pageKey | string | 自定义页面唯一标识,如果不传则自动从路由获取 | 否 | 自动生成 |
|
|
280
288
|
|
|
281
289
|
#### 例子
|
|
@@ -969,11 +977,123 @@ WebTracking.init({
|
|
|
969
977
|
|
|
970
978
|
两种方式可以同时使用,互不冲突。
|
|
971
979
|
|
|
980
|
+
### 5.8 元素曝光埋点
|
|
981
|
+
|
|
982
|
+
SDK 支持自动监听元素曝光事件,适用于需要追踪元素可见性的场景(如商品卡片曝光、广告曝光等)。
|
|
983
|
+
|
|
984
|
+
#### 触发条件
|
|
985
|
+
|
|
986
|
+
仅对包含 `data-exposure="true"` 的 DOM 元素做曝光监听与上报(区分大小写,建议统一为字符串 "true")。
|
|
987
|
+
|
|
988
|
+
#### 配置参数
|
|
989
|
+
|
|
990
|
+
- `autoTrackExposure`: 是否启用曝光埋点(默认:false)
|
|
991
|
+
- `exposureThreshold`: 曝光进入可视区判定阈值,0-1之间(默认:0.5)
|
|
992
|
+
- `exposureTime`: 曝光可见停留时长阈值,单位毫秒(默认:500)
|
|
993
|
+
- `exposureNum`: 同一元素允许上报的最大曝光次数(默认:不限制)
|
|
994
|
+
|
|
995
|
+
#### 工作原理
|
|
996
|
+
|
|
997
|
+
1. 使用 `IntersectionObserver` API 判定元素是否进入可视区
|
|
998
|
+
2. 元素进入可视区后开始计时
|
|
999
|
+
3. 元素离开可视区时,如果可见时长达到 `exposureTime` 阈值,则上报曝光事件
|
|
1000
|
+
4. 如果设置了 `exposureNum`,同一元素超过该次数后不再上报
|
|
1001
|
+
|
|
1002
|
+
#### 上报参数提取
|
|
1003
|
+
|
|
1004
|
+
从目标元素(或其祖先节点,按"就近原则")提取所有 `data-*` 属性作为埋点业务参数,规则如下:
|
|
1005
|
+
|
|
1006
|
+
- 属性名从 `data-xxx-yyy` 转为 `xxxYyy`(camelCase)
|
|
1007
|
+
- 示例:`data-goods-id` → `goodsId`,`data-list-id` → `listId`
|
|
1008
|
+
- 排除属性:`data-exposure`、`data-part-key`、`data-desc`
|
|
1009
|
+
|
|
1010
|
+
#### 使用示例
|
|
1011
|
+
|
|
1012
|
+
```jsx
|
|
1013
|
+
WebTracking.init({
|
|
1014
|
+
appKey: "218844",
|
|
1015
|
+
serverUrl: "https://xxx/push",
|
|
1016
|
+
// 启用曝光埋点
|
|
1017
|
+
autoTrackExposure: true,
|
|
1018
|
+
// 元素进入可视区 50% 时判定为可见
|
|
1019
|
+
exposureThreshold: 0.5,
|
|
1020
|
+
// 元素连续可见 500ms 才算一次有效曝光
|
|
1021
|
+
exposureTime: 500,
|
|
1022
|
+
// 同一元素最多上报 3 次曝光
|
|
1023
|
+
exposureNum: 3,
|
|
1024
|
+
});
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
#### HTML 使用示例
|
|
1028
|
+
|
|
1029
|
+
```jsx
|
|
1030
|
+
<div className="goods-list">
|
|
1031
|
+
<div
|
|
1032
|
+
data-exposure="true"
|
|
1033
|
+
data-part-key="goods_card"
|
|
1034
|
+
data-desc="商品卡片曝光"
|
|
1035
|
+
data-goods-id="12345"
|
|
1036
|
+
data-goods-name="测试商品"
|
|
1037
|
+
data-list-id="home_list"
|
|
1038
|
+
>
|
|
1039
|
+
<img src="goods.jpg" alt="商品图片" />
|
|
1040
|
+
<h3>商品名称</h3>
|
|
1041
|
+
</div>
|
|
1042
|
+
|
|
1043
|
+
<div
|
|
1044
|
+
data-exposure="true"
|
|
1045
|
+
data-part-key="ad_banner"
|
|
1046
|
+
data-desc="广告横幅曝光"
|
|
1047
|
+
data-ad-id="999"
|
|
1048
|
+
data-ad-position="top"
|
|
1049
|
+
>
|
|
1050
|
+
<img src="ad.jpg" alt="广告图片" />
|
|
1051
|
+
</div>
|
|
1052
|
+
</div>
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
#### 上报数据示例
|
|
1056
|
+
|
|
1057
|
+
```json
|
|
1058
|
+
{
|
|
1059
|
+
"event": "WebExposure",
|
|
1060
|
+
"desc": "商品卡片曝光",
|
|
1061
|
+
"itemKey": "218844.home_page.goods_card",
|
|
1062
|
+
"requestTime": 1709524231171,
|
|
1063
|
+
"deviceId": "1dd539cdea9332ebb9d5c087f9d4471f",
|
|
1064
|
+
"privateParamMap": {
|
|
1065
|
+
"business": {
|
|
1066
|
+
"goodsId": "12345",
|
|
1067
|
+
"goodsName": "测试商品",
|
|
1068
|
+
"listId": "home_list"
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
#### 注意事项
|
|
1075
|
+
|
|
1076
|
+
1. **浏览器兼容性**:需要浏览器支持 `IntersectionObserver` 和 `MutationObserver` API,不支持时会自动禁用曝光埋点
|
|
1077
|
+
2. **性能优化**:SDK 会自动去重,避免重复监听同一元素
|
|
1078
|
+
3. **动态元素**:自动监听动态添加的曝光元素,无需手动调用
|
|
1079
|
+
4. **数据提取**:`data-*` 属性会从目标元素向上遍历到 BODY 标签,按"就近原则"提取
|
|
1080
|
+
|
|
972
1081
|
---
|
|
973
1082
|
|
|
974
1083
|
## 六、版本更新日志
|
|
975
1084
|
|
|
976
|
-
### v1.2.
|
|
1085
|
+
### v1.2.4 (最新)
|
|
1086
|
+
|
|
1087
|
+
- ✨ 新增元素曝光埋点功能
|
|
1088
|
+
- `autoTrackExposure` - 是否启用曝光埋点
|
|
1089
|
+
- `exposureThreshold` - 曝光进入可视区判定阈值(0-1之间)
|
|
1090
|
+
- `exposureTime` - 曝光可见停留时长阈值(毫秒)
|
|
1091
|
+
- `exposureNum` - 同一元素允许上报的最大曝光次数
|
|
1092
|
+
- 使用 `IntersectionObserver` API 判定元素可见性
|
|
1093
|
+
- 自动提取 `data-*` 属性作为业务参数
|
|
1094
|
+
- 支持自定义曝光次数限制
|
|
1095
|
+
|
|
1096
|
+
### v1.2.3
|
|
977
1097
|
|
|
978
1098
|
- 🐛 修复批量发送数据格式问题
|
|
979
1099
|
- 批量发送时直接发送数组,不再包装在 `events` 参数中
|
package/lib/index.esm.js
CHANGED
|
@@ -1253,7 +1253,13 @@ function (_super) {
|
|
|
1253
1253
|
|
|
1254
1254
|
_this.DEFAULT_PENDING_REQUESTS_MAX_SIZE = 50; // LocalStorage 最大大小限制(4MB)
|
|
1255
1255
|
|
|
1256
|
-
_this.MAX_STORAGE_SIZE = 4 * 1024 * 1024; //
|
|
1256
|
+
_this.MAX_STORAGE_SIZE = 4 * 1024 * 1024; // IntersectionObserver 实例
|
|
1257
|
+
|
|
1258
|
+
_this.exposureObserver = null; // 曝光元素映射
|
|
1259
|
+
|
|
1260
|
+
_this.exposureElementsMap = new Map(); // MutationObserver 实例(用于监听动态添加的元素)
|
|
1261
|
+
|
|
1262
|
+
_this.mutationObserver = null; // 用户信息
|
|
1257
1263
|
|
|
1258
1264
|
_this.userInfo = null; // 当前路由
|
|
1259
1265
|
|
|
@@ -1267,7 +1273,8 @@ function (_super) {
|
|
|
1267
1273
|
PageView: "Web 浏览页面",
|
|
1268
1274
|
WebClick: "Web 元素点击",
|
|
1269
1275
|
PageRetained: "Web 页面浏览时长",
|
|
1270
|
-
CustomTrack: "Web 自定义代码上报"
|
|
1276
|
+
CustomTrack: "Web 自定义代码上报",
|
|
1277
|
+
WebExposure: "Web 元素曝光"
|
|
1271
1278
|
};
|
|
1272
1279
|
/**
|
|
1273
1280
|
* @description 初始化函数
|
|
@@ -1312,6 +1319,11 @@ function (_super) {
|
|
|
1312
1319
|
|
|
1313
1320
|
if (_this.initConfig.autoTrackPageDurationInterval) {
|
|
1314
1321
|
_this.startPageDurationTimer();
|
|
1322
|
+
} // 如果启用了曝光监听,初始化曝光监听
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
if (_this.initConfig.autoTrackExposure) {
|
|
1326
|
+
_this.initExposureObserver();
|
|
1315
1327
|
}
|
|
1316
1328
|
};
|
|
1317
1329
|
/**
|
|
@@ -1372,6 +1384,13 @@ function (_super) {
|
|
|
1372
1384
|
_this.startPageDurationTimer();
|
|
1373
1385
|
} else {
|
|
1374
1386
|
_this.stopPageDurationTimer();
|
|
1387
|
+
} // 处理曝光监听配置
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
if (_this.initConfig.autoTrackExposure) {
|
|
1391
|
+
_this.initExposureObserver();
|
|
1392
|
+
} else {
|
|
1393
|
+
_this.stopExposureObserver();
|
|
1375
1394
|
}
|
|
1376
1395
|
};
|
|
1377
1396
|
/**
|
|
@@ -1454,6 +1473,36 @@ function (_super) {
|
|
|
1454
1473
|
|
|
1455
1474
|
break;
|
|
1456
1475
|
|
|
1476
|
+
case 'exposureThreshold':
|
|
1477
|
+
if (typeof value !== 'number' || value < 0 || value > 1) {
|
|
1478
|
+
return {
|
|
1479
|
+
valid: false,
|
|
1480
|
+
message: 'exposureThreshold 必须是 0-1 之间的数字'
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
break;
|
|
1485
|
+
|
|
1486
|
+
case 'exposureTime':
|
|
1487
|
+
if (typeof value !== 'number' || value <= 0) {
|
|
1488
|
+
return {
|
|
1489
|
+
valid: false,
|
|
1490
|
+
message: 'exposureTime 必须是大于 0 的数字'
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
break;
|
|
1495
|
+
|
|
1496
|
+
case 'exposureNum':
|
|
1497
|
+
if (value !== undefined && (typeof value !== 'number' || value <= 0 || !Number.isInteger(value))) {
|
|
1498
|
+
return {
|
|
1499
|
+
valid: false,
|
|
1500
|
+
message: 'exposureNum 必须是大于 0 的整数或不限制'
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
break;
|
|
1505
|
+
|
|
1457
1506
|
case 'showLog':
|
|
1458
1507
|
case 'autoTrack':
|
|
1459
1508
|
case 'isTrackSinglePage':
|
|
@@ -2780,8 +2829,275 @@ function (_super) {
|
|
|
2780
2829
|
return str + ("" + (str.length ? "." : "")) + key;
|
|
2781
2830
|
}, "");
|
|
2782
2831
|
};
|
|
2832
|
+
/**
|
|
2833
|
+
* @description 从元素或其祖先节点提取 data-* 属性
|
|
2834
|
+
* @param element 目标元素
|
|
2835
|
+
* @returns 提取的业务参数对象
|
|
2836
|
+
*/
|
|
2837
|
+
|
|
2838
|
+
|
|
2839
|
+
_this.extractDataAttributes = function (element) {
|
|
2840
|
+
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
|
+
|
|
2862
|
+
currentElement = currentElement.parentElement;
|
|
2863
|
+
|
|
2864
|
+
if (currentElement && currentElement.tagName === 'BODY') {
|
|
2865
|
+
break;
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
|
|
2869
|
+
return business;
|
|
2870
|
+
};
|
|
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
|
+
|
|
2978
|
+
_this.reportExposure = function (element) {
|
|
2979
|
+
var elementInfo = _this.exposureElementsMap.get(element);
|
|
2980
|
+
|
|
2981
|
+
if (!elementInfo) {
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
var exposureNum = _this.initConfig.exposureNum;
|
|
2986
|
+
|
|
2987
|
+
if (exposureNum !== undefined && elementInfo.exposureCount >= exposureNum) {
|
|
2988
|
+
if (_this.initConfig.showLog) {
|
|
2989
|
+
_this.printLog("\u5143\u7D20\u5DF2\u8FBE\u5230\u6700\u5927\u66DD\u5149\u6B21\u6570\u9650\u5236: " + exposureNum);
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
var business = _this.extractDataAttributes(element);
|
|
2996
|
+
|
|
2997
|
+
var desc = element.getAttribute('data-desc') || _this.eventDescMap['WebExposure'];
|
|
2998
|
+
|
|
2999
|
+
var partkey = element.getAttribute('data-part-key') || 'exposure';
|
|
3000
|
+
|
|
3001
|
+
var params = _this.getParams({
|
|
3002
|
+
event: 'WebExposure',
|
|
3003
|
+
desc: desc,
|
|
3004
|
+
itemKey: _this.getItemKey(partkey),
|
|
3005
|
+
privateParamMap: {
|
|
3006
|
+
business: business
|
|
3007
|
+
}
|
|
3008
|
+
});
|
|
3009
|
+
|
|
3010
|
+
_this.sendData(params).then(function () {
|
|
3011
|
+
elementInfo.exposureCount++;
|
|
3012
|
+
|
|
3013
|
+
if (elementInfo.exposureTimer) {
|
|
3014
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
3015
|
+
elementInfo.exposureTimer = null;
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
if (_this.initConfig.showLog) {
|
|
3019
|
+
_this.printLog("\u66DD\u5149\u4E0A\u62A5\u6210\u529F\uFF0C\u5F53\u524D\u66DD\u5149\u6B21\u6570: " + elementInfo.exposureCount);
|
|
3020
|
+
}
|
|
3021
|
+
}).catch(function (err) {
|
|
3022
|
+
if (_this.initConfig.showLog) {
|
|
3023
|
+
_this.printLog("\u66DD\u5149\u4E0A\u62A5\u5931\u8D25: " + err);
|
|
3024
|
+
}
|
|
3025
|
+
});
|
|
3026
|
+
};
|
|
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
|
+
};
|
|
2783
3099
|
|
|
2784
|
-
_this.sdkVersion = "1.2.
|
|
3100
|
+
_this.sdkVersion = "1.2.4"; // sdk版本
|
|
2785
3101
|
|
|
2786
3102
|
_this.initConfig = {
|
|
2787
3103
|
appKey: "",
|
|
@@ -2802,7 +3118,11 @@ function (_super) {
|
|
|
2802
3118
|
pendingRequestsMaxSize: 50,
|
|
2803
3119
|
autoTrackPageDurationInterval: false,
|
|
2804
3120
|
pageDurationInterval: 30000,
|
|
2805
|
-
sendMethod: "auto"
|
|
3121
|
+
sendMethod: "auto",
|
|
3122
|
+
autoTrackExposure: false,
|
|
3123
|
+
exposureThreshold: 0.5,
|
|
3124
|
+
exposureTime: 500,
|
|
3125
|
+
exposureNum: undefined // 同一元素允许上报的最大曝光次数,不限制
|
|
2806
3126
|
|
|
2807
3127
|
}; // 系统信息
|
|
2808
3128
|
|