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