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.
- package/dist/alipay.js +1 -1
- package/dist/baidu.js +1 -1
- package/dist/bytedance.js +1 -1
- package/dist/jingdong.js +1 -1
- package/dist/kuaishou.js +1 -1
- package/dist/plugins/gioABTest.js +1 -1
- package/dist/plugins/gioCompress.js +1 -1
- package/dist/plugins/gioEventAutoTracking.js +1 -1
- package/dist/plugins/gioImpressionTracking.js +1 -1
- package/dist/plugins/gioMultipleInstances.js +1 -0
- package/dist/qq.js +1 -1
- package/dist/quickapp.js +1 -1
- package/dist/taobao.js +1 -1
- package/dist/taro.js +1 -1
- package/dist/uniapp.js +1 -1
- package/dist/wechat.js +1 -1
- package/package.json +39 -42
- package/rollup.config.js +11 -6
- package/rollup.plugins.config.js +18 -10
- package/src/{pluginsOut/frameworks → adapters}/gioTaobaoAdapter.ts +49 -43
- package/src/{pluginsOut/frameworks → adapters}/gioTaroAdapter.ts +6 -4
- package/src/{pluginsOut/frameworks → adapters}/gioUniAppAdapter.ts +37 -6
- package/src/constants/config.ts +48 -18
- package/src/constants/emitMsg.ts +23 -0
- package/src/constants/regex.ts +0 -1
- package/src/core/dataStore/eventContextBuilder.ts +54 -25
- package/src/core/dataStore/eventHooks/appEffects.ts +50 -31
- package/src/core/dataStore/eventHooks/index.ts +13 -6
- package/src/core/dataStore/eventHooks/minipPage.ts +41 -13
- package/src/core/dataStore/eventHooks/pageEffects.ts +54 -31
- package/src/core/dataStore/index.ts +287 -205
- package/src/core/growingIO.ts +370 -180
- package/src/core/pluginsInstance/base.ts +157 -0
- package/src/core/pluginsInstance/taro.ts +15 -0
- package/src/core/pluginsInstance/tb.ts +15 -0
- package/src/core/pluginsInstance/uniapp.ts +15 -0
- package/src/core/uploader.ts +131 -82
- package/src/core/userStore.ts +160 -121
- package/src/index.ts +37 -28
- package/src/minipInstance/base.ts +2 -1
- package/src/minipInstance/quickapp.ts +5 -19
- package/src/platformConfig/base.ts +0 -5
- package/src/{pluginsOut/ordinary → plugins}/gioABTest.ts +88 -44
- package/src/{pluginsOut/ordinary → plugins}/gioCompress.ts +2 -0
- package/src/{pluginsOut/ordinary → plugins}/gioEventAutoTracking.ts +45 -21
- package/src/{pluginsOut/ordinary → plugins}/gioImpressionTracking.ts +67 -23
- package/src/plugins/gioMultipleInstances.ts +187 -0
- package/src/types/base.ts +10 -3
- package/src/types/dataStore.ts +35 -16
- package/src/types/eventHooks.ts +8 -6
- package/src/types/growingIO.ts +74 -39
- package/src/types/platforms.ts +0 -4
- package/src/types/plugins.ts +1 -1
- package/src/types/uploader.ts +16 -10
- package/src/types/userStore.ts +21 -17
- package/src/utils/glodash.ts +10 -3
- package/src/utils/tools.ts +31 -6
- package/src/utils/verifiers.ts +25 -50
- package/typings/global.d.ts +5 -0
- package/.babelrc +0 -4
- package/bin/build/full.sh +0 -32
- package/bin/build/jd.sh +0 -14
- package/bin/build/ks.sh +0 -14
- package/bin/build/my.sh +0 -14
- package/bin/build/plugins.sh +0 -5
- package/bin/build/qq.sh +0 -14
- package/bin/build/quickapp.sh +0 -14
- package/bin/build/swan.sh +0 -14
- package/bin/build/taro.sh +0 -18
- package/bin/build/tb.sh +0 -18
- package/bin/build/tt.sh +0 -14
- package/bin/build/uniapp.sh +0 -18
- package/bin/build/wx.sh +0 -14
- package/src/core/plugins.ts +0 -152
- package/src/pluginsOut/ordinary/gioCustomTracking.ts +0 -71
- package/bin/{build/all.sh → build.sh} +3 -3
package/src/core/growingIO.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
forEach,
|
|
2
3
|
isArray,
|
|
3
4
|
isEmpty,
|
|
4
5
|
isFunction,
|
|
@@ -12,12 +13,14 @@ import {
|
|
|
12
13
|
callError,
|
|
13
14
|
consoleText,
|
|
14
15
|
eventNameValidate,
|
|
15
|
-
|
|
16
|
+
getDynamicAttributes,
|
|
17
|
+
getGlobal,
|
|
16
18
|
getPlainPlatform,
|
|
17
19
|
guid,
|
|
18
|
-
limitObject
|
|
20
|
+
limitObject,
|
|
21
|
+
niceCallback
|
|
19
22
|
} from '@@/utils/tools';
|
|
20
|
-
import {
|
|
23
|
+
import { ALLOW_SET_OPTIONS, DEFAULT_SETTINGS } from '@@/constants/config';
|
|
21
24
|
import { DataStoreType, OriginOptions } from '@@/types/dataStore';
|
|
22
25
|
import { FRAMEWORKS, PLATFORMTYPES } from '@@/types/platforms';
|
|
23
26
|
import { GrowingIOType } from '@@/types/growingIO';
|
|
@@ -32,10 +35,11 @@ import DataStore from './dataStore';
|
|
|
32
35
|
import mitt from 'mitt';
|
|
33
36
|
import platformConfig from '__GIO_PLATFORM_CONFIG__';
|
|
34
37
|
import PlatformInstance from '__GIO_PLATFORM_INSTANCE__';
|
|
35
|
-
import Plugins from '
|
|
38
|
+
import Plugins from '__GIO_PLUGIN_INSTANCE__';
|
|
36
39
|
import qs from 'querystringify';
|
|
37
40
|
import Uploader from './uploader';
|
|
38
41
|
import UserStore from '@@/core/userStore';
|
|
42
|
+
import EMIT_MSG from '@@/constants/emitMsg';
|
|
39
43
|
|
|
40
44
|
// SDK全局参数 版本号、小程序平台、框架名称、运行环境 均由打包工具替换写入
|
|
41
45
|
const sdkVersion: any = '__SDK_VERSION__';
|
|
@@ -58,7 +62,9 @@ class GrowingIO implements GrowingIOType {
|
|
|
58
62
|
public dataStore: DataStoreType;
|
|
59
63
|
public plugins: PluginsType;
|
|
60
64
|
public uploader: UploaderType;
|
|
61
|
-
|
|
65
|
+
// 当前主SDK的trackingId,用于区分事件归属。
|
|
66
|
+
public trackingId: string;
|
|
67
|
+
public subInstance: any;
|
|
62
68
|
constructor() {
|
|
63
69
|
this.utils = { ...glodash, ...tools, qs };
|
|
64
70
|
this.emitter = mitt();
|
|
@@ -94,84 +100,186 @@ class GrowingIO implements GrowingIOType {
|
|
|
94
100
|
this.dataStore = new DataStore(this);
|
|
95
101
|
// 用户实例
|
|
96
102
|
this.userStore = new UserStore(this);
|
|
103
|
+
// 初始化请求逻辑
|
|
104
|
+
this.uploader = new Uploader(this);
|
|
97
105
|
// 插件管理实例
|
|
98
106
|
this.plugins = new Plugins(this);
|
|
99
107
|
// 加载内置插件
|
|
100
108
|
this.plugins.innerPluginInit();
|
|
101
|
-
// 数据管理实例和上传实例均在各自环境中继承实现
|
|
102
109
|
}
|
|
103
110
|
|
|
111
|
+
// SDK初始化方法
|
|
112
|
+
init = (options: any) => {
|
|
113
|
+
// 初始化实例之前
|
|
114
|
+
this.emitter.emit(EMIT_MSG.ON_SDK_INITIALIZE_BEFORE, { options });
|
|
115
|
+
try {
|
|
116
|
+
consoleText('Gio小程序SDK 初始化中...', 'info');
|
|
117
|
+
if (
|
|
118
|
+
options.trackingId &&
|
|
119
|
+
this.dataStore.initializedTrackingIds.includes(options.trackingId)
|
|
120
|
+
) {
|
|
121
|
+
throw new Error(`已存在实例 ${options.trackingId},请勿重复初始化!`);
|
|
122
|
+
}
|
|
123
|
+
if (this.trackingId && !this.plugins.gioMultipleInstances) {
|
|
124
|
+
throw new Error('您正在尝试初始化另一个实例,请集成多实例插件后重试!');
|
|
125
|
+
}
|
|
126
|
+
// 初始化实例配置
|
|
127
|
+
const vdsConfig = this.dataStore.initTrackerOptions(options);
|
|
128
|
+
// 广播基础配置初始化完成
|
|
129
|
+
this.emitter?.emit(EMIT_MSG.OPTION_INITIALIZED, vdsConfig);
|
|
130
|
+
// 标记SDK已初始化完成
|
|
131
|
+
this.gioSDKInitialized = true;
|
|
132
|
+
// 初始化实例hooker
|
|
133
|
+
this.dataStore.initTrackerHooker(vdsConfig);
|
|
134
|
+
// 手动初始化用户信息
|
|
135
|
+
if (this.gioPlatform !== 'quickapp') {
|
|
136
|
+
this.userStore.initUserInfo(options.trackingId);
|
|
137
|
+
}
|
|
138
|
+
// 广播SDK初始化完成
|
|
139
|
+
this.emitter.emit(EMIT_MSG.SDK_INITIALIZED, vdsConfig);
|
|
140
|
+
// 初始化完成后把实例注入到小程序全局
|
|
141
|
+
if (!this.trackingId || this.trackingId === options.trackingId) {
|
|
142
|
+
// ?直接挂载对象,存在问题:Page.data 触发深拷贝 存在循环引用会导致死循环
|
|
143
|
+
getGlobal().__gio__ = () => this;
|
|
144
|
+
}
|
|
145
|
+
consoleText('Gio小程序SDK 初始化完成!', 'success');
|
|
146
|
+
// 在插件中手动触发visit
|
|
147
|
+
if (this.inPlugin && this.minipInstance.platform !== 'tbp') {
|
|
148
|
+
this.dataStore.sendVisit(vdsConfig.trackingId);
|
|
149
|
+
}
|
|
150
|
+
if (this.vdsConfig.forceLogin) {
|
|
151
|
+
consoleText(
|
|
152
|
+
'forceLogin已开启,请调用 identify 方法设置 openId 以继续上报!',
|
|
153
|
+
'info'
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
consoleText(error, 'error');
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// 需要校验实例的方法执行
|
|
164
|
+
handlerDistribute = (trackingId: string, handler: string, args: any) => {
|
|
165
|
+
const { initializedTrackingIds, getTrackerVds } = this.dataStore;
|
|
166
|
+
const trakerVds = getTrackerVds(trackingId);
|
|
167
|
+
if (trakerVds && initializedTrackingIds.includes(trackingId)) {
|
|
168
|
+
return this[handler](trackingId, ...args);
|
|
169
|
+
} else {
|
|
170
|
+
consoleText(`不存在实例:${trackingId},请检查!`, 'warn');
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
104
174
|
// 手动注册插件
|
|
105
175
|
registerPlugins = (plugins: any) => {
|
|
106
176
|
this.plugins.pluginItems = [...this.plugins.pluginItems, ...plugins];
|
|
107
177
|
this.plugins.installAll(plugins);
|
|
108
178
|
};
|
|
109
179
|
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// 广播基础配置初始化完成
|
|
116
|
-
this.emitter?.emit('OPTION_INITIALIZED', this);
|
|
117
|
-
// 标记SDK已初始化完成
|
|
118
|
-
this.gioSDKInitialized = true;
|
|
119
|
-
// 初始化完成后把实例注入到小程序全局
|
|
120
|
-
// ?注意不要轻易修改实例挂载的地方(这里指app),会影响分包插件和运营SDK的实例取值
|
|
121
|
-
if (!this.vdsConfig.subpackage) {
|
|
122
|
-
const app = getAppInst();
|
|
123
|
-
// 直接挂载对象,存在问题:Page.data 触发深拷贝 存在循环引用会导致死循环
|
|
124
|
-
app.__gio__ = () => {
|
|
125
|
-
return this;
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
// 初始化请求逻辑
|
|
129
|
-
this.uploader = new Uploader(this);
|
|
130
|
-
// 没有开启IDMapping的时候要把userKey清掉,防止之前有数被带到上报数据里
|
|
131
|
-
if (!this.vdsConfig.idMapping) {
|
|
132
|
-
this.userStore.userKey = '';
|
|
133
|
-
}
|
|
134
|
-
// 广播SDK初始化完成
|
|
135
|
-
this.emitter.emit('SDK_INITIALIZED', this);
|
|
136
|
-
consoleText('Gio小程序SDK 初始化完成!', 'success');
|
|
137
|
-
if (this.vdsConfig.forceLogin) {
|
|
138
|
-
consoleText(
|
|
139
|
-
'forceLogin已开启,请调用 identify 方法设置 openId 以继续上报!',
|
|
140
|
-
'info'
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
// 在插件中手动触发visit
|
|
144
|
-
if (this.inPlugin && this.minipInstance.platform !== 'tbp') {
|
|
145
|
-
this.dataStore.sendVisit();
|
|
146
|
-
}
|
|
147
|
-
return true;
|
|
148
|
-
};
|
|
180
|
+
// 获取所有已注册插件
|
|
181
|
+
getPlugins = () => this.plugins.pluginItems;
|
|
182
|
+
|
|
183
|
+
// 获取设备ID(匿名用户ID)
|
|
184
|
+
getDeviceId = () => this.userStore.getUid();
|
|
149
185
|
|
|
150
186
|
// 运行中获取配置
|
|
151
|
-
getOption = (k?: string) =>
|
|
187
|
+
getOption = (trackingId: string, k?: string) =>
|
|
188
|
+
this.dataStore.getOption(trackingId, k);
|
|
152
189
|
|
|
153
190
|
// 运行中修改配置
|
|
154
|
-
setOption = (k: string, v: any) => {
|
|
155
|
-
if (keys(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
consoleText(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
);
|
|
191
|
+
setOption = (trackingId: string, k: string, v: any) => {
|
|
192
|
+
if (keys(ALLOW_SET_OPTIONS).includes(k)) {
|
|
193
|
+
if (typeof v === DEFAULT_SETTINGS[k]?.type) {
|
|
194
|
+
this.dataStore.setOption(trackingId, k, v);
|
|
195
|
+
consoleText(`已修改${ALLOW_SET_OPTIONS[k]}: ${v}`, 'info');
|
|
196
|
+
return true;
|
|
197
|
+
} else {
|
|
198
|
+
consoleText(`参数格式不正确:${v},请检查后重试!`, 'error');
|
|
199
|
+
return false;
|
|
162
200
|
}
|
|
163
|
-
return r;
|
|
164
201
|
} else {
|
|
165
|
-
consoleText(`不存在可修改的配置项:${k},请检查后重试!`, '
|
|
202
|
+
consoleText(`不存在可修改的配置项:${k},请检查后重试!`, 'error');
|
|
166
203
|
return false;
|
|
167
204
|
}
|
|
168
205
|
};
|
|
169
206
|
|
|
170
|
-
//
|
|
171
|
-
|
|
207
|
+
// 设置页面属性
|
|
208
|
+
setPageAttributes = (trackingId: string, properties: any) => {
|
|
209
|
+
if (isObject(properties) && !isEmpty(properties)) {
|
|
210
|
+
const { currentPage } = this.dataStore.eventHooks;
|
|
211
|
+
if (isEmpty(currentPage.pageProps[trackingId])) {
|
|
212
|
+
currentPage.pageProps[trackingId] = {};
|
|
213
|
+
}
|
|
214
|
+
if (isEmpty(currentPage.pageProps[trackingId][currentPage.path])) {
|
|
215
|
+
currentPage.pageProps[trackingId][currentPage.path] = {};
|
|
216
|
+
}
|
|
217
|
+
// 结果合并,动态属性不作处理
|
|
218
|
+
if (!isEmpty(properties)) {
|
|
219
|
+
forEach(properties, (v, k) => {
|
|
220
|
+
if (
|
|
221
|
+
!isFunction(
|
|
222
|
+
currentPage.pageProps[trackingId][currentPage.path][k]
|
|
223
|
+
) ||
|
|
224
|
+
isFunction(v)
|
|
225
|
+
) {
|
|
226
|
+
currentPage.pageProps[trackingId][currentPage.path][k] = v;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return true;
|
|
231
|
+
} else {
|
|
232
|
+
callError('setPageAttributes');
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// 清空已设置的页面属性
|
|
238
|
+
clearPageAttributes = (
|
|
239
|
+
trackingId: string,
|
|
240
|
+
properties: string[] | undefined
|
|
241
|
+
) => {
|
|
242
|
+
try {
|
|
243
|
+
if (
|
|
244
|
+
!isEmpty(this.dataStore.eventHooks.currentPage.pageProps[trackingId])
|
|
245
|
+
) {
|
|
246
|
+
const { currentPage } = this.dataStore.eventHooks;
|
|
247
|
+
if (isArray(properties) && !isEmpty(properties)) {
|
|
248
|
+
properties.forEach((propName: string) => {
|
|
249
|
+
unset(
|
|
250
|
+
currentPage.pageProps[trackingId][currentPage.path],
|
|
251
|
+
propName
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
} else {
|
|
255
|
+
currentPage.pageProps[trackingId][currentPage.path] = {};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
} catch (error) {
|
|
259
|
+
callError('clearPageAttributes');
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// 手动发page
|
|
265
|
+
sendPage = (trackingId: string, props?: any) => {
|
|
266
|
+
const { trackPage } = this.dataStore.getTrackerVds(trackingId);
|
|
267
|
+
if (!trackPage) {
|
|
268
|
+
this.dataStore.sendPage(trackingId, props);
|
|
269
|
+
} else {
|
|
270
|
+
consoleText(
|
|
271
|
+
'仅在关闭trackPage时允许调用sendPage,请确认后修改初始化配置项!',
|
|
272
|
+
'error'
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
172
276
|
|
|
173
277
|
// 设置设备ID,一般为openId
|
|
174
|
-
identify = (assignmentId: string | number) => {
|
|
278
|
+
identify = (trackingId: string, assignmentId: string | number) => {
|
|
279
|
+
if (trackingId !== this.trackingId) {
|
|
280
|
+
callError('identify', !1, '子实例不允许调用identify');
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
175
283
|
if (this.vdsConfig.forceLogin) {
|
|
176
284
|
if (!verifyId(assignmentId)) {
|
|
177
285
|
callError('identify');
|
|
@@ -180,33 +288,66 @@ class GrowingIO implements GrowingIOType {
|
|
|
180
288
|
// 截取长度
|
|
181
289
|
const asId = toString(assignmentId).slice(0, 1000);
|
|
182
290
|
// 在之后的请求中使用assignmentId作为uid(deviceId)使用
|
|
183
|
-
this.userStore.
|
|
291
|
+
this.userStore.setUid(asId);
|
|
292
|
+
// 修改forceLogin配置项
|
|
293
|
+
this.dataStore.setOption(this.trackingId, 'forceLogin', false);
|
|
184
294
|
// 为已积压的请求使用assignmentId全部赋值deviceId
|
|
185
|
-
this.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
295
|
+
this.dataStore.trackersExecute((tid: string) => {
|
|
296
|
+
const hq = this.uploader.getHoardingQueue(tid);
|
|
297
|
+
hq.forEach((o, i) => (hq[i].deviceId = asId));
|
|
298
|
+
// 发送积压队列中的请求
|
|
299
|
+
this.uploader.initiateRequest(tid, true);
|
|
300
|
+
});
|
|
191
301
|
} else {
|
|
192
302
|
callError('identify', !1, 'forceLogin未开启');
|
|
193
303
|
}
|
|
194
304
|
};
|
|
195
305
|
|
|
306
|
+
// 发送用户属性
|
|
307
|
+
setUserAttributes = (trackingId: string, userAttributes: any) => {
|
|
308
|
+
if (isObject(userAttributes) && !isEmpty(userAttributes)) {
|
|
309
|
+
const { eventContextBuilder, eventInterceptor, lastVisitEvent } =
|
|
310
|
+
this.dataStore;
|
|
311
|
+
const event = {
|
|
312
|
+
eventType: 'LOGIN_USER_ATTRIBUTES',
|
|
313
|
+
...eventContextBuilder(trackingId)
|
|
314
|
+
};
|
|
315
|
+
event.attributes = limitObject({
|
|
316
|
+
...(event.attributes ?? {}),
|
|
317
|
+
...getDynamicAttributes(userAttributes)
|
|
318
|
+
});
|
|
319
|
+
// 该方法很可能被放在在app的onShow中的wx.login异步回调中,
|
|
320
|
+
// 此时页面的path和query可能还没取到,就拿visit事件的path和query补上
|
|
321
|
+
if (!event.path) {
|
|
322
|
+
event.path = lastVisitEvent.path;
|
|
323
|
+
event.query = lastVisitEvent.query;
|
|
324
|
+
event.title = lastVisitEvent.title;
|
|
325
|
+
}
|
|
326
|
+
eventInterceptor(event);
|
|
327
|
+
} else {
|
|
328
|
+
callError('setUserAttributes');
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
196
332
|
// 设置登录用户Id
|
|
197
|
-
setUserId = (
|
|
333
|
+
setUserId = (
|
|
334
|
+
trackingId: string,
|
|
335
|
+
userId: string | number,
|
|
336
|
+
userKey?: string
|
|
337
|
+
) => {
|
|
198
338
|
if (verifyId(userId)) {
|
|
199
339
|
// 切换userId要重设session补发visit
|
|
200
|
-
const prevId = this.userStore.
|
|
340
|
+
const prevId = this.userStore.getGioId(trackingId);
|
|
201
341
|
userId = toString(userId).slice(0, 1000);
|
|
202
342
|
userKey = toString(userKey).slice(0, 1000);
|
|
203
|
-
this.userStore.
|
|
204
|
-
|
|
205
|
-
|
|
343
|
+
this.userStore.setUserId(trackingId, userId);
|
|
344
|
+
const { idMapping } = this.dataStore.getTrackerVds(trackingId);
|
|
345
|
+
if (idMapping) {
|
|
346
|
+
this.userStore.setUserKey(trackingId, isNil(userKey) ? '' : userKey);
|
|
206
347
|
}
|
|
207
348
|
// 切换userId时重置session并补发visit
|
|
208
349
|
if (prevId && prevId !== userId) {
|
|
209
|
-
this.userStore.
|
|
350
|
+
this.userStore.setSessionId(trackingId);
|
|
210
351
|
const { path, query, settedTitle } =
|
|
211
352
|
this.dataStore.eventHooks.currentPage;
|
|
212
353
|
// 重新获取页面title,防止切换配置前修改了title没取到
|
|
@@ -214,7 +355,7 @@ class GrowingIO implements GrowingIOType {
|
|
|
214
355
|
settedTitle[path] ||
|
|
215
356
|
this.minipInstance.getPageTitle(this.minipInstance.getCurrentPage());
|
|
216
357
|
// visit取当前页面值
|
|
217
|
-
this.dataStore.sendVisit({ path, query });
|
|
358
|
+
this.dataStore.sendVisit(trackingId, { path, query });
|
|
218
359
|
}
|
|
219
360
|
} else {
|
|
220
361
|
callError('setUserId');
|
|
@@ -222,65 +363,127 @@ class GrowingIO implements GrowingIOType {
|
|
|
222
363
|
};
|
|
223
364
|
|
|
224
365
|
// 清除登录用户Id
|
|
225
|
-
clearUserId = () => {
|
|
226
|
-
this.userStore.
|
|
227
|
-
this.userStore.
|
|
366
|
+
clearUserId = (trackingId: string) => {
|
|
367
|
+
this.userStore.setUserId(trackingId, undefined);
|
|
368
|
+
this.userStore.setUserKey(trackingId, undefined);
|
|
228
369
|
};
|
|
229
370
|
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
this.
|
|
371
|
+
// 设置全局通用属性(即每个事件都会带上的属性值)
|
|
372
|
+
setGeneralProps = (trackingId: string, properties: any) => {
|
|
373
|
+
if (isObject(properties) && !isEmpty(properties)) {
|
|
374
|
+
if (isEmpty(this.dataStore.generalProps[trackingId])) {
|
|
375
|
+
this.dataStore.generalProps[trackingId] = {};
|
|
376
|
+
}
|
|
377
|
+
forEach(properties, (v, k) => {
|
|
378
|
+
if (
|
|
379
|
+
!isFunction(this.dataStore.generalProps[trackingId][k]) ||
|
|
380
|
+
isFunction(v)
|
|
381
|
+
) {
|
|
382
|
+
this.dataStore.generalProps[trackingId][k] = v;
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
return true;
|
|
234
386
|
} else {
|
|
235
|
-
callError('
|
|
387
|
+
callError('setGeneralProps');
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// 清空已设置的全局通用属性
|
|
393
|
+
clearGeneralProps = (
|
|
394
|
+
trackingId: string,
|
|
395
|
+
properties: string[] | undefined
|
|
396
|
+
) => {
|
|
397
|
+
try {
|
|
398
|
+
if (!isEmpty(this.dataStore.generalProps[trackingId])) {
|
|
399
|
+
if (isArray(properties) && !isEmpty(properties)) {
|
|
400
|
+
properties.forEach((propName: string) => {
|
|
401
|
+
unset(this.dataStore.generalProps[trackingId], propName);
|
|
402
|
+
});
|
|
403
|
+
} else {
|
|
404
|
+
this.dataStore.generalProps[trackingId] = {};
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
} catch (error) {
|
|
408
|
+
callError('clearGeneralProps');
|
|
409
|
+
return false;
|
|
236
410
|
}
|
|
237
411
|
};
|
|
238
412
|
|
|
239
413
|
// 自定义埋点事件
|
|
240
|
-
track = (
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
414
|
+
track = (
|
|
415
|
+
trackingId: string,
|
|
416
|
+
eventName: string,
|
|
417
|
+
properties: { [key: string]: string | string[] }
|
|
418
|
+
) => {
|
|
419
|
+
eventNameValidate(eventName, () => {
|
|
420
|
+
const { eventContextBuilder, eventInterceptor } = this.dataStore;
|
|
421
|
+
const event = {
|
|
422
|
+
eventType: 'CUSTOM',
|
|
423
|
+
eventName,
|
|
424
|
+
...eventContextBuilder(trackingId)
|
|
425
|
+
};
|
|
426
|
+
event.attributes = limitObject({
|
|
427
|
+
...(event.attributes ?? {}),
|
|
428
|
+
...getDynamicAttributes({
|
|
429
|
+
...(isObject(properties) && !isEmpty(properties) ? properties : {})
|
|
430
|
+
})
|
|
431
|
+
});
|
|
432
|
+
// 埋点事件要保留'&&sendTo'字段用于多实例复制发送
|
|
433
|
+
if (
|
|
434
|
+
this.plugins.gioMultipleInstances &&
|
|
435
|
+
properties &&
|
|
436
|
+
properties['&&sendTo']
|
|
437
|
+
) {
|
|
438
|
+
event['&&sendTo'] = properties['&&sendTo'];
|
|
439
|
+
}
|
|
440
|
+
eventInterceptor(event);
|
|
246
441
|
});
|
|
247
442
|
};
|
|
248
443
|
|
|
249
444
|
// 初始化事件计时器
|
|
250
|
-
trackTimerStart = (eventName: string) => {
|
|
251
|
-
|
|
445
|
+
trackTimerStart = (trackingId: string, eventName: string) => {
|
|
446
|
+
const { dataCollect } = this.dataStore.getTrackerVds(trackingId);
|
|
447
|
+
if (dataCollect) {
|
|
252
448
|
return eventNameValidate(eventName, () => {
|
|
253
449
|
const timerId = guid();
|
|
254
|
-
this.dataStore.trackTimers[
|
|
450
|
+
if (!this.dataStore.trackTimers[trackingId]) {
|
|
451
|
+
this.dataStore.trackTimers[trackingId] = {};
|
|
452
|
+
}
|
|
453
|
+
this.dataStore.trackTimers[trackingId][timerId] = {
|
|
255
454
|
eventName,
|
|
256
455
|
leng: 0,
|
|
257
456
|
start: +Date.now()
|
|
258
457
|
};
|
|
259
458
|
return timerId;
|
|
260
459
|
});
|
|
460
|
+
} else {
|
|
461
|
+
consoleText('指定实例未开启数据采集,请检查!', 'error');
|
|
261
462
|
}
|
|
262
463
|
return false;
|
|
263
464
|
};
|
|
264
465
|
|
|
265
466
|
// 暂停事件计时器
|
|
266
|
-
trackTimerPause = (timerId: string) => {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
467
|
+
trackTimerPause = (trackingId: string, timerId: string) => {
|
|
468
|
+
const timers = this.dataStore.trackTimers[trackingId];
|
|
469
|
+
if (timerId && timers && timers[timerId]) {
|
|
470
|
+
const timer = timers[timerId];
|
|
471
|
+
if (timer.start) {
|
|
472
|
+
timer.leng = timer.leng + (+Date.now() - timer.start);
|
|
271
473
|
}
|
|
272
|
-
|
|
474
|
+
timer.start = 0;
|
|
273
475
|
return true;
|
|
274
476
|
}
|
|
275
477
|
return false;
|
|
276
478
|
};
|
|
277
479
|
|
|
278
480
|
// 恢复事件计时器
|
|
279
|
-
trackTimerResume = (timerId: string) => {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
481
|
+
trackTimerResume = (trackingId: string, timerId: string) => {
|
|
482
|
+
const timers = this.dataStore.trackTimers[trackingId];
|
|
483
|
+
if (timerId && timers && timers[timerId]) {
|
|
484
|
+
const timer = timers[timerId];
|
|
485
|
+
if (timer.start === 0) {
|
|
486
|
+
timer.start = +Date.now();
|
|
284
487
|
}
|
|
285
488
|
return true;
|
|
286
489
|
}
|
|
@@ -288,114 +491,101 @@ class GrowingIO implements GrowingIOType {
|
|
|
288
491
|
};
|
|
289
492
|
|
|
290
493
|
// 停止事件计时器并上报事件
|
|
291
|
-
trackTimerEnd = (timerId: string,
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
494
|
+
trackTimerEnd = (trackingId: string, timerId: string, properties: any) => {
|
|
495
|
+
const { dataCollect } = this.dataStore.getTrackerVds(trackingId);
|
|
496
|
+
const timers = this.dataStore.trackTimers[trackingId];
|
|
497
|
+
if (timerId && timers && timers[timerId]) {
|
|
498
|
+
if (dataCollect) {
|
|
499
|
+
const maxEnd = 60 * 60 * 24 * 1000;
|
|
500
|
+
const timer = timers[timerId];
|
|
501
|
+
if (timer.start !== 0) {
|
|
502
|
+
const shortCut = +Date.now() - timer.start;
|
|
503
|
+
timer.leng = shortCut > 0 ? timer.leng + shortCut : 0;
|
|
299
504
|
}
|
|
300
|
-
// 要直接构建custom事件,不要去调用埋点插件的方法,万一插件没有加载就发不出去了
|
|
301
505
|
const { eventContextBuilder, eventInterceptor } = this.dataStore;
|
|
302
506
|
const event = {
|
|
303
507
|
eventType: 'CUSTOM',
|
|
304
|
-
eventName:
|
|
305
|
-
|
|
306
|
-
...attributes,
|
|
307
|
-
event_duration: tracker.leng > maxEnd ? 0 : tracker.leng / 1000
|
|
308
|
-
}),
|
|
309
|
-
...eventContextBuilder()
|
|
508
|
+
eventName: timer.eventName,
|
|
509
|
+
...eventContextBuilder(trackingId)
|
|
310
510
|
};
|
|
511
|
+
event.attributes = limitObject({
|
|
512
|
+
...(event.attributes ?? {}),
|
|
513
|
+
...getDynamicAttributes({
|
|
514
|
+
...(isObject(properties) && !isEmpty(properties) ? properties : {}),
|
|
515
|
+
event_duration: timer.leng > maxEnd ? 0 : timer.leng / 1000
|
|
516
|
+
})
|
|
517
|
+
});
|
|
518
|
+
// 埋点事件要保留'&&sendTo'字段用于多实例复制发送
|
|
519
|
+
if (
|
|
520
|
+
this.plugins.gioMultipleInstances &&
|
|
521
|
+
properties &&
|
|
522
|
+
properties['&&sendTo']
|
|
523
|
+
) {
|
|
524
|
+
event['&&sendTo'] = properties['&&sendTo'];
|
|
525
|
+
}
|
|
311
526
|
eventInterceptor(event);
|
|
312
|
-
this.removeTimer(timerId);
|
|
313
527
|
return true;
|
|
314
528
|
} else {
|
|
315
|
-
consoleText('
|
|
529
|
+
consoleText('指定实例未开启数据采集,计时器已移除,请检查!', 'error');
|
|
316
530
|
return false;
|
|
317
531
|
}
|
|
532
|
+
this.removeTimer(trackingId, timerId);
|
|
533
|
+
} else {
|
|
534
|
+
consoleText('未查询到指定计时器,请检查!', 'error');
|
|
535
|
+
return false;
|
|
318
536
|
}
|
|
319
|
-
return false;
|
|
320
537
|
};
|
|
321
538
|
|
|
322
539
|
// 移除事件计时器
|
|
323
|
-
removeTimer = (timerId: string) => {
|
|
324
|
-
|
|
325
|
-
|
|
540
|
+
removeTimer = (trackingId: string, timerId: string) => {
|
|
541
|
+
const timers = this.dataStore.trackTimers[trackingId];
|
|
542
|
+
if (timerId && timers && timers[timerId]) {
|
|
543
|
+
delete timers[timerId];
|
|
326
544
|
return true;
|
|
545
|
+
} else {
|
|
546
|
+
consoleText('未查询到指定计时器,请检查!', 'error');
|
|
547
|
+
return false;
|
|
327
548
|
}
|
|
328
|
-
return false;
|
|
329
549
|
};
|
|
330
550
|
|
|
331
551
|
// 清除所有事件计时器
|
|
332
|
-
clearTrackTimer = () => {
|
|
333
|
-
this.dataStore.trackTimers = {};
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
// 设置埋点事件的通用属性(即每个埋点事件都会带上的属性值)
|
|
337
|
-
setGeneralProps = (properties: any) => {
|
|
338
|
-
if (isObject(properties) && !isEmpty(properties)) {
|
|
339
|
-
this.dataStore.generalProps = {
|
|
340
|
-
...this.dataStore.generalProps,
|
|
341
|
-
...properties
|
|
342
|
-
};
|
|
343
|
-
keys(this.dataStore.generalProps).forEach((k: string) => {
|
|
344
|
-
if ([undefined, null].includes(this.dataStore.generalProps[k])) {
|
|
345
|
-
this.dataStore.generalProps[k] = '';
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
} else {
|
|
349
|
-
callError('setGeneralProps');
|
|
350
|
-
}
|
|
552
|
+
clearTrackTimer = (trackingId: string) => {
|
|
553
|
+
this.dataStore.trackTimers[trackingId] = {};
|
|
351
554
|
};
|
|
352
555
|
|
|
353
|
-
//
|
|
354
|
-
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
unset(this.dataStore.generalProps, prop);
|
|
358
|
-
});
|
|
359
|
-
} else {
|
|
360
|
-
this.dataStore.generalProps = {};
|
|
556
|
+
// 手动获取位置信息补发visit上报
|
|
557
|
+
setLocation = (trackingId: string, latitude: number, longitude: number) => {
|
|
558
|
+
if (isEmpty(this.dataStore.locationData[trackingId])) {
|
|
559
|
+
this.dataStore.locationData[trackingId] = {};
|
|
361
560
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
currentPage.pageProps[currentPath] = limitObject(properties);
|
|
561
|
+
const ld = this.dataStore.locationData[trackingId];
|
|
562
|
+
const verifyLT = (o: number) => o >= -180 && o <= 180;
|
|
563
|
+
if (
|
|
564
|
+
verifyLT(latitude) &&
|
|
565
|
+
verifyLT(longitude) &&
|
|
566
|
+
(ld.latitude !== latitude || ld.longitude !== longitude)
|
|
567
|
+
) {
|
|
568
|
+
this.dataStore.locationData[trackingId] = { latitude, longitude };
|
|
371
569
|
}
|
|
372
570
|
};
|
|
373
571
|
|
|
374
572
|
// 手动更新曝光监听(该方法会在曝光插件加载时被重写)
|
|
375
573
|
updateImpression = () => {
|
|
376
574
|
consoleText(
|
|
377
|
-
'
|
|
378
|
-
'
|
|
575
|
+
'updateImpression 错误! 请集成半自动埋点浏览插件后重试!',
|
|
576
|
+
'error'
|
|
379
577
|
);
|
|
380
578
|
};
|
|
381
579
|
|
|
382
|
-
//
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const verifyLT = (o: number) => o >= -180 && o <= 180;
|
|
387
|
-
if (
|
|
388
|
-
verifyLT(latitude) &&
|
|
389
|
-
verifyLT(longitude) &&
|
|
390
|
-
(ld.latitude !== latitude || ld.longitude !== longitude)
|
|
391
|
-
) {
|
|
392
|
-
this.dataStore.locationData = nld;
|
|
393
|
-
}
|
|
580
|
+
// 获取A/B实验数据
|
|
581
|
+
getABTest = (trackingId: string, layerId: string | number, callback: any) => {
|
|
582
|
+
consoleText('获取ABTest数据错误! 请集成ABTest插件后重试!', 'error');
|
|
583
|
+
niceCallback(callback, {});
|
|
394
584
|
};
|
|
395
585
|
|
|
396
586
|
// 获取打通信息
|
|
397
|
-
getGioInfo = () => {
|
|
398
|
-
const {
|
|
587
|
+
getGioInfo = (trackingId: string) => {
|
|
588
|
+
const { getUid, getUserId, getUserKey, getSessionId } = this.userStore;
|
|
399
589
|
const {
|
|
400
590
|
projectId,
|
|
401
591
|
appId,
|
|
@@ -404,19 +594,19 @@ class GrowingIO implements GrowingIOType {
|
|
|
404
594
|
idMapping,
|
|
405
595
|
extraParams,
|
|
406
596
|
ignoreFields
|
|
407
|
-
} = this.
|
|
597
|
+
} = this.dataStore.getTrackerVds(trackingId);
|
|
408
598
|
const infos: any = {
|
|
409
599
|
gioappid: appId,
|
|
410
|
-
giocs1:
|
|
600
|
+
giocs1: getUserId(trackingId) || '',
|
|
411
601
|
gioplatform: this.platformConfig.platform,
|
|
412
602
|
gioprojectid: projectId,
|
|
413
|
-
gios:
|
|
414
|
-
giou:
|
|
603
|
+
gios: getSessionId(trackingId),
|
|
604
|
+
giou: getUid()
|
|
415
605
|
};
|
|
416
606
|
infos.giodatacollect = dataCollect;
|
|
417
607
|
infos.giodatasourceid = dataSourceId;
|
|
418
608
|
if (idMapping) {
|
|
419
|
-
infos.giouserkey =
|
|
609
|
+
infos.giouserkey = getUserKey(trackingId);
|
|
420
610
|
}
|
|
421
611
|
if (!isEmpty(extraParams)) {
|
|
422
612
|
extraParams.forEach((o) => {
|