gio-miniprogram-sdk 4.0.1 → 4.1.0

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.
Files changed (76) hide show
  1. package/dist/alipay.js +1 -1
  2. package/dist/baidu.js +1 -1
  3. package/dist/bytedance.js +1 -1
  4. package/dist/jingdong.js +1 -1
  5. package/dist/kuaishou.js +1 -1
  6. package/dist/plugins/gioABTest.js +1 -1
  7. package/dist/plugins/gioCompress.js +1 -1
  8. package/dist/plugins/gioEventAutoTracking.js +1 -1
  9. package/dist/plugins/gioImpressionTracking.js +1 -1
  10. package/dist/plugins/gioMultipleInstances.js +1 -0
  11. package/dist/qq.js +1 -1
  12. package/dist/quickapp.js +1 -1
  13. package/dist/taobao.js +1 -1
  14. package/dist/taro.js +1 -1
  15. package/dist/uniapp.js +1 -1
  16. package/dist/wechat.js +1 -1
  17. package/package.json +39 -42
  18. package/rollup.config.js +11 -6
  19. package/rollup.plugins.config.js +13 -10
  20. package/src/{pluginsOut/frameworks → adapters}/gioTaobaoAdapter.ts +47 -43
  21. package/src/{pluginsOut/frameworks → adapters}/gioTaroAdapter.ts +4 -4
  22. package/src/{pluginsOut/frameworks → adapters}/gioUniAppAdapter.ts +35 -6
  23. package/src/constants/config.ts +47 -18
  24. package/src/constants/emitMsg.ts +23 -0
  25. package/src/constants/regex.ts +0 -1
  26. package/src/core/dataStore/eventContextBuilder.ts +28 -17
  27. package/src/core/dataStore/eventHooks/appEffects.ts +50 -31
  28. package/src/core/dataStore/eventHooks/index.ts +7 -5
  29. package/src/core/dataStore/eventHooks/minipPage.ts +2 -11
  30. package/src/core/dataStore/eventHooks/pageEffects.ts +61 -27
  31. package/src/core/dataStore/index.ts +263 -185
  32. package/src/core/growingIO.ts +312 -178
  33. package/src/core/pluginsInstance/base.ts +157 -0
  34. package/src/core/pluginsInstance/taro.ts +15 -0
  35. package/src/core/pluginsInstance/tb.ts +15 -0
  36. package/src/core/pluginsInstance/uniapp.ts +15 -0
  37. package/src/core/uploader.ts +131 -82
  38. package/src/core/userStore.ts +160 -121
  39. package/src/index.ts +37 -28
  40. package/src/minipInstance/base.ts +2 -1
  41. package/src/minipInstance/quickapp.ts +5 -19
  42. package/src/platformConfig/base.ts +0 -4
  43. package/src/{pluginsOut/ordinary → plugins}/gioABTest.ts +74 -37
  44. package/src/{pluginsOut/ordinary → plugins}/gioEventAutoTracking.ts +25 -18
  45. package/src/{pluginsOut/ordinary → plugins}/gioImpressionTracking.ts +55 -22
  46. package/src/plugins/gioMultipleInstances.ts +176 -0
  47. package/src/types/base.ts +10 -3
  48. package/src/types/dataStore.ts +31 -16
  49. package/src/types/eventHooks.ts +5 -6
  50. package/src/types/growingIO.ts +30 -14
  51. package/src/types/platforms.ts +0 -4
  52. package/src/types/plugins.ts +1 -1
  53. package/src/types/uploader.ts +16 -10
  54. package/src/types/userStore.ts +21 -17
  55. package/src/utils/glodash.ts +10 -3
  56. package/src/utils/tools.ts +27 -6
  57. package/src/utils/verifiers.ts +25 -50
  58. package/typings/global.d.ts +5 -0
  59. package/.babelrc +0 -4
  60. package/bin/build/full.sh +0 -32
  61. package/bin/build/jd.sh +0 -14
  62. package/bin/build/ks.sh +0 -14
  63. package/bin/build/my.sh +0 -14
  64. package/bin/build/plugins.sh +0 -5
  65. package/bin/build/qq.sh +0 -14
  66. package/bin/build/quickapp.sh +0 -14
  67. package/bin/build/swan.sh +0 -14
  68. package/bin/build/taro.sh +0 -18
  69. package/bin/build/tb.sh +0 -18
  70. package/bin/build/tt.sh +0 -14
  71. package/bin/build/uniapp.sh +0 -18
  72. package/bin/build/wx.sh +0 -14
  73. package/src/core/plugins.ts +0 -152
  74. package/src/pluginsOut/ordinary/gioCustomTracking.ts +0 -71
  75. package/bin/{build/all.sh → build.sh} +3 -3
  76. /package/src/{pluginsOut/ordinary → plugins}/gioCompress.ts +0 -0
