gio-miniprogram-sdk 4.1.0 → 4.3.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 (45) hide show
  1. package/.github/workflows/publish.yml +2 -0
  2. package/dist/alipay.js +1 -1
  3. package/dist/baidu.js +1 -1
  4. package/dist/bytedance.js +1 -1
  5. package/dist/jingdong.js +1 -1
  6. package/dist/kuaishou.js +1 -1
  7. package/dist/plugins/gioABTest.js +1 -1
  8. package/dist/plugins/gioCompress.js +1 -1
  9. package/dist/plugins/gioEventAutoTracking.js +1 -1
  10. package/dist/plugins/gioImpressionTracking.js +1 -1
  11. package/dist/plugins/gioMultipleInstances.js +1 -1
  12. package/dist/qq.js +1 -1
  13. package/dist/quickapp.js +1 -1
  14. package/dist/taobao.js +1 -1
  15. package/dist/taro.js +1 -1
  16. package/dist/uniapp.js +1 -1
  17. package/dist/wechat.js +1 -1
  18. package/package.json +1 -1
  19. package/rollup.config.js +1 -1
  20. package/rollup.plugins.config.js +6 -1
  21. package/src/adapters/gioTaobaoAdapter.ts +7 -3
  22. package/src/adapters/gioTaroAdapter.ts +18 -10
  23. package/src/adapters/gioUniAppAdapter.ts +3 -32
  24. package/src/constants/config.ts +1 -0
  25. package/src/core/dataStore/eventContextBuilder.ts +27 -13
  26. package/src/core/dataStore/eventHooks/appEffects.ts +62 -76
  27. package/src/core/dataStore/eventHooks/index.ts +45 -24
  28. package/src/core/dataStore/eventHooks/minipPage.ts +129 -30
  29. package/src/core/dataStore/eventHooks/pageEffects.ts +25 -53
  30. package/src/core/dataStore/index.ts +67 -74
  31. package/src/core/growingIO.ts +93 -45
  32. package/src/index.ts +12 -12
  33. package/src/minipInstance/base.ts +53 -26
  34. package/src/minipInstance/my.ts +5 -0
  35. package/src/minipInstance/tb.ts +5 -0
  36. package/src/platformConfig/base.ts +0 -1
  37. package/src/plugins/gioABTest.ts +15 -8
  38. package/src/plugins/gioCompress.ts +2 -0
  39. package/src/plugins/gioEventAutoTracking.ts +20 -3
  40. package/src/plugins/gioImpressionTracking.ts +13 -2
  41. package/src/plugins/gioMultipleInstances.ts +14 -3
  42. package/src/types/dataStore.ts +5 -1
  43. package/src/types/eventHooks.ts +13 -8
  44. package/src/types/growingIO.ts +52 -33
  45. package/src/utils/tools.ts +26 -3
@@ -1,16 +1,13 @@
1
1
  import { get, isEmpty, isFunction, unset } from '@@/utils/glodash';
2
2
  import { GrowingIOType } from '@@/types/growingIO';
3
- import { niceTry } from '@@/utils/tools';
4
3
  import { PageHookLifeCircle } from '@@/types/eventHooks';
5
4
  import EMIT_MSG from '@@/constants/emitMsg';
6
5
 
