gio-miniprogram-sdk 4.3.0 → 4.3.2

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.
@@ -163,8 +163,8 @@ class GrowingIO implements GrowingIOType {
163
163
  // 需要校验实例的方法执行
164
164
  handlerDistribute = (trackingId: string, handler: string, args: any) => {
165
165
  const { initializedTrackingIds, getTrackerVds } = this.dataStore;
166
- const trakerVds = getTrackerVds(trackingId);
167
- if (trakerVds && initializedTrackingIds.includes(trackingId)) {
166
+ const trackerVds = getTrackerVds(trackingId);
167
+ if (trackerVds && initializedTrackingIds.includes(trackingId)) {
168
168
  return this[handler](trackingId, ...args);
169
169
  } else {
170
170
  consoleText(`不存在实例:${trackingId},请检查!`, 'warn');
@@ -342,10 +342,9 @@ class GrowingIO implements GrowingIOType {
342
342
  if (idMapping) {
343
343
  this.userStore.setUserKey(trackingId, isNil(userKey) ? '' : userKey);
344
344
  }
345
- // 切换userId时重置session并补发visit
345
+ // 切换userId时重置session
346
346
  if (prevId && prevId !== userId) {
347
347
  this.userStore.setSessionId(trackingId);
348
- this.dataStore.sendVisit(trackingId);
349
348
  }
350
349
  } else {
351
350
  callError('setUserId');
@@ -26,12 +26,15 @@ class UserStore implements UserStoreType {
26
26
  public _userKey: StringObject;
27
27
  // 最后一次登录用户id(持久性存储)
28
28
  public _gioId: StringObject;
29
+ // 设置了session有效期以后判断用的session失效时间
30
+ public _sessionExpires: number;
29
31
  constructor(public growingIO: GrowingIOType) {
30
32
  this._uid = undefined;
31
33
  this._sessionId = {};
32
34
  this._userId = {};
33
35
  this._userKey = {};
34
36
  this._gioId = {};
37
+ this._sessionExpires = -1;
35
38
  }
36
39
 
37
40
  // 获取sessionId存储key
@@ -69,9 +72,26 @@ class UserStore implements UserStoreType {
69
72
 
70
73
  // 获取sessionId
71
74
  getSessionId = (trackingId: string) => {
75
+ // 设置了session时长,就需要检查session是否过期
76
+ const {
77
+ vdsConfig: { sessionExpires },
78
+ dataStore: { trackersExecute }
79
+ } = this.growingIO;
80
+ // 不存在sessionId(即新进)要设一个新的sessionId
72
81
  if (!this._sessionId[trackingId]) {
73
82
  this.setSessionId(trackingId);
74
83
  }
84
+ // 设置了session时长且过期
85
+ if (sessionExpires > -1) {
86
+ // 只要有一个session超时,所有实例都要重设sessionId
87
+ if (Date.now() > this._sessionExpires) {
88
+ trackersExecute((id: string) => {
89
+ this.setSessionId(id);
90
+ });
91
+ }
92
+ // 每次获取session后要更新过期时间
93
+ this._sessionExpires = Date.now() + 1000 * 60 * sessionExpires;
94
+ }
75
95
  return this._sessionId[trackingId];
76
96
  };
77
97
 
@@ -83,9 +103,15 @@ class UserStore implements UserStoreType {
83
103
  }
84
104
  // 小程序中sessionId只需要在内存中存储就可以,不需要持久化存储
85
105
  this._sessionId[trackingId] = id;
106
+ // 设置了session时长,就需要更新过期时间
107
+ const { sessionExpires } = this.growingIO.vdsConfig;
108
+ if (sessionExpires > -1) {
109
+ this._sessionExpires = Date.now() + 1000 * 60 * sessionExpires;
110
+ }
86
111
  // 广播通知登录sessionId变更
87
112
  if (prevId !== id) {
88
113
  this.growingIO.emitter.emit(EMIT_MSG.SESSIONID_UPDATE, {
114
+ trackingId,
89
115
  newSessionId: id,
90
116
  oldSessionId: prevId
91
117
  });
@@ -64,7 +64,7 @@ class BaseInstance implements MinipInstanceType {
64
64
  // 这个currentPath一般认为是在onLoad中获取的当前小程序页面的path,此时SDK还没有parse,保存的还是上一个页面的信息
65
65
  const currentPath = self.getCurrentPath();
66
66
  const { title } = arguments[0] || {};
67
- self.growingIO.dataStore.eventHooks.currentPage.settedTitle[
67
+ self.growingIO.dataStore.eventHooks.currentPage.configuredTitle[
68
68
  currentPath
69
69
  ] = title;
70
70
  }
@@ -148,7 +148,7 @@ class BaseInstance implements MinipInstanceType {
148
148
  const { enterParams } = this.growingIO.dataStore.eventHooks.appEffects;
149
149
  if (!page.route && !isEmpty(enterParams)) {
150
150
  page.route = enterParams.path || '';
151
- title = this._getTitleFromTabbar(instConfig, page.route);
151
+ title = this._getTitleFromTabBar(instConfig, page.route);
152
152
  }
153
153
  // 第四优先级取页面的navigationBarTitleText
154
154
  niceTry(() => {
@@ -169,13 +169,13 @@ class BaseInstance implements MinipInstanceType {
169
169
  });
170
170
  // 第五优先级取tabBar配置
171
171
  if (!title) {
172
- title = this._getTitleFromTabbar(instConfig, page.route);
172
+ title = this._getTitleFromTabBar(instConfig, page.route);
173
173
  }
174
174
  }
175
175
  return limitString(title);
176
176
  };
177
177
 
178
- private _getTitleFromTabbar = (
178
+ private _getTitleFromTabBar = (
179
179
  instConfig: any,
180
180
  pageRoute: string
181
181
  ): string => {
@@ -268,8 +268,6 @@ class BaseInstance implements MinipInstanceType {
268
268
  data,
269
269
  // 微信小程序和其他小程序里叫header
270
270
  header,
271
- // 支付宝小程序里叫headers
272
- headers: header,
273
271
  timeout,
274
272
  method,
275
273
  success,
@@ -1,4 +1,6 @@
1
+ import { compareVersion } from '@@/utils/tools';
1
2
  import { GrowingIOType } from '@@/types/growingIO';
3
+ import { isFunction } from '@@/utils/glodash';
2
4
  import BaseImplements from './base';
3
5
 
4
6
  class Alipay extends BaseImplements {
@@ -20,7 +22,7 @@ class Alipay extends BaseImplements {
20
22
  // 这个currentPath一般认为是在onLoad中获取的当前小程序页面的path,此时SDK还没有parse,保存的还是上一个页面的信息
21
23
  const currentPath = self.getCurrentPath();
22
24
  const { title } = arguments[0] || {};
23
- self.growingIO.dataStore.eventHooks.currentPage.settedTitle[
25
+ self.growingIO.dataStore.eventHooks.currentPage.configuredTitle[
24
26
  currentPath
25
27
  ] = title;
26
28
  }
@@ -53,6 +55,44 @@ class Alipay extends BaseImplements {
53
55
  removeStorageSync = (key: string) => {
54
56
  this.minip?.removeStorageSync({ key });
55
57
  };
58
+
59
+ // 支付宝和mpass单独处理
60
+ request = ({
61
+ url,
62
+ data,
63
+ header,
64
+ timeout,
65
+ method,
66
+ success,
67
+ fail,
68
+ complete
69
+ }) => {
70
+ const requestTask = this.minip?.request({
71
+ url,
72
+ data,
73
+ // 支付宝小程序里叫headers
74
+ headers: header,
75
+ timeout,
76
+ method,
77
+ success,
78
+ fail,
79
+ complete
80
+ });
81
+ const myVersion = this.minip.SDKVersion;
82
+ // 支付宝小程序2.0.0版本及以上才超时中断请求
83
+ // https://github.com/growingio/growingio-sdk-miniprogram-autotracker/issues/3
84
+ if (compareVersion(myVersion, '2.0.0') >= 0) {
85
+ // 设置超时中断请求
86
+ let t = setTimeout(() => {
87
+ if (requestTask?.abort && isFunction(requestTask?.abort)) {
88
+ requestTask?.abort();
89
+ }
90
+ clearTimeout(t);
91
+ t = null;
92
+ }, (timeout || 10000) + 10);
93
+ }
94
+ return requestTask;
95
+ };
56
96
  }
57
97
 
58
98
  export default Alipay;
@@ -1,6 +1,6 @@
1
1
  import { GrowingIOType } from '@@/types/growingIO';
2
2
  import { isString, last } from '@@/utils/glodash';
3
- import { limitString } from '@@/utils/tools';
3
+ import { limitString, niceTry } from '@@/utils/tools';
4
4
  import { SystemInfo } from '@@/types/minipInstance';
5
5
  import app from '@system.app';
6
6
  import BaseImplements from './base';
@@ -97,16 +97,22 @@ class QuickApp extends BaseImplements {
97
97
  */
98
98
  // 获取当前页面栈
99
99
  getCurrentPage = () => {
100
- if (router?.getPages) {
101
- return last(router?.getPages());
102
- }
100
+ niceTry(() => {
101
+ if (router?.getPages) {
102
+ return last(router?.getPages()) || {};
103
+ }
104
+ });
103
105
  return {};
104
106
  };
105
107
 
106
108
  // 获取当前页面路由
107
109
  getCurrentPath = () => {
108
- const route = router?.getState();
109
- return route?.path;
110
+ niceTry(() => {
111
+ if (router?.getState) {
112
+ return router?.getState()?.path || '';
113
+ }
114
+ });
115
+ return '';
110
116
  };
111
117
 
112
118
  // 获取页面标题(除wx以外其他平台)
@@ -20,7 +20,7 @@ class Taobao extends BaseImplements {
20
20
  // 这个currentPath一般认为是在onLoad中获取的当前小程序页面的path,此时SDK还没有parse,保存的还是上一个页面的信息
21
21
  const currentPath = self.getCurrentPath();
22
22
  const { title } = arguments[0] || {};
23
- self.growingIO.dataStore.eventHooks.currentPage.settedTitle[
23
+ self.growingIO.dataStore.eventHooks.currentPage.configuredTitle[
24
24
  currentPath
25
25
  ] = title;
26
26
  }
@@ -11,7 +11,8 @@ import {
11
11
  isString,
12
12
  keys,
13
13
  startsWith,
14
- toString
14
+ toString,
15
+ unset
15
16
  } from '@@/utils/glodash';
16
17
  import {
17
18
  consoleText,
@@ -148,15 +149,15 @@ class GioABTest {
148
149
  `${this.getHashKey(trackingId, layerId)}_gdp_abt_sign`
149
150
  ) || 0;
150
151
  // 没有超时尝试取数据
151
- const abtData =
152
+ const expData =
152
153
  minipInstance.getStorageSync(
153
154
  `${this.getHashKey(trackingId, layerId)}_gdp_abtd`
154
155
  ) || {};
155
156
  // 没有有效数据或者接口请求标记超时则从调用分流服务获取数据
156
157
  if (!abtSign || abtSign < Date.now()) {
157
- this.initiateRequest(trackingId, layerId, abtData, callback);
158
+ this.initiateRequest(trackingId, layerId, expData, callback);
158
159
  } else {
159
- niceCallback(callback, abtData);
160
+ niceCallback(callback, expData);
160
161
  }
161
162
  };
162
163
 
@@ -234,49 +235,58 @@ class GioABTest {
234
235
  originData: any,
235
236
  callback: any
236
237
  ) => {
237
- const { layerId, strategyId, experimentId, variables } = responseData;
238
- const abtDataKey = `${this.getHashKey(trackingId, layerId)}_gdp_abtd`;
239
- const abtData = {
238
+ const {
239
+ layerId,
240
+ strategyId,
241
+ experimentId,
242
+ layerName,
243
+ experimentName,
244
+ strategyName,
245
+ variables
246
+ } = responseData;
247
+ const expDataKey = `${this.getHashKey(trackingId, layerId)}_gdp_abtd`;
248
+ // 从接口取回来的用于hash比较的数据对象
249
+ const comparisonData = {
240
250
  layerId: toString(layerId),
241
251
  strategyId: toString(strategyId),
242
252
  experimentId: toString(experimentId),
243
253
  variables
244
254
  };
245
- const comparisonValue = hashCode(JSON.stringify(abtData));
246
- const controlValue = hashCode(JSON.stringify(originData));
255
+ // 从本地存储中取回来的用于hash比较的数据对象
256
+ const controlData = { ...originData };
257
+ unset(controlData, ['layerName', 'strategyName', 'experimentName']);
258
+ const comparisonValue = hashCode(JSON.stringify(comparisonData));
259
+ const controlValue = hashCode(JSON.stringify(controlData));
260
+ // 需要传给下一步和存储的数据对象
261
+ const expData = {
262
+ ...comparisonData,
263
+ layerName,
264
+ strategyName,
265
+ experimentName
266
+ };
267
+ // 存储实验数据(无需经过hash对比判断直接复写存储,防止只改了名称)
268
+ this.growingIO.minipInstance.setStorageSync(
269
+ expDataKey,
270
+ expData,
271
+ new Date(
272
+ new Date().getFullYear(),
273
+ new Date().getMonth(),
274
+ new Date().getDate() + 1
275
+ ).getTime()
276
+ );
247
277
  // 本地实验和请求回来的实验直接做整体hash数据对比
248
278
  if (comparisonValue !== controlValue) {
249
- // 存储实验数据
250
- this.growingIO.minipInstance.setStorageSync(
251
- abtDataKey,
252
- abtData,
253
- new Date(
254
- new Date().getFullYear(),
255
- new Date().getMonth(),
256
- new Date().getDate() + 1
257
- ).getTime()
258
- );
259
279
  // 数据不一致重新发命中埋点
260
280
  if (strategyId && experimentId) {
261
- this.buildExperimentHitEvent(
262
- trackingId,
263
- toString(layerId),
264
- toString(experimentId),
265
- toString(strategyId)
266
- );
281
+ this.buildExperimentHitEvent(trackingId, expData);
267
282
  }
268
283
  }
269
284
  // 回调调用
270
- niceCallback(callback, abtData);
285
+ niceCallback(callback, expData);
271
286
  };
272
287
 
273
288
  // 构建实验命中事件
274
- buildExperimentHitEvent = (
275
- trackingId: string,
276
- layerId: string,
277
- experimentId: string,
278
- strategyId: string
279
- ) => {
289
+ buildExperimentHitEvent = (trackingId: string, expData: any) => {
280
290
  const {
281
291
  dataStore: { eventContextBuilder, eventConverter }
282
292
  } = this.growingIO;
@@ -285,11 +295,22 @@ class GioABTest {
285
295
  eventName: '$exp_hit',
286
296
  ...eventContextBuilder(trackingId)
287
297
  };
298
+ const {
299
+ layerId,
300
+ experimentId,
301
+ strategyId,
302
+ layerName,
303
+ experimentName,
304
+ strategyName
305
+ } = expData;
288
306
  event.attributes = limitObject({
289
307
  ...(event.attributes ?? {}),
290
308
  $exp_layer_id: layerId,
291
309
  $exp_id: experimentId,
292
- $exp_strategy_id: strategyId
310
+ $exp_strategy_id: strategyId,
311
+ $exp_layer_name: layerName,
312
+ $exp_name: experimentName,
313
+ $exp_strategy_name: strategyName
293
314
  });
294
315
  eventConverter(event);
295
316
  };
@@ -113,7 +113,7 @@ class GioImpressionTracking {
113
113
  };
114
114
 
115
115
  // 获取到可监听节点后校验节点信息
116
- rectobserve = (rect, collectTarget, optionKey) => {
116
+ rectObserve = (rect, collectTarget, optionKey) => {
117
117
  const { gioPlatform } = this.growingIO;
118
118
  if (
119
119
  (gioPlatform === 'tt' && collectTarget.__nodeId__) ||
@@ -146,7 +146,7 @@ class GioImpressionTracking {
146
146
  this.rects[page.route] = {};
147
147
  }
148
148
  this.rects[page.route][nodeId] = rect;
149
- this.creatObserver(collectTarget, optionKey);
149
+ this.createObserver(collectTarget, optionKey);
150
150
  }
151
151
  };
152
152
 
@@ -166,7 +166,7 @@ class GioImpressionTracking {
166
166
  .boundingClientRect(([rect = []]) => {
167
167
  rect = ut.isArray(rect) ? rect : [rect];
168
168
  if (!isEmpty(rect)) {
169
- this.rectobserve(rect, collectTarget, optionKey);
169
+ this.rectObserve(rect, collectTarget, optionKey);
170
170
  }
171
171
  });
172
172
  query.exec();
@@ -174,20 +174,22 @@ class GioImpressionTracking {
174
174
  query.selectAll('.growing_collect_imp').boundingClientRect();
175
175
  query.exec(([rect]) => {
176
176
  if (!isEmpty(rect)) {
177
- this.rectobserve(rect, collectTarget, optionKey);
177
+ this.rectObserve(rect, collectTarget, optionKey);
178
178
  }
179
179
  });
180
180
  }
181
181
  };
182
182
 
183
183
  // 创建监听
184
- creatObserver = (
184
+ createObserver = (
185
185
  collectTarget: any,
186
186
  optionKey: 'observeAll' | 'selectAll'
187
187
  ) => {
188
- const { gioPlatform, minipInstance } = this.growingIO;
188
+ const { gioPlatform, minipInstance, vdsConfig } = this.growingIO;
189
189
  // 初始化监听对象
190
- const observerOption = { [optionKey]: true };
190
+ // 数值要大于0,只能无限趋近于0,等于0的时候会导致没出现就会发曝光
191
+ const threshold = vdsConfig.impressionScale || 0.0000000000001;
192
+ const observerOption = { thresholds: [threshold], [optionKey]: true };
191
193
  if (
192
194
  ['tb', 'my'].includes(gioPlatform) &&
193
195
  ut.compareVersion(my.SDKVersion, '2.7.0') >= -1
@@ -221,7 +223,7 @@ class GioImpressionTracking {
221
223
  )
222
224
  : collectTarget.createIntersectionObserver(observerOption);
223
225
  observer = observer.relativeToViewport();
224
- // 不管原先是否创建过,直接覆盖(obeserverId会更新)
226
+ // 不管原先是否创建过,直接覆盖(observerId会更新)
225
227
  this.observerIds[page.route][nodeId] = observer;
226
228
  // 添加监听回调
227
229
  this.targetObserve(observer, page);
@@ -229,10 +231,12 @@ class GioImpressionTracking {
229
231
 
230
232
  // 给目标节点添加监听回调
231
233
  targetObserve = (observerTarget: any, collectPage: any) => {
232
- const { taro } = this.growingIO.vdsConfig;
234
+ const { taro, impressionScale } = this.growingIO.vdsConfig;
235
+ // 数值要大于0,只能无限趋近于0,等于0的时候会导致没出现就会发曝光
236
+ const threshold = impressionScale || 0.0000000000001;
233
237
  // 监听节点变化
234
238
  observerTarget.observe('.growing_collect_imp', (result: any) => {
235
- if (!ut.isEmpty(result) && result.intersectionRatio > 0) {
239
+ if (!ut.isEmpty(result) && result.intersectionRatio >= threshold) {
236
240
  let dataset: any = result.dataset;
237
241
  if (taro && ut.isTaro3(taro)) {
238
242
  dataset = this.getTaro3Dataset(collectPage.route, result.id);
@@ -82,10 +82,12 @@ export class GioMultipleInstances {
82
82
  'autotrack',
83
83
  'debug',
84
84
  'forceLogin',
85
+ 'impressionScale',
85
86
  'keepAlive',
86
87
  'originalSource',
87
88
  'performance',
88
89
  'pluginMode',
90
+ 'sessionExpires',
89
91
  'taro',
90
92
  'taroVue',
91
93
  'tbConfig',
package/src/types/base.ts CHANGED
@@ -29,6 +29,8 @@ export interface UserOptions {
29
29
  forceLogin: boolean;
30
30
  // 或略上报字段
31
31
  ignoreFields: string[];
32
+ // 曝光比例
33
+ impressionScale: number;
32
34
  // 是否使用原始来源信息作为访问事件的参数上报
33
35
  originalSource: boolean;
34
36
  // session保活时长(5分钟)
@@ -39,6 +41,8 @@ export interface UserOptions {
39
41
  requestTimeout?: number;
40
42
  // 数据上报域名
41
43
  serverUrl?: string;
44
+ // session超时时长
45
+ sessionExpires?: number;
42
46
  // taro框架实例
43
47
  taro?: any;
44
48
  // taro框架vue实例
@@ -77,12 +77,13 @@ export interface PageShareResult {
77
77
 
78
78
  export interface MinipPageType {
79
79
  queryOption: any;
80
- settedTitle: any;
80
+ configuredTitle: any;
81
81
  pageProps: any;
82
82
  lastLifecycle: string;
83
83
  currentLifecycle: string;
84
+ lifeBeforeShow: boolean;
84
85
  getPagePath: () => string;
85
- getPageQeury: () => string;
86
+ getPageQuery: () => string;
86
87
  getPageTitle: (trackingId?: string) => string;
87
88
  qsQuery: (query: any) => string;
88
89
  getReferralPage: (trackingId: string) => string;
@@ -7,6 +7,8 @@ export interface UserStoreType {
7
7
  getSessionId: (trackingId: string) => string;
8
8
  // 设置sessionId
9
9
  setSessionId: (trackingId: string, id?: string) => void;
10
+ // session超时时刻
11
+ _sessionExpires: number;
10
12
  // 获取userId
11
13
  getUserId: (trackingId: string) => string;
12
14
  // 设置userId