@@ -1,7 +1,9 @@
1
1
  import {
2
+ ALLOW_SET_OPTIONS,
2
3
  DEFAULT_SETTINGS,
3
4
  EXTRA_INFO_PARAMS,
4
- IGNORE_PARAMS
5
+ IGNORE_PARAMS,
6
+ STORAGE_KEYS
5
7
  } from '@@/constants/config';
6
8
  import {
7
9
  forEach,
@@ -14,7 +16,6 @@ import {
14
16
  isNil,
15
17
  isString,
16
18
  keys,
17
- toString,
18
19
  typeOf,
19
20
  unset
20
21
  } from '@@/utils/glodash';
@@ -22,23 +23,26 @@ import {
22
23
  batchSetStorageSync,
23
24
  callError,
24
25
  consoleText,
25
- getAppInst,
26
- getSubKeys,
26
+ getGlobal,
27
27
  guid,
28
28
  niceTry
29
29
  } from '@@/utils/tools';
30
- import { DataStoreType, OriginOptions } from '@@/types/dataStore';
30
+ import {
31
+ DataStoreType,
32
+ OriginOptions,
33
+ StorageKeyType
34
+ } from '@@/types/dataStore';
35
+ import { EXTEND_EVENT } from '@@/types/base';
31
36
  import { EventHooksType } from '@@/types/eventHooks';
32
37
  import { GrowingIOType } from '@@/types/growingIO';
38
+ import EMIT_MSG from '@@/constants/emitMsg';
33
39
  import EventContextBuilder from './eventContextBuilder';
34
40
  import EventHooks from './eventHooks';
35
41
 
36
42
  class DataStore implements DataStoreType {
37
43
  readonly ALLOW_SETTING_KEYS = keys(DEFAULT_SETTINGS);
38
- public gsidStorageName = '_growing_gsid_';
39
- public originalSourceName = 'gdp_original_source';
40
- public _gsid: number;
41
- public _stid: number; // 用于判断每发送10个事件,往本地存储里同步一次gsid,减少存储的读写操作。
44
+ public _gsid: any;
45
+ public _stid: any; // 用于判断每发送10个事件,往本地存储里同步一次gsid,减少存储的读写操作。
42
46
  public eventHooks: EventHooksType;
43
47
  // 来源场景值
44
48
  public _scene: number | string;
@@ -48,10 +52,8 @@ class DataStore implements DataStoreType {
48
52
  public shareOut: boolean;
49
53
  // 上次小程序关闭时间
50
54
  public lastCloseTime: number;
51
- // 保活时间(两次打开小程序间隔算为一次访问的时间)
52
- public keepAlive: number;
53
55
  // 事件通用属性构建方法
54
- public eventContextBuilder: (params?: any) => any;
56
+ public eventContextBuilder: (trackingId: string, params?: any) => any;
55
57
  // 上一个访问事件,保存最近的一次visit事件,存储一些设备系统信息,避免多次重新获取
56
58
  public lastVisitEvent: any;
57
59
  // 上一个页面事件,便于下一个Page事件获取数据
@@ -64,82 +66,107 @@ class DataStore implements DataStoreType {
64
66
  public trackTimers: any;
65
67
  // 被拦截的事件
66
68
  public interceptEvents: any;
69
+ // 记录已初始化的trackingId,以帮助判断是否再更新sessionId时是否需要发送事件
70
+ public initializedTrackingIds: string[];
67
71
 
68
72
  constructor(public growingIO: GrowingIOType) {
69
- this.initStorageInfo();
73
+ this.initializedTrackingIds = [];
70
74
  this.eventContextBuilder = new EventContextBuilder(this.growingIO).main;
71
75
  this.eventHooks = new EventHooks(this.growingIO);
72
76
  this.shareOut = false;
77
+ this._gsid = {};
78
+ this._stid = {};
73
79
  this.lastVisitEvent = {};
74
80
  this.lastPageEvent = {};
75
81
  this.locationData = {};
76
82
  this.generalProps = {};
77
83
  this.trackTimers = {};
78
84
  this.interceptEvents = [];
85
+ const { emitter, minipInstance } = this.growingIO;
86
+ // sdk初始化完成记录trackingId
87
+ emitter.on(EMIT_MSG.SDK_INITIALIZED, ({ trackingId: initTrackingId }) => {
88
+ this.initializedTrackingIds.push(initTrackingId);
89
+ this.initStorageInfo(initTrackingId);
90
+ });
79
91
  // visit、page事件监听
80
- this.growingIO.emitter.on('onComposeAfter', ({ composedEvent }) => {
81
- if (composedEvent.eventType === 'VISIT' || composedEvent.t === 'vst') {
82
- this.lastVisitEvent = composedEvent;
83
- }
84
- if (composedEvent.eventType === 'PAGE' || composedEvent.t === 'page') {
85
- this.lastPageEvent = composedEvent;
92
+ emitter.on(
93
+ EMIT_MSG.ON_COMMIT_REQUEST,
94
+ ({ eventData: event, trackingId }) => {
95
+ if (event.eventType === 'VISIT') {
96
+ this.lastVisitEvent = event;
97
+ }
98
+ if (event.eventType === 'PAGE') {
99
+ this.lastPageEvent[trackingId] = event;
100
+ }
86
101
  }
87
- });
102
+ );
88
103
  // 小程序切后台把所有还在计时中的计时器记一次时长
89
- if (isFunction(this.growingIO.minipInstance.minip?.onAppHide)) {
90
- this.growingIO.minipInstance.minip.onAppHide(() => {
91
- forEach(this.trackTimers, (tracker: any) => {
92
- if (tracker.start) {
93
- tracker.leng = tracker.leng + (+Date.now() - tracker.start);
94
- }
104
+ if (isFunction(minipInstance.minip?.onAppHide)) {
105
+ minipInstance.minip.onAppHide(() => {
106
+ this.trackersExecute((trackingId: string) => {
107
+ const timers = this.trackTimers[trackingId];
108
+ forEach(timers, (timer: any) => {
109
+ if (timer.start) {
110
+ timer.leng = timer.leng + (+Date.now() - timer.start);
111
+ }
112
+ });
95
113
  });
96
114
  });
97
115
  }
98
-
99
116
  // 小程序切前台把所有还在计时中的计时器重置开始时间
100
- if (isFunction(this.growingIO.minipInstance.minip?.onAppShow)) {
101
- this.growingIO.minipInstance.minip.onAppShow(() => {
102
- forEach(this.trackTimers, (tracker: any) => {
103
- if (tracker.start) {
104
- tracker.start = +Date.now();
105
- }
117
+ if (isFunction(minipInstance.minip?.onAppShow)) {
118
+ minipInstance.minip.onAppShow(() => {
119
+ this.trackersExecute((trackingId: string) => {
120
+ const timers = this.trackTimers[trackingId];
121
+ forEach(timers, (timer: any) => {
122
+ if (timer.start) {
123
+ timer.start = +Date.now();
124
+ }
125
+ });
106
126
  });
107
127
  });
108
128
  }
109
129
  // 关闭数据采集时要移除所有的计时器
110
- this.growingIO.emitter.on(
111
- 'OPTION_CHANGE',
112
- ({ optionName, optionValue }) => {
113
- if (optionName === 'dataCollect' && optionValue === false) {
114
- this.growingIO.clearTrackTimer();
115
- }
130
+ emitter.on(EMIT_MSG.OPTION_CHANGE, ({ optionName, optionValue }) => {
131
+ if (optionName === 'dataCollect' && optionValue === false) {
132
+ this.trackersExecute((trackingId: string) => {
133
+ this.growingIO.clearTrackTimer(trackingId);
134
+ });
116
135
  }
117
- );
136
+ });
118
137
  }
119
138
 
120
- // @ts-ignore
121
- get gsid() {
122
- const app = getAppInst();
123
- const sKeys = getSubKeys(app);
124
- return !isEmpty(sKeys) && app.gio_gsid ? app.gio_gsid : this._gsid;
125
- }
139
+ // 获取存储key
140
+ getStorageKey = (trackingId: string, name: StorageKeyType) => {
141
+ const { inPlugin } = this.growingIO;
142
+ return `${trackingId === this.growingIO.trackingId ? '' : trackingId}${
143
+ STORAGE_KEYS[inPlugin ? 'plugin_' + name : name]
144
+ }`;
145
+ };
126
146
 
127
147
  // @ts-ignore
128
- set gsid(v: any) {
129
- const newV = Number.parseInt(v, 10);
130
- if (Number.isNaN(newV) || v >= 1e9 || v < 1) {
131
- this._gsid = 1;
148
+ getGsid = (trackingId: string) => {
149
+ let gsid = Number(this._gsid[trackingId]);
150
+ if (Number.isNaN(gsid) || gsid >= 1e9 || gsid < 1) {
151
+ this.setGsid(trackingId, 1);
152
+ return 1;
132
153
  } else {
133
- this._gsid = v;
154
+ return gsid;
155
+ }
156
+ };
157
+
158
+ // @ts-ignore
159
+ setGsid = (trackingId: string, value: any) => {
160
+ let gsid = Number(value);
161
+ if (Number.isNaN(gsid) || gsid >= 1e9 || gsid < 1) {
162
+ gsid = 1;
134
163
  }
135
- // 在全局app中存一份gsid给分包用
136
- const app = getAppInst();
137
- app.gio_gsid = this._gsid;
164
+ this._gsid[trackingId] = gsid;
138
165
  // _gsid每自增10次(即每发送10个事件)时,往本地存储里同步一次gsid
139
- if (this._gsid - this._stid >= 10) {
166
+ if (this._gsid[trackingId] - this._stid[trackingId] >= 10) {
140
167
  this.saveStorageInfo();
141
168
  }
142
- }
169
+ };
143
170
 
144
171
  get scene() {
145
172
  return this._scene;
@@ -149,7 +176,7 @@ class DataStore implements DataStoreType {
149
176
  const prevScene = this._scene;
150
177
  this._scene = v;
151
178
  if (prevScene !== this._scene) {
152
- this.growingIO.emitter.emit('SCENE_UPDATE', {
179
+ this.growingIO.emitter.emit(EMIT_MSG.SCENE_UPDATE, {
153
180
  newScene: v,
154
181
  oldScene: prevScene
155
182
  });
@@ -157,54 +184,106 @@ class DataStore implements DataStoreType {
157
184
  }
158
185
 
159
186
  // 初始化gsid
160
- initStorageInfo = () => {
187
+ initStorageInfo = (trackingId: string) => {
161
188
  const { minipInstance } = this.growingIO;
162
- const app = getAppInst();
163
- // gsid
164
- const gid = app.gio_gsid
165
- ? app.gio_gsid
166
- : Number.parseInt(minipInstance.getStorageSync(this.gsidStorageName), 10);
167
- this._gsid = Number.isNaN(gid) || gid >= 1e9 || gid < 1 ? 1 : gid;
168
- // 初始化时同步stid
169
- this._stid = this._gsid;
170
- if (gid !== this._gsid) {
171
- minipInstance.setStorageSync(this.gsidStorageName, this._gsid);
189
+ const oriGsid = minipInstance.getStorageSync(
190
+ this.getStorageKey(trackingId, 'gsid')
191
+ );
192
+ let gsid = Number(oriGsid);
193
+ if (Number.isNaN(gsid) || gsid >= 1e9 || gsid < 1) {
194
+ gsid = 1;
195
+ }
196
+ this._gsid[trackingId] = gsid;
197
+ this._stid[trackingId] = gsid;
198
+ // 存储中的gsid不合法时要往存储写一次
199
+ if (gsid !== oriGsid) {
200
+ minipInstance.setStorageSync(
201
+ this.getStorageKey(trackingId, 'gsid'),
202
+ gsid
203
+ );
172
204
  }
173
205
  };
174
206
 
175
- // 退出小程序时在存储中同步gsid信息
207
+ // 在存储中同步gsid信息
176
208
  saveStorageInfo = () => {
177
209
  const { minipInstance } = this.growingIO;
178
- this._stid = this._gsid;
179
- batchSetStorageSync(minipInstance, [
180
- { key: this.gsidStorageName, value: this._gsid }
181
- ]);
210
+ this._stid = { ...this._gsid };
211
+ batchSetStorageSync(
212
+ minipInstance,
213
+ this.initializedTrackingIds.map((trackingId: string) => ({
214
+ key: this.getStorageKey(trackingId, 'gsid'),
215
+ value: this._gsid[trackingId]
216
+ }))
217
+ );
182
218
  };
183
219
 
184
220
  // 保存初始来源信息
185
- setOriginalSource = ({ path, query }) => {
221
+ setOriginalSource = (trackingId: string, { path, query }) => {
186
222
  const { minipInstance } = this.growingIO;
187
- if (isNil(this.getOriginalSource())) {
223
+ if (isNil(this.getOriginalSource(trackingId))) {
188
224
  const originalSource = { path, query, title: '' };
189
225
  minipInstance.setStorageSync(
190
- this.originalSourceName,
226
+ this.getStorageKey(trackingId, 'originalSource'),
191
227
  JSON.stringify(originalSource)
192
228
  );
193
229
  }
194
230
  };
195
231
 
196
232
  // 获取初始来源信息
197
- getOriginalSource = () => {
233
+ getOriginalSource = (trackingId: string) => {
198
234
  const { minipInstance } = this.growingIO;
199
235
  return niceTry(() =>
200
- JSON.parse(minipInstance.getStorageSync(this.originalSourceName))
236
+ JSON.parse(
237
+ minipInstance.getStorageSync(
238
+ this.getStorageKey(trackingId, 'originalSource')
239
+ )
240
+ )
201
241
  );
202
242
  };
203
243
 
244
+ // 获取采集实例配置内容 //? 多实例插件会重写该方法
245
+ // eslint-disable-next-line
246
+ getTrackerVds = (trackingId: string): any =>
247
+ this.growingIO.trackingId === trackingId
248
+ ? { ...this.growingIO.vdsConfig }
249
+ : undefined;
250
+
251
+ // 初始化实例的配置项 // ?多实例插件会重写该方法
252
+ initTrackerOptions = (options: any) => {
253
+ const trackerOptions = this.initOptions(options);
254
+ trackerOptions.trackingId = options.trackingId;
255
+ this.growingIO.trackingId = options.trackingId;
256
+ this.growingIO.vdsConfig = trackerOptions;
257
+ return trackerOptions;
258
+ };
259
+
260
+ // 初始化实例的hooker // ?多实例插件会重写该方法
261
+ initTrackerHooker = (vdsConfig: OriginOptions) => {
262
+ const { platformConfig, inPlugin, minipInstance, plugins } = this.growingIO;
263
+ const { uniVue, taro } = vdsConfig;
264
+ // 如果是使用全量版本时,当前小程序不是框架的,要允许原生的hook
265
+ if (!(uniVue || taro)) {
266
+ platformConfig.canHook = true;
267
+ }
268
+ // 初始化核心钩子(重写全局)
269
+ if (!inPlugin || ['tbp', 'jdp'].includes(minipInstance.platform)) {
270
+ this.eventHooks.initEventHooks();
271
+ }
272
+ /** 第三方框架重写 */
273
+ // uniapp
274
+ if (uniVue) {
275
+ plugins?.gioUniAppAdapter?.main();
276
+ }
277
+ // taro
278
+ if (taro) {
279
+ plugins?.gioTaroAdapter?.main();
280
+ }
281
+ };
282
+
204
283
  // 初始化全局配置
205
284
  initOptions = (userOptions: OriginOptions) => {
206
- const { projectId, dataSourceId, appId } = userOptions;
207
- const vdsConfig: any = {};
285
+ const { projectId, dataSourceId, appId, trackingId } = userOptions;
286
+ const configs: any = {};
208
287
  // 只处理允许的配置项,之外用户的配置项无视
209
288
  this.ALLOW_SETTING_KEYS.forEach((k) => {
210
289
  // 配置项值不存在或类型不合法时置为默认值
@@ -213,123 +292,94 @@ class DataStore implements DataStoreType {
213
292
  ? !altp.includes(typeOf(userOptions[k]))
214
293
  : typeOf(userOptions[k]) !== DEFAULT_SETTINGS[k].type;
215
294
  if (invalid) {
216
- vdsConfig[k] = DEFAULT_SETTINGS[k].default;
295
+ configs[k] = DEFAULT_SETTINGS[k].default;
217
296
  } else if (k === 'ignoreFields') {
218
- vdsConfig.ignoreFields = userOptions.ignoreFields.filter((o) =>
297
+ configs.ignoreFields = userOptions.ignoreFields.filter((o) =>
219
298
  IGNORE_PARAMS.includes(o)
220
299
  );
221
300
  } else if (k === 'extraParams') {
222
- vdsConfig.extraParams = userOptions.extraParams.filter((o) =>
301
+ configs.extraParams = userOptions.extraParams.filter((o) =>
223
302
  EXTRA_INFO_PARAMS.includes(o)
224
303
  );
225
304
  } else {
226
- vdsConfig[k] = userOptions[k];
305
+ configs[k] = userOptions[k];
306
+ // 数据采集和无埋点采集关闭时给提示
307
+ if (['dataCollect', 'autotrack'].includes(k) && !configs[k]) {
308
+ consoleText(`已关闭${ALLOW_SET_OPTIONS[k]}`, 'info');
309
+ }
227
310
  }
228
311
  });
229
312
  // 发送间隔不允许设置为小数,如果是小数则取整
230
- vdsConfig.uploadInterval = Math.round(vdsConfig.uploadInterval);
231
- // 设置发送间隔小于0或者大于2秒的都认为不合法,改回1秒
313
+ configs.uploadInterval = Math.round(configs.uploadInterval);
314
+ // 设置发送间隔小于0或者大于3秒的都认为不合法,改回1秒
232
315
  if (
233
- Number.isNaN(vdsConfig.uploadInterval) ||
234
- vdsConfig.uploadInterval < 0 ||
235
- vdsConfig.uploadInterval > 2000
316
+ Number.isNaN(configs.uploadInterval) ||
317
+ configs.uploadInterval < 0 ||
318
+ configs.uploadInterval > 3000
236
319
  ) {
237
- vdsConfig.uploadInterval = 1000;
320
+ configs.uploadInterval = 1000;
238
321
  }
239
322
  // idMapping配置项兼容处理
240
- if (vdsConfig.enableIdMapping && !vdsConfig.idMapping) {
241
- vdsConfig.idMapping = true;
323
+ if (configs.enableIdMapping && !configs.idMapping) {
324
+ configs.idMapping = true;
325
+ // 没有开启IDMapping的时候要把userKey清掉,防止之前有数被带到上报数据里
326
+ if (!configs.idMapping) {
327
+ this.growingIO.userStore.setUserKey(trackingId, '');
328
+ }
242
329
  }
330
+ unset(configs, 'enableIdMapping');
243
331
  // 是否开启强制插件模式
244
- if (vdsConfig.pluginMode) {
332
+ if (configs.pluginMode) {
245
333
  this.growingIO.inPlugin = true;
246
334
  }
247
335
  // 请求超时时长设置的合法区间校验,值小于等于0ms认为不合法,改回5秒,浏览器默认有2分钟的上限
248
- if (
249
- isNaN(Number(vdsConfig.requestTimeout)) ||
250
- vdsConfig.requestTimeout <= 0
251
- ) {
252
- vdsConfig.requestTimeout = 5000;
336
+ if (isNaN(Number(configs.requestTimeout)) || configs.requestTimeout <= 0) {
337
+ configs.requestTimeout = 5000;
253
338
  }
254
- this.growingIO.vdsConfig = {
255
- ...vdsConfig,
339
+
340
+ return {
341
+ ...configs,
256
342
  projectId,
257
343
  dataSourceId,
258
344
  appId,
345
+ trackingId,
259
346
  // 补充性能默认值
260
347
  performance: {
261
- monitor: vdsConfig.performance?.monitor ?? true,
262
- exception: vdsConfig.performance?.exception ?? true,
263
- network: vdsConfig.performance?.network ?? false
348
+ monitor: configs.performance?.monitor ?? true,
349
+ exception: configs.performance?.exception ?? true,
350
+ network: configs.performance?.network ?? false
264
351
  }
265
352
  };
266
- this.keepAlive = vdsConfig.keepAlive;
267
- // 初始化配置提示
268
- if (!vdsConfig.dataCollect) {
269
- consoleText('已关闭数据采集', 'info');
270
- }
271
- if (!vdsConfig.autotrack) {
272
- consoleText('已关闭无埋点', 'info');
273
- }
274
- const { plugins, inPlugin, minipInstance } = this.growingIO;
275
- const { uniVue, taro } = vdsConfig;
276
- // 如果是使用全量版本时,当前小程序不是框架的,要允许原生的hook
277
- if (!(uniVue || taro)) {
278
- this.growingIO.platformConfig.canHook = true;
279
- }
280
- // 初始化核心钩子(重写全局)
281
- if (!inPlugin || ['tbp', 'jdp'].includes(minipInstance.platform)) {
282
- this.eventHooks.initEventHooks();
283
- }
284
- /** 第三方框架重写 */
285
- // uniapp
286
- if (uniVue) {
287
- plugins?.gioUniAppAdapter?.main();
288
- }
289
- // taro
290
- if (taro) {
291
- plugins?.gioTaroAdapter?.main();
292
- }
293
353
  };
294
354
 
295
355
  // 全局配置修改
296
- setOption = (k: string, v: any) => {
297
- const { vdsConfig, userStore, uploader, emitter } = this.growingIO;
356
+ setOption = (trackingId: string, k: string, v: any) => {
357
+ const { userStore, emitter } = this.growingIO;
358
+ const trakerVds = this.getTrackerVds(trackingId);
298
359
  // 检查 k
299
360
  const validKey = isString(k) && this.ALLOW_SETTING_KEYS.includes(k);
300
361
  const validValue = validKey && typeof v === DEFAULT_SETTINGS[k]?.type;
301
362
  if (validKey && validValue) {
363
+ const prevConfig = { ...trakerVds };
364
+ this.updateVdsConfig(trackingId, { ...trakerVds, [k]: v });
302
365
  // 从关闭到打开dataCollect时补发visit和page
303
- if (
304
- k === 'dataCollect' &&
305
- vdsConfig.dataCollect === false &&
306
- v === true
307
- ) {
308
- let t = setTimeout(() => {
309
- userStore.sessionId = '';
310
- const { path, query, settedTitle } = this.eventHooks.currentPage;
311
- // 重新获取页面title,防止切换配置前修改了title没取到
312
- this.eventHooks.currentPage.title =
313
- settedTitle[path] ||
314
- this.growingIO.minipInstance.getPageTitle(
315
- this.growingIO.minipInstance.getCurrentPage()
316
- );
317
- // visit取当前页面值
318
- this.sendVisit({ path, query });
319
- // 要重设一次页面时间,防止比visit早
320
- this.eventHooks.currentPage.time = Date.now();
321
- this.sendPage({ path, query });
322
- clearTimeout(t);
323
- t = null;
324
- }, 0);
325
- }
326
- vdsConfig[k] = v;
327
- // 修改serverUrl时要重新生成上报地址
328
- if (k === 'serverUrl') {
329
- uploader?.generateURL();
366
+ if (k === 'dataCollect' && prevConfig.dataCollect !== v && v) {
367
+ userStore.setSessionId(trackingId);
368
+ const { path, query, settedTitle } = this.eventHooks.currentPage;
369
+ // 重新获取页面title,防止切换配置前修改了title没取到
370
+ this.eventHooks.currentPage.title =
371
+ settedTitle[path] ||
372
+ this.growingIO.minipInstance.getPageTitle(
373
+ this.growingIO.minipInstance.getCurrentPage()
374
+ );
375
+ // visit取当前页面值
376
+ this.sendVisit(trackingId, { path, query });
377
+ // 要重设一次页面时间,防止比visit早
378
+ this.eventHooks.currentPage.time = Date.now();
379
+ this.sendPage(trackingId, { path, query });
330
380
  }
331
381
  // 配置项有变更要全局广播
332
- emitter.emit('OPTION_CHANGE', { optionName: k, optionValue: v });
382
+ emitter.emit(EMIT_MSG.OPTION_CHANGE, { optionName: k, optionValue: v });
333
383
  return true;
334
384
  } else {
335
385
  callError(`setOption > ${k}`);
@@ -338,18 +388,37 @@ class DataStore implements DataStoreType {
338
388
  };
339
389
 
340
390
  // 获取全局配置
341
- getOption = (k?: string) => {
342
- const { vdsConfig } = this.growingIO;
343
- if (k && has(vdsConfig, toString(k))) {
344
- return vdsConfig[toString(k)];
345
- } else if (isNil(k)) {
346
- return { ...vdsConfig };
391
+ getOption = (trackingId: string, k?: string) => {
392
+ const trakerVds = this.getTrackerVds(trackingId);
393
+ if (k && has(this.growingIO.vdsConfig, k)) {
394
+ if (has(trakerVds, k)) {
395
+ return trakerVds[k];
396
+ } else {
397
+ return this.growingIO.vdsConfig[k];
398
+ }
399
+ } else if (isEmpty(k)) {
400
+ return trakerVds;
347
401
  } else {
348
402
  callError(`getOption > ${k}`);
349
403
  return undefined;
350
404
  }
351
405
  };
352
406
 
407
+ // 根据实例更新内存和存储中的vds配置项值
408
+ updateVdsConfig = (trackingId: string, vds: any) => {
409
+ if (trackingId === this.growingIO.trackingId) {
410
+ this.growingIO.vdsConfig = { ...this.growingIO.vdsConfig, ...vds };
411
+ getGlobal().vdsConfig = this.growingIO.vdsConfig;
412
+ } else {
413
+ this.growingIO.subInstance[trackingId] = {
414
+ ...this.growingIO.subInstance[trackingId],
415
+ ...vds
416
+ };
417
+ getGlobal().vdsConfig.subInstance[trackingId] =
418
+ this.growingIO.subInstance[trackingId];
419
+ }
420
+ };
421
+
353
422
  // 修改分享跳出判断值
354
423
  toggleShareOut = (v?: boolean) => {
355
424
  if (isBoolean(v)) {
@@ -360,30 +429,30 @@ class DataStore implements DataStoreType {
360
429
  };
361
430
 
362
431
  // 手动调用visit事件的方法
363
- sendVisit = (props?: any) => {
432
+ sendVisit = (trackingId: string, props?: any) => {
364
433
  (this.eventHooks.appEffects as any).buildVisitEvent(
434
+ trackingId,
365
435
  props ?? this.lastVisitEvent
366
436
  );
367
- // 等visit发完要重置页面时间,确保不会比visit早
368
- this.eventHooks.currentPage.time = Date.now();
369
437
  };
370
438
 
371
439
  // 手动调用page事件的方法
372
- sendPage = (props?: any) => {
373
- (this.eventHooks.pageEffects as any).buildPageEvent(props);
440
+ sendPage = (trackingId: string, props?: any) => {
441
+ (this.eventHooks.pageEffects as any).buildPageEvent(trackingId, props);
374
442
  };
375
443
 
376
444
  // 事件的格式转换(同时移除无值的字段)
377
- eventConverter = (event: any) => {
378
- const { vdsConfig, dataStore, uploader } = this.growingIO;
445
+ eventConverter = (event: EXTEND_EVENT) => {
446
+ const { dataStore, uploader } = this.growingIO;
447
+ const { dataCollect } = this.getTrackerVds(event.trackingId);
379
448
  // 开启数据采集时才会处理事件、累计全局计数并将合成的事件提交到请求队列
380
- if (vdsConfig.dataCollect) {
449
+ if (dataCollect) {
381
450
  //? 在4.0中用户属性事件和关闭事件不再带eventSequenceId字段
382
451
  if (!['LOGIN_USER_ATTRIBUTES', 'APP_CLOSED'].includes(event.eventType)) {
383
452
  //? 在4.0中event.eventSequenceId(esid)的值实际为全局的事件id,即值是globalSequenceId(gsid)为了保持向下兼容不做更名,会涉及存储
384
- event.eventSequenceId = dataStore.gsid;
453
+ event.eventSequenceId = dataStore.getGsid(event.trackingId);
385
454
  // 全局事件计数加1
386
- this.growingIO.dataStore.gsid += 1;
455
+ dataStore.setGsid(event.trackingId, event.eventSequenceId + 1);
387
456
  }
388
457
  const convertedEvent: any = {};
389
458
  forEach(event, (v: any, k: string) => {
@@ -404,7 +473,7 @@ class DataStore implements DataStoreType {
404
473
  convertedEvent[k] = v;
405
474
  }
406
475
  });
407
- this.growingIO.emitter.emit('onComposeAfter', {
476
+ this.growingIO.emitter.emit(EMIT_MSG.ON_COMPOSE_AFTER, {
408
477
  composedEvent: convertedEvent
409
478
  });
410
479
  // 提交请求队列
@@ -424,7 +493,7 @@ class DataStore implements DataStoreType {
424
493
  // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
425
494
  const ne = {
426
495
  ...e,
427
- ...this.eventContextBuilder({
496
+ ...this.eventContextBuilder(event.trackingId, {
428
497
  path: e.path,
429
498
  query: e.query,
430
499
  // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
@@ -450,7 +519,7 @@ class DataStore implements DataStoreType {
450
519
  // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
451
520
  const ne = {
452
521
  ...e,
453
- ...this.eventContextBuilder({
522
+ ...this.eventContextBuilder(e.trackingId, {
454
523
  path: e.path,
455
524
  query: e.query,
456
525
  // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
@@ -464,7 +533,7 @@ class DataStore implements DataStoreType {
464
533
  };
465
534
 
466
535
  // 构建应用/页面转发分享事件
467
- buildAppMessageEvent = (args: any) => {
536
+ buildAppMessageEvent = (trackingId: string, args: any) => {
468
537
  const originResult = args[0];
469
538
  let updateResult;
470
539
  if (args.length >= 2) {
@@ -487,13 +556,13 @@ class DataStore implements DataStoreType {
487
556
  $share_query: uri[1],
488
557
  ...updateResult?.attributes
489
558
  },
490
- ...eventContextBuilder()
559
+ ...eventContextBuilder(trackingId)
491
560
  };
492
561
  eventInterceptor(event);
493
562
  };
494
563
 
495
564
  // 构建朋友圈分享事件
496
- buildTimelineEvent = (args: any) => {
565
+ buildTimelineEvent = (trackingId: string, args: any) => {
497
566
  const originResult = args[0];
498
567
  let updateResult;
499
568
  if (args.length >= 2) {
@@ -515,13 +584,13 @@ class DataStore implements DataStoreType {
515
584
  $share_query: uri[1],
516
585
  ...updateResult?.attributes
517
586
  },
518
- ...eventContextBuilder()
587
+ ...eventContextBuilder(trackingId)
519
588
  };
520
589
  eventInterceptor(event);
521
590
  };
522
591
 
523
592
  // 构建添加收藏事件
524
- buildAddFavorites = (args: any) => {
593
+ buildAddFavorites = (trackingId: string, args: any) => {
525
594
  const originResult = args[0];
526
595
  let updateResult;
527
596
  if (args.length >= 2) {
@@ -541,10 +610,19 @@ class DataStore implements DataStoreType {
541
610
  $share_path: head(uri),
542
611
  $share_query: uri[1]
543
612
  },
544
- ...eventContextBuilder()
613
+ ...eventContextBuilder(trackingId)
545
614
  };
546
615
  eventInterceptor(event);
547
616
  };
617
+
618
+ // 需要对所有trackingId执行的逻辑
619
+ trackersExecute = (callback: (trackingId: string) => any) => {
620
+ this.initializedTrackingIds.forEach((trackingId: string) => {
621
+ if (typeOf(callback) === 'function') {
622
+ callback(trackingId);
623
+ }
624
+ });
625
+ };
548
626
  }
549
627
 
550
628
  export default DataStore;