7
6
  class PageEffects {
8
7
  public buildTabClickEvent: (tabItem: any) => void;
9
8
  private prevEvent: any;
10
- private argQuery: any;
11
9
  constructor(public growingIO: GrowingIOType) {
12
10
  this.prevEvent = {};
13
- this.argQuery = {};
14
11
  }
15
12
 
16
13
  main = (page: any, event: PageHookLifeCircle, args: any) => {
@@ -23,15 +20,15 @@ class PageEffects {
23
20
  platformConfig,
24
21
  dataStore: {
25
22
  getTrackerVds,
23
+ getOriginalSource,
24
+ setOriginalSource,
26
25
  trackersExecute,
27
- shareOut,
28
26
  eventHooks,
29
27
  toggleShareOut,
30
28
  buildAppMessageEvent,
31
29
  buildTimelineEvent,
32
30
  buildAddFavorites
33
- },
34
- inPlugin
31
+ }
35
32
  }: GrowingIOType = this.growingIO;
36
33
  const { currentPage } = eventHooks;
37
34
  if (
@@ -69,43 +66,34 @@ class PageEffects {
69
66
  currentPage.currentLifecycle = event;
70
67
  switch (event) {
71
68
  case pageListeners.pageLoad: {
72
- this.argQuery[path] =
69
+ // 获取一次页面参数存起来,防止类似支付宝小程序只能通过生命周期获取页面参数或页面堆栈拿不到页面参数,做兜底
70
+ currentPage.queryOption[path] =
73
71
  get(page, 'options') ||
74
72
  get(page, '__displayReporter.query') ||
75
73
  get(page, '$page.query') ||
76
74
  get(page, '$wx.__displayReporter.query') ||
75
+ get(page, '$taroParams') ||
77
76
  args[0] ||
78
77
  {};
79
- unset(this.argQuery[path], '$taroTimestamp');
80
- currentPage.parsePage(page, this.argQuery[path]);
78
+ unset(currentPage.queryOption[path], '$taroTimestamp');
81
79
  break;
82
80
  }
83
81
  case pageListeners.pageShow: {
84
- if (inPlugin) {
85
- currentPage.parsePage(page, this.argQuery[path]);
86
- if (!currentPage.path) {
87
- // 插件中没有页面时直接将插件appId作为页面信息
88
- currentPage.path = `/插件${vdsConfig.appId}}`;
89
- currentPage.title = `/插件${vdsConfig.appId}}`;
82
+ trackersExecute((trackingId: string) => {
83
+ // 检查originalSource内容是否已经被消费,如果没有被消费是同一个页面,说明visit还没被发出去,要更新title
84
+ const originalSource = getOriginalSource(trackingId);
85
+ if (!isEmpty(originalSource) && originalSource.path === path) {
86
+ setOriginalSource(trackingId, {
87
+ ...originalSource,
88
+ title: currentPage.getPageTitle()
89
+ });
90
90
  }
91
- trackersExecute((trackingId: string) => {
92
- const { trackPage } = getTrackerVds(trackingId);
93
- if (trackPage) {
94
- this.buildPageEvent(trackingId);
95
- }
96
- });
97
- } else if (!shareOut || !eventHooks.currentPage.time) {
98
- // 不是因为分享切出再返回的onshow(视为第一次进入改页面)和切出去以后因为超时或者进入的场景值不一致时(会在appshow清掉页面时间),发page
99
- currentPage.parsePage(page, this.argQuery[path]);
100
- // 超时进入页面时前后path一致parsePage方法不会重置页面时间,可能会没有值,所以要补充重设一次
101
- eventHooks.currentPage.time = Date.now();
102
- trackersExecute((trackingId: string) => {
103
- const { trackPage } = getTrackerVds(trackingId);
104
- if (trackPage) {
105
- this.buildPageEvent(trackingId);
106
- }
107
- });
108
- }
91
+ // 发page事件
92
+ const { trackPage } = getTrackerVds(trackingId);
93
+ if (trackPage) {
94
+ this.buildPageEvent(trackingId);
95
+ }
96
+ });
109
97
  // 分享标记置为false
110
98
  toggleShareOut(false);
111
99
  break;
@@ -157,12 +145,6 @@ class PageEffects {
157
145
  default:
158
146
  break;
159
147
  }
160
- // 页面销毁移除当前页面的属性
161
- if (event === pageListeners.pageUnload) {
162
- trackersExecute((trackingId: string) => {
163
- currentPage.pageProps[trackingId] = undefined;
164
- });
165
- }
166
148
  };
167
149
 
168
150
  // 构建页面访问事件
@@ -172,29 +154,19 @@ class PageEffects {
172
154
  eventContextBuilder,
173
155
  eventInterceptor,
174
156
  eventHooks: { currentPage }
175
- },
176
- minipInstance
157
+ }
177
158
  } = this.growingIO;
178
159
  const event = {
179
160
  eventType: 'PAGE',
180
161
  referralPage: currentPage.getReferralPage(trackingId),
181
- ...eventContextBuilder(trackingId),
182
- // page事件要单独设一个title以覆盖eventContextBuilder中的lastPage的title错误值
183
- title:
184
- currentPage?.title ||
185
- minipInstance.getPageTitle(minipInstance.getCurrentPage()),
186
- timestamp: currentPage.time
162
+ ...eventContextBuilder(trackingId)
187
163
  };
164
+ // 合并页面属性
165
+ event.attributes = currentPage.eventSetPageProps(trackingId, event);
188
166
  // 传入参数生成的page事件取值为传入参数
189
167
  if (!isEmpty(props) && props.title) {
190
168
  event.title = props.title;
191
169
  }
192
- // 添加页面属性
193
- const pageProps = niceTry(() => currentPage.pageProps[trackingId]);
194
- if (!isEmpty(pageProps)) {
195
- event.attributes = pageProps;
196
- currentPage.pageProps[trackingId] = undefined;
197
- }
198
170
  eventInterceptor(event);
199
171
  };
200
172
  }
@@ -13,7 +13,6 @@ import {
13
13
  isBoolean,
14
14
  isEmpty,
15
15
  isFunction,
16
- isNil,
17
16
  isString,
18
17
  keys,
19
18
  typeOf,
@@ -25,6 +24,7 @@ import {
25
24
  consoleText,
26
25
  getGlobal,
27
26
  guid,
27
+ limitObject,
28
28
  niceTry
29
29
  } from '@@/utils/tools';
30
30
  import {
@@ -93,7 +93,7 @@ class DataStore implements DataStoreType {
93
93
  EMIT_MSG.ON_COMMIT_REQUEST,
94
94
  ({ eventData: event, trackingId }) => {
95
95
  if (event.eventType === 'VISIT') {
96
- this.lastVisitEvent = event;
96
+ this.lastVisitEvent[trackingId] = event;
97
97
  }
98
98
  if (event.eventType === 'PAGE') {
99
99
  this.lastPageEvent[trackingId] = event;
@@ -218,26 +218,25 @@ class DataStore implements DataStoreType {
218
218
  };
219
219
 
220
220
  // 保存初始来源信息
221
- setOriginalSource = (trackingId: string, { path, query }) => {
221
+ setOriginalSource = (trackingId: string, origins: any) => {
222
222
  const { minipInstance } = this.growingIO;
223
- if (isNil(this.getOriginalSource(trackingId))) {
224
- const originalSource = { path, query, title: '' };
225
- minipInstance.setStorageSync(
226
- this.getStorageKey(trackingId, 'originalSource'),
227
- JSON.stringify(originalSource)
228
- );
229
- }
223
+ minipInstance.setStorageSync(
224
+ this.getStorageKey(trackingId, 'originalSource'),
225
+ JSON.stringify(origins)
226
+ );
230
227
  };
231
228
 
232
229
  // 获取初始来源信息
233
230
  getOriginalSource = (trackingId: string) => {
234
231
  const { minipInstance } = this.growingIO;
235
- return niceTry(() =>
236
- JSON.parse(
237
- minipInstance.getStorageSync(
238
- this.getStorageKey(trackingId, 'originalSource')
232
+ return (
233
+ niceTry(() =>
234
+ JSON.parse(
235
+ minipInstance.getStorageSync(
236
+ this.getStorageKey(trackingId, 'originalSource')
237
+ )
239
238
  )
240
- )
239
+ ) ?? {}
241
240
  );
242
241
  };
243
242
 
@@ -262,12 +261,14 @@ class DataStore implements DataStoreType {
262
261
  const { platformConfig, inPlugin, minipInstance, plugins } = this.growingIO;
263
262
  const { uniVue, taro } = vdsConfig;
264
263
  // 如果是使用全量版本时,当前小程序不是框架的,要允许原生的hook
265
- if (!(uniVue || taro)) {
264
+ if (!(uniVue || taro || minipInstance.platform === 'quickapp')) {
266
265
  platformConfig.canHook = true;
267
266
  }
268
267
  // 初始化核心钩子(重写全局)
269
268
  if (!inPlugin || ['tbp', 'jdp'].includes(minipInstance.platform)) {
270
269
  this.eventHooks.initEventHooks();
270
+ } else {
271
+ this.eventHooks.initOriginalValue();
271
272
  }
272
273
  /** 第三方框架重写 */
273
274
  // uniapp
@@ -364,19 +365,11 @@ class DataStore implements DataStoreType {
364
365
  this.updateVdsConfig(trackingId, { ...trakerVds, [k]: v });
365
366
  // 从关闭到打开dataCollect时补发visit和page
366
367
  if (k === 'dataCollect' && prevConfig.dataCollect !== v && v) {
368
+ // 更新session
367
369
  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 });
370
+ // 重发visit/page
371
+ this.sendVisit(trackingId);
372
+ this.sendPage(trackingId);
380
373
  }
381
374
  // 配置项有变更要全局广播
382
375
  emitter.emit(EMIT_MSG.OPTION_CHANGE, { optionName: k, optionValue: v });
@@ -430,10 +423,7 @@ class DataStore implements DataStoreType {
430
423
 
431
424
  // 手动调用visit事件的方法
432
425
  sendVisit = (trackingId: string, props?: any) => {
433
- (this.eventHooks.appEffects as any).buildVisitEvent(
434
- trackingId,
435
- props ?? this.lastVisitEvent
436
- );
426
+ (this.eventHooks.appEffects as any).buildVisitEvent(trackingId, props);
437
427
  };
438
428
 
439
429
  // 手动调用page事件的方法
@@ -481,6 +471,26 @@ class DataStore implements DataStoreType {
481
471
  }
482
472
  };
483
473
 
474
+ // 事件重组
475
+ eventRefactor = (e: any) => {
476
+ // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
477
+ const ne = {
478
+ ...e,
479
+ ...this.eventContextBuilder(e.trackingId, {
480
+ path: e.path,
481
+ query: e.query,
482
+ // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
483
+ timestamp: e.timestamp
484
+ })
485
+ };
486
+ // 防止事件原有的属性被通用属性直接覆盖
487
+ ne.attributes = {
488
+ ...(ne.attributes ?? {}),
489
+ ...(e.attributes ?? {})
490
+ };
491
+ return ne;
492
+ };
493
+
484
494
  // 事件拦截器(有的通用维度字段需要异步获取,为了防止事件在通用维度还没返回之前就发出去)一般只有最开始的个别事件会被拦住
485
495
  eventInterceptor = (event: any) => {
486
496
  const { systemInfo, network } = this.growingIO.minipInstance;
@@ -490,17 +500,7 @@ class DataStore implements DataStoreType {
490
500
  } else if (!isEmpty(this.interceptEvents)) {
491
501
  // 有通用维度字段了,且有被拦截的事件,放一起重新添加通用维度字段再提交转换
492
502
  [...this.interceptEvents, event].forEach((e: any) => {
493
- // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
494
- const ne = {
495
- ...e,
496
- ...this.eventContextBuilder(event.trackingId, {
497
- path: e.path,
498
- query: e.query,
499
- // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
500
- timestamp: e.timestamp
501
- })
502
- };
503
- this.eventConverter(ne);
503
+ this.eventConverter(this.eventRefactor(e));
504
504
  });
505
505
  this.interceptEvents = [];
506
506
  } else {
@@ -516,17 +516,7 @@ class DataStore implements DataStoreType {
516
516
  } = this.growingIO;
517
517
  if (systemInfo && network && !isEmpty(this.interceptEvents)) {
518
518
  [...this.interceptEvents].forEach((e: any) => {
519
- // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
520
- const ne = {
521
- ...e,
522
- ...this.eventContextBuilder(e.trackingId, {
523
- path: e.path,
524
- query: e.query,
525
- // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
526
- timestamp: e.timestamp
527
- })
528
- };
529
- this.eventConverter(ne);
519
+ this.eventConverter(this.eventRefactor(e));
530
520
  });
531
521
  this.interceptEvents = [];
532
522
  }
@@ -548,16 +538,17 @@ class DataStore implements DataStoreType {
548
538
  const event = {
549
539
  eventType: 'CUSTOM',
550
540
  eventName: '$mp_on_share',
551
- attributes: {
552
- $from: originResult.from,
553
- $target: originResult?.target?.id,
554
- $share_title: updateResult?.title,
555
- $share_path: head(uri),
556
- $share_query: uri[1],
557
- ...updateResult?.attributes
558
- },
559
541
  ...eventContextBuilder(trackingId)
560
542
  };
543
+ event.attributes = limitObject({
544
+ ...(event.attributes ?? {}),
545
+ $from: originResult.from,
546
+ $target: originResult?.target?.id,
547
+ $share_title: updateResult?.title,
548
+ $share_path: head(uri),
549
+ $share_query: uri[1],
550
+ ...updateResult?.attributes
551
+ });
561
552
  eventInterceptor(event);
562
553
  };
563
554
 
@@ -577,15 +568,16 @@ class DataStore implements DataStoreType {
577
568
  const event = {
578
569
  eventType: 'CUSTOM',
579
570
  eventName: '$mp_share_timeline',
580
- attributes: {
581
- $target: originResult?.target?.id,
582
- $share_title: updateResult?.title,
583
- $share_path: head(uri),
584
- $share_query: uri[1],
585
- ...updateResult?.attributes
586
- },
587
571
  ...eventContextBuilder(trackingId)
588
572
  };
573
+ event.attributes = limitObject({
574
+ ...(event.attributes ?? {}),
575
+ $target: originResult?.target?.id,
576
+ $share_title: updateResult?.title,
577
+ $share_path: head(uri),
578
+ $share_query: uri[1],
579
+ ...updateResult?.attributes
580
+ });
589
581
  eventInterceptor(event);
590
582
  };
591
583
 
@@ -605,13 +597,14 @@ class DataStore implements DataStoreType {
605
597
  const event = {
606
598
  eventType: 'CUSTOM',
607
599
  eventName: '$mp_add_favorites',
608
- attributes: {
609
- $share_title: updateResult?.title,
610
- $share_path: head(uri),
611
- $share_query: uri[1]
612
- },
613
600
  ...eventContextBuilder(trackingId)
614
601
  };
602
+ event.attributes = limitObject({
603
+ ...(event.attributes ?? {}),
604
+ $share_title: updateResult?.title,
605
+ $share_path: head(uri),
606
+ $share_query: uri[1]
607
+ });
615
608
  eventInterceptor(event);
616
609
  };
617
610
 
@@ -1,4 +1,5 @@
1
1
  import {
2
+ forEach,
2
3
  isArray,
3
4
  isEmpty,
4
5
  isFunction,
@@ -205,15 +206,55 @@ class GrowingIO implements GrowingIOType {
205
206
 
206
207
  // 设置页面属性
207
208
  setPageAttributes = (trackingId: string, properties: any) => {
208
- const { currentPage } = this.dataStore.eventHooks;
209
- if (isEmpty(currentPage.pageProps[trackingId])) {
210
- currentPage.pageProps[trackingId] = {};
209
+ if (isObject(properties) && !isEmpty(properties)) {
210
+ const { currentPage } = this.dataStore.eventHooks;
211
+ const path = currentPage.getPagePath();
212
+ if (isEmpty(currentPage.pageProps[trackingId])) {
213
+ currentPage.pageProps[trackingId] = {};
214
+ }
215
+ if (isEmpty(currentPage.pageProps[trackingId][path])) {
216
+ currentPage.pageProps[trackingId][path] = {};
217
+ }
218
+ // 结果合并,动态属性不作处理
219
+ if (!isEmpty(properties)) {
220
+ forEach(properties, (v, k) => {
221
+ if (
222
+ !isFunction(currentPage.pageProps[trackingId][path][k]) ||
223
+ isFunction(v)
224
+ ) {
225
+ currentPage.pageProps[trackingId][path][k] = v;
226
+ }
227
+ });
228
+ }
229
+ return true;
230
+ } else {
231
+ callError('setPageAttributes');
232
+ return false;
211
233
  }
212
- if (!isEmpty(properties)) {
213
- currentPage.pageProps[trackingId] = {
214
- ...currentPage.pageProps[trackingId],
215
- ...limitObject(properties)
216
- };
234
+ };
235
+
236
+ // 清空已设置的页面属性
237
+ clearPageAttributes = (
238
+ trackingId: string,
239
+ properties: string[] | undefined
240
+ ) => {
241
+ try {
242
+ if (
243
+ !isEmpty(this.dataStore.eventHooks.currentPage.pageProps[trackingId])
244
+ ) {
245
+ const { currentPage } = this.dataStore.eventHooks;
246
+ const path = currentPage.getPagePath();
247
+ if (isArray(properties) && !isEmpty(properties)) {
248
+ properties.forEach((propName: string) => {
249
+ unset(currentPage.pageProps[trackingId][path], propName);
250
+ });
251
+ } else {
252
+ currentPage.pageProps[trackingId][path] = {};
253
+ }
254
+ }
255
+ } catch (error) {
256
+ callError('clearPageAttributes');
257
+ return false;
217
258
  }
218
259
  };
219
260
 
@@ -261,20 +302,23 @@ class GrowingIO implements GrowingIOType {
261
302
 
262
303
  // 发送用户属性
263
304
  setUserAttributes = (trackingId: string, userAttributes: any) => {
264
- if (!isEmpty(userAttributes) && isObject(userAttributes)) {
305
+ if (isObject(userAttributes) && !isEmpty(userAttributes)) {
265
306
  const { eventContextBuilder, eventInterceptor, lastVisitEvent } =
266
307
  this.dataStore;
267
308
  const event = {
268
309
  eventType: 'LOGIN_USER_ATTRIBUTES',
269
- attributes: limitObject(userAttributes),
270
310
  ...eventContextBuilder(trackingId)
271
311
  };
312
+ event.attributes = limitObject({
313
+ ...(event.attributes ?? {}),
314
+ ...getDynamicAttributes(userAttributes)
315
+ });
272
316
  // 该方法很可能被放在在app的onShow中的wx.login异步回调中,
273
317
  // 此时页面的path和query可能还没取到,就拿visit事件的path和query补上
274
318
  if (!event.path) {
275
- event.path = lastVisitEvent.path;
276
- event.query = lastVisitEvent.query;
277
- event.title = lastVisitEvent.title;
319
+ event.path = lastVisitEvent[trackingId]?.path;
320
+ event.query = lastVisitEvent[trackingId]?.query;
321
+ event.title = lastVisitEvent[trackingId]?.title;
278
322
  }
279
323
  eventInterceptor(event);
280
324
  } else {
@@ -301,14 +345,7 @@ class GrowingIO implements GrowingIOType {
301
345
  // 切换userId时重置session并补发visit
302
346
  if (prevId && prevId !== userId) {
303
347
  this.userStore.setSessionId(trackingId);
304
- const { path, query, settedTitle } =
305
- this.dataStore.eventHooks.currentPage;
306
- // 重新获取页面title,防止切换配置前修改了title没取到
307
- this.dataStore.eventHooks.currentPage.title =
308
- settedTitle[path] ||
309
- this.minipInstance.getPageTitle(this.minipInstance.getCurrentPage());
310
- // visit取当前页面值
311
- this.dataStore.sendVisit(trackingId, { path, query });
348
+ this.dataStore.sendVisit(trackingId);
312
349
  }
313
350
  } else {
314
351
  callError('setUserId');
@@ -321,13 +358,20 @@ class GrowingIO implements GrowingIOType {
321
358
  this.userStore.setUserKey(trackingId, undefined);
322
359
  };
323
360
 
324
- // 设置埋点事件的通用属性(即每个埋点事件都会带上的属性值)
361
+ // 设置全局通用属性(即每个事件都会带上的属性值)
325
362
  setGeneralProps = (trackingId: string, properties: any) => {
326
- if (!isEmpty(properties)) {
327
- this.dataStore.generalProps[trackingId] = {
328
- ...(this.dataStore.generalProps[trackingId] ?? {}),
329
- ...properties
330
- };
363
+ if (isObject(properties) && !isEmpty(properties)) {
364
+ if (isEmpty(this.dataStore.generalProps[trackingId])) {
365
+ this.dataStore.generalProps[trackingId] = {};
366
+ }
367
+ forEach(properties, (v, k) => {
368
+ if (
369
+ !isFunction(this.dataStore.generalProps[trackingId][k]) ||
370
+ isFunction(v)
371
+ ) {
372
+ this.dataStore.generalProps[trackingId][k] = v;
373
+ }
374
+ });
331
375
  return true;
332
376
  } else {
333
377
  callError('setGeneralProps');
@@ -335,14 +379,13 @@ class GrowingIO implements GrowingIOType {
335
379
  }
336
380
  };
337
381
 
338
- // 清空已设置的埋点事件的通用属性
382
+ // 清空已设置的全局通用属性
339
383
  clearGeneralProps = (
340
384
  trackingId: string,
341
385
  properties: string[] | undefined
342
386
  ) => {
343
387
  try {
344
388
  if (!isEmpty(this.dataStore.generalProps[trackingId])) {
345
- // 获取目标tracker的引用
346
389
  if (isArray(properties) && !isEmpty(properties)) {
347
390
  properties.forEach((propName: string) => {
348
391
  unset(this.dataStore.generalProps[trackingId], propName);
@@ -352,7 +395,7 @@ class GrowingIO implements GrowingIOType {
352
395
  }
353
396
  }
354
397
  } catch (error) {
355
- callError('setGeneralProps');
398
+ callError('clearGeneralProps');
356
399
  return false;
357
400
  }
358
401
  };
@@ -360,22 +403,22 @@ class GrowingIO implements GrowingIOType {
360
403
  // 自定义埋点事件
361
404
  track = (
362
405
  trackingId: string,
363
- name: string,
406
+ eventName: string,
364
407
  properties: { [key: string]: string | string[] }
365
408
  ) => {
366
- eventNameValidate(name, () => {
367
- const { eventContextBuilder, eventInterceptor, generalProps } =
368
- this.dataStore;
369
- const mergedProperties = {
370
- ...(generalProps[trackingId] ?? {}),
371
- ...(isObject(properties) && !isEmpty(properties) ? properties : {})
372
- };
409
+ eventNameValidate(eventName, () => {
410
+ const { eventContextBuilder, eventInterceptor } = this.dataStore;
373
411
  const event = {
374
412
  eventType: 'CUSTOM',
375
- eventName: name,
376
- attributes: limitObject(getDynamicAttributes(mergedProperties)),
413
+ eventName,
377
414
  ...eventContextBuilder(trackingId)
378
415
  };
416
+ event.attributes = limitObject({
417
+ ...(event.attributes ?? {}),
418
+ ...getDynamicAttributes({
419
+ ...(isObject(properties) && !isEmpty(properties) ? properties : {})
420
+ })
421
+ });
379
422
  // 埋点事件要保留'&&sendTo'字段用于多实例复制发送
380
423
  if (
381
424
  this.plugins.gioMultipleInstances &&
@@ -453,12 +496,15 @@ class GrowingIO implements GrowingIOType {
453
496
  const event = {
454
497
  eventType: 'CUSTOM',
455
498
  eventName: timer.eventName,
456
- attributes: limitObject({
457
- ...properties,
458
- event_duration: timer.leng > maxEnd ? 0 : timer.leng / 1000
459
- }),
460
499
  ...eventContextBuilder(trackingId)
461
500
  };
501
+ event.attributes = limitObject({
502
+ ...(event.attributes ?? {}),
503
+ ...getDynamicAttributes({
504
+ ...(isObject(properties) && !isEmpty(properties) ? properties : {}),
505
+ event_duration: timer.leng > maxEnd ? 0 : timer.leng / 1000
506
+ })
507
+ });
462
508
  // 埋点事件要保留'&&sendTo'字段用于多实例复制发送
463
509
  if (
464
510
  this.plugins.gioMultipleInstances &&
@@ -555,7 +601,9 @@ class GrowingIO implements GrowingIOType {
555
601
  if (!isEmpty(extraParams)) {
556
602
  extraParams.forEach((o) => {
557
603
  if (!ignoreFields.includes(o)) {
558
- infos[`gio${o}`] = this.dataStore.lastVisitEvent[o];
604
+ infos[`gio${o}`] = (this.dataStore.lastVisitEvent[trackingId] ?? {})[
605
+ o
606
+ ];
559
607
  }
560
608
  });
561
609
  }
package/src/index.ts CHANGED
@@ -62,16 +62,16 @@ const gdp = function () {
62
62
  getGlobal().gdp = gdp;
63
63
  getGlobal().gioSDKVersion = gioInstance.sdkVersion;
64
64
 
65
- export const GioApp = niceTry(
66
- () => gioInstance.dataStore.eventHooks.growingApp ?? App
67
- );
68
- export const GioPage = niceTry(
69
- () => gioInstance.dataStore.eventHooks.growingPage ?? Page
70
- );
71
- export const GioComponent = niceTry(
72
- () => gioInstance.dataStore.eventHooks.growingComponent ?? Component
73
- );
74
- export const GioBehavior = niceTry(
75
- () => gioInstance.dataStore.eventHooks.growingBehavior ?? Behavior
76
- );
65
+ const {
66
+ growingApp,
67
+ growingPage,
68
+ growingComponent,
69
+ growingBehavior,
70
+ initOriginalValue
71
+ } = gioInstance.dataStore.eventHooks;
72
+ initOriginalValue();
73
+ export const GioApp = niceTry(() => growingApp ?? App);
74
+ export const GioPage = niceTry(() => growingPage ?? Page);
75
+ export const GioComponent = niceTry(() => growingComponent ?? Component);
76
+ export const GioBehavior = niceTry(() => growingBehavior ?? Behavior);
77
77
  export default gdp;