@openreplay/tracker 17.0.0 → 17.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/entry.js +1072 -47
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +1070 -47
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/index.d.ts +1 -0
- package/dist/cjs/main/app/session.d.ts +1 -0
- package/dist/cjs/main/entry.d.ts +5 -4
- package/dist/cjs/main/index.d.ts +17 -5
- package/dist/cjs/main/modules/analytics/batcher.d.ts +46 -0
- package/dist/cjs/main/modules/analytics/constantProperties.d.ts +53 -0
- package/dist/cjs/main/modules/analytics/demo.d.ts +0 -0
- package/dist/cjs/main/modules/analytics/events.d.ts +37 -0
- package/dist/cjs/main/modules/analytics/index.d.ts +73 -0
- package/dist/cjs/main/modules/analytics/people.d.ts +51 -0
- package/dist/cjs/main/modules/analytics/types.d.ts +32 -0
- package/dist/cjs/main/modules/analytics/utils.d.ts +19 -0
- package/dist/lib/entry.js +1071 -48
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +1070 -47
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/index.d.ts +1 -0
- package/dist/lib/main/app/session.d.ts +1 -0
- package/dist/lib/main/entry.d.ts +5 -4
- package/dist/lib/main/index.d.ts +17 -5
- package/dist/lib/main/modules/analytics/batcher.d.ts +46 -0
- package/dist/lib/main/modules/analytics/constantProperties.d.ts +53 -0
- package/dist/lib/main/modules/analytics/demo.d.ts +0 -0
- package/dist/lib/main/modules/analytics/events.d.ts +37 -0
- package/dist/lib/main/modules/analytics/index.d.ts +73 -0
- package/dist/lib/main/modules/analytics/people.d.ts +51 -0
- package/dist/lib/main/modules/analytics/types.d.ts +32 -0
- package/dist/lib/main/modules/analytics/utils.d.ts +19 -0
- package/dist/types/main/app/index.d.ts +1 -0
- package/dist/types/main/app/session.d.ts +1 -0
- package/dist/types/main/entry.d.ts +5 -4
- package/dist/types/main/index.d.ts +17 -5
- package/dist/types/main/modules/analytics/batcher.d.ts +46 -0
- package/dist/types/main/modules/analytics/constantProperties.d.ts +53 -0
- package/dist/types/main/modules/analytics/demo.d.ts +0 -0
- package/dist/types/main/modules/analytics/events.d.ts +37 -0
- package/dist/types/main/modules/analytics/index.d.ts +73 -0
- package/dist/types/main/modules/analytics/people.d.ts +51 -0
- package/dist/types/main/modules/analytics/types.d.ts +32 -0
- package/dist/types/main/modules/analytics/utils.d.ts +19 -0
- package/package.json +3 -3
package/dist/cjs/entry.js
CHANGED
|
@@ -3519,8 +3519,7 @@ class Observer {
|
|
|
3519
3519
|
sl.assignedNodes({ flatten: true }).forEach((n) => {
|
|
3520
3520
|
const nid = this.app.nodes.getID(n);
|
|
3521
3521
|
if (nid !== undefined) {
|
|
3522
|
-
this.recents.set(nid, RecentsType.
|
|
3523
|
-
this.commitNode(nid);
|
|
3522
|
+
this.recents.set(nid, RecentsType.Changed);
|
|
3524
3523
|
}
|
|
3525
3524
|
});
|
|
3526
3525
|
});
|
|
@@ -3587,13 +3586,6 @@ class Observer {
|
|
|
3587
3586
|
return true;
|
|
3588
3587
|
}
|
|
3589
3588
|
let slot = node.assignedSlot;
|
|
3590
|
-
let isLightDom = false;
|
|
3591
|
-
if (slot) {
|
|
3592
|
-
// Check if the node is in light DOM (not in shadow DOM)
|
|
3593
|
-
// This is a workaround for the issue with shadow DOM and slots
|
|
3594
|
-
// where the slot is not assigned to the node in shadow DOM.
|
|
3595
|
-
isLightDom = node.getRootNode() instanceof ShadowRoot;
|
|
3596
|
-
}
|
|
3597
3589
|
const parent = node.parentNode;
|
|
3598
3590
|
let parentID;
|
|
3599
3591
|
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
|
@@ -3606,15 +3598,7 @@ class Observer {
|
|
|
3606
3598
|
this.unbindTree(node);
|
|
3607
3599
|
return false;
|
|
3608
3600
|
}
|
|
3609
|
-
|
|
3610
|
-
parentID = this.app.nodes.getID(slot);
|
|
3611
|
-
// in light dom, we don't "slot" the node,
|
|
3612
|
-
// but rather use the slot as a parent
|
|
3613
|
-
slot = null;
|
|
3614
|
-
}
|
|
3615
|
-
else {
|
|
3616
|
-
parentID = this.app.nodes.getID(parent);
|
|
3617
|
-
}
|
|
3601
|
+
parentID = this.app.nodes.getID(parent);
|
|
3618
3602
|
if (parentID === undefined) {
|
|
3619
3603
|
this.unbindTree(node);
|
|
3620
3604
|
return false;
|
|
@@ -3910,12 +3894,12 @@ function getInlineOptions(mode, logger) {
|
|
|
3910
3894
|
case InlineCssMode.Unset:
|
|
3911
3895
|
const isLocalhost = /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?\/?/.test(window.location.href);
|
|
3912
3896
|
if (isLocalhost) {
|
|
3913
|
-
logger(`Enabling InlineCssMode by default on localhost to preserve css styles, refer to ${localhostStylesDoc} for details, set InlineCssMode to 0 to skip this behavior`);
|
|
3897
|
+
logger(`Enabling InlineCssMode.PlainFetched by default on localhost to preserve css styles, refer to ${localhostStylesDoc} for details, set InlineCssMode to 0 to skip this behavior`);
|
|
3914
3898
|
return {
|
|
3915
3899
|
inlineRemoteCss: true,
|
|
3916
3900
|
inlinerOptions: {
|
|
3917
|
-
forceFetch:
|
|
3918
|
-
forcePlain:
|
|
3901
|
+
forceFetch: true,
|
|
3902
|
+
forcePlain: true,
|
|
3919
3903
|
},
|
|
3920
3904
|
};
|
|
3921
3905
|
}
|
|
@@ -4163,6 +4147,7 @@ class Sanitizer {
|
|
|
4163
4147
|
}
|
|
4164
4148
|
}
|
|
4165
4149
|
|
|
4150
|
+
const tokenSeparator = '_$_';
|
|
4166
4151
|
class Session {
|
|
4167
4152
|
constructor(params) {
|
|
4168
4153
|
this.metadata = {};
|
|
@@ -4190,19 +4175,22 @@ class Session {
|
|
|
4190
4175
|
this.getSessionToken = (projectKey) => {
|
|
4191
4176
|
const tokenWithProject = this.token || this.app.sessionStorage.getItem(this.options.session_token_key);
|
|
4192
4177
|
if (projectKey && tokenWithProject) {
|
|
4193
|
-
const savedProject = tokenWithProject.split(
|
|
4178
|
+
const savedProject = tokenWithProject.split(tokenSeparator)[1];
|
|
4194
4179
|
if (!savedProject || savedProject !== projectKey) {
|
|
4195
4180
|
this.app.sessionStorage.removeItem(this.options.session_token_key);
|
|
4196
4181
|
this.token = undefined;
|
|
4197
4182
|
return undefined;
|
|
4198
4183
|
}
|
|
4199
4184
|
}
|
|
4200
|
-
const token = tokenWithProject ? tokenWithProject.split(
|
|
4185
|
+
const token = tokenWithProject ? tokenWithProject.split(tokenSeparator)[0] : null;
|
|
4201
4186
|
return token || undefined;
|
|
4202
4187
|
};
|
|
4188
|
+
this.getRawTokenWithProject = () => {
|
|
4189
|
+
return this.token || this.app.sessionStorage.getItem(this.options.session_token_key);
|
|
4190
|
+
};
|
|
4203
4191
|
this.setSessionToken = (token, projectKey) => {
|
|
4204
|
-
this.token = `${token}
|
|
4205
|
-
this.app.sessionStorage.setItem(this.options.session_token_key, `${token}
|
|
4192
|
+
this.token = `${token}${tokenSeparator}${projectKey}`;
|
|
4193
|
+
this.app.sessionStorage.setItem(this.options.session_token_key, `${token}${tokenSeparator}${projectKey}`);
|
|
4206
4194
|
};
|
|
4207
4195
|
this.app = params.app;
|
|
4208
4196
|
this.options = params.options;
|
|
@@ -4265,7 +4253,7 @@ class Session {
|
|
|
4265
4253
|
}
|
|
4266
4254
|
getSessionHash() {
|
|
4267
4255
|
const pageNo = this.getPageNumber();
|
|
4268
|
-
const token = this.
|
|
4256
|
+
const token = this.getRawTokenWithProject();
|
|
4269
4257
|
if (pageNo === undefined || token === undefined) {
|
|
4270
4258
|
return;
|
|
4271
4259
|
}
|
|
@@ -4395,6 +4383,9 @@ const proto = {
|
|
|
4395
4383
|
startIframe: 'start tracker inside frame',
|
|
4396
4384
|
// checking updates
|
|
4397
4385
|
polling: 'hello-how-are-you-im-under-the-water-please-help-me',
|
|
4386
|
+
// happens if tab is old and has outdated token but
|
|
4387
|
+
// not communicating with backend to update it (for whatever reason)
|
|
4388
|
+
reset: 'reset-your-session-please',
|
|
4398
4389
|
};
|
|
4399
4390
|
class App {
|
|
4400
4391
|
constructor(projectKey, sessionToken, options, signalError, insideIframe) {
|
|
@@ -4411,7 +4402,7 @@ class App {
|
|
|
4411
4402
|
this.stopCallbacks = [];
|
|
4412
4403
|
this.commitCallbacks = [];
|
|
4413
4404
|
this.activityState = ActivityState.NotActive;
|
|
4414
|
-
this.version = '17.
|
|
4405
|
+
this.version = '17.1.0'; // TODO: version compatability check inside each plugin.
|
|
4415
4406
|
this.socketMode = false;
|
|
4416
4407
|
this.compressionThreshold = 24 * 1000;
|
|
4417
4408
|
this.bc = null;
|
|
@@ -4645,6 +4636,19 @@ class App {
|
|
|
4645
4636
|
}
|
|
4646
4637
|
};
|
|
4647
4638
|
this.startTimeout = null;
|
|
4639
|
+
this.restart = () => {
|
|
4640
|
+
this.stop(false);
|
|
4641
|
+
this.waitStatus(ActivityState.NotActive).then(() => {
|
|
4642
|
+
this.allowAppStart();
|
|
4643
|
+
this.start(this.prevOpts, true)
|
|
4644
|
+
.then((r) => {
|
|
4645
|
+
this.debug.info('Session restart', r);
|
|
4646
|
+
})
|
|
4647
|
+
.catch((e) => {
|
|
4648
|
+
this.debug.error('Session restart failed', e);
|
|
4649
|
+
});
|
|
4650
|
+
});
|
|
4651
|
+
};
|
|
4648
4652
|
this.send = (message, urgent = false) => {
|
|
4649
4653
|
if (this.activityState === ActivityState.NotActive) {
|
|
4650
4654
|
return;
|
|
@@ -4806,7 +4810,12 @@ class App {
|
|
|
4806
4810
|
});
|
|
4807
4811
|
this.session.attachUpdateCallback(({ userID, metadata }) => {
|
|
4808
4812
|
if (userID != null) {
|
|
4809
|
-
|
|
4813
|
+
if (!userID ||
|
|
4814
|
+
typeof userID !== 'string' ||
|
|
4815
|
+
userID.trim().length === 0) {
|
|
4816
|
+
this.debug.warn('Invalid userID (must be type string), ignoring.');
|
|
4817
|
+
return;
|
|
4818
|
+
}
|
|
4810
4819
|
this.send(UserID(userID));
|
|
4811
4820
|
}
|
|
4812
4821
|
if (metadata != null) {
|
|
@@ -4881,6 +4890,12 @@ class App {
|
|
|
4881
4890
|
});
|
|
4882
4891
|
}
|
|
4883
4892
|
}
|
|
4893
|
+
if (ev.data.line === proto.reset) {
|
|
4894
|
+
const newToken = ev.data.token;
|
|
4895
|
+
this.debug.log('Received reset signal from another tab');
|
|
4896
|
+
this.session.setSessionToken(newToken, this.projectKey);
|
|
4897
|
+
this.restart();
|
|
4898
|
+
}
|
|
4884
4899
|
};
|
|
4885
4900
|
}
|
|
4886
4901
|
}
|
|
@@ -5453,9 +5468,10 @@ class App {
|
|
|
5453
5468
|
// Reset session metadata only if requested directly
|
|
5454
5469
|
this.session.reset();
|
|
5455
5470
|
}
|
|
5471
|
+
const userId = startOpts.userID ? startOpts.userID.trim() : undefined;
|
|
5456
5472
|
this.session.assign({
|
|
5457
5473
|
// MBTODO: maybe it would make sense to `forceNew` if the `userID` was changed
|
|
5458
|
-
userID:
|
|
5474
|
+
userID: userId || undefined,
|
|
5459
5475
|
metadata: startOpts.metadata,
|
|
5460
5476
|
});
|
|
5461
5477
|
const timestamp = now();
|
|
@@ -5522,6 +5538,12 @@ class App {
|
|
|
5522
5538
|
}
|
|
5523
5539
|
this.delay = delay;
|
|
5524
5540
|
this.session.setSessionToken(token, this.projectKey);
|
|
5541
|
+
if (sessionToken && sessionToken !== token) {
|
|
5542
|
+
this.bc?.postMessage({
|
|
5543
|
+
type: proto.reset,
|
|
5544
|
+
token: token,
|
|
5545
|
+
});
|
|
5546
|
+
}
|
|
5525
5547
|
this.session.setUserInfo({
|
|
5526
5548
|
userBrowser,
|
|
5527
5549
|
userCity,
|
|
@@ -7412,9 +7434,9 @@ function axiosSpy (app, instance, opts, sanitize, stringify) {
|
|
|
7412
7434
|
});
|
|
7413
7435
|
}
|
|
7414
7436
|
function isAxiosError(payload) {
|
|
7415
|
-
return isObject(payload) && payload.isAxiosError === true;
|
|
7437
|
+
return isObject$1(payload) && payload.isAxiosError === true;
|
|
7416
7438
|
}
|
|
7417
|
-
function isObject(thing) {
|
|
7439
|
+
function isObject$1(thing) {
|
|
7418
7440
|
return thing !== null && typeof thing === 'object';
|
|
7419
7441
|
}
|
|
7420
7442
|
|
|
@@ -8828,6 +8850,969 @@ function webAnimations(app, options = {}) {
|
|
|
8828
8850
|
});
|
|
8829
8851
|
}
|
|
8830
8852
|
|
|
8853
|
+
/**
|
|
8854
|
+
* Detects client browser, OS, and device information
|
|
8855
|
+
*/
|
|
8856
|
+
function uaParse(sWindow) {
|
|
8857
|
+
const unknown = '-';
|
|
8858
|
+
// Screen detection
|
|
8859
|
+
let width = 0;
|
|
8860
|
+
let height = 0;
|
|
8861
|
+
let screenSize = '';
|
|
8862
|
+
if (sWindow.screen.width) {
|
|
8863
|
+
width = sWindow.screen.width;
|
|
8864
|
+
height = sWindow.screen.height;
|
|
8865
|
+
screenSize = `${width} x ${height}`;
|
|
8866
|
+
}
|
|
8867
|
+
// Browser detection
|
|
8868
|
+
const nVer = sWindow.navigator.appVersion ?? '0';
|
|
8869
|
+
const nAgt = sWindow.navigator.userAgent ?? 'unknown';
|
|
8870
|
+
let browser = sWindow.navigator.appName ?? "unknown";
|
|
8871
|
+
let version = String(parseFloat(nVer));
|
|
8872
|
+
let nameOffset;
|
|
8873
|
+
let verOffset;
|
|
8874
|
+
let ix;
|
|
8875
|
+
// Browser detection logic
|
|
8876
|
+
if ((verOffset = nAgt.indexOf('YaBrowser')) !== -1) {
|
|
8877
|
+
browser = 'Yandex';
|
|
8878
|
+
version = nAgt.substring(verOffset + 10);
|
|
8879
|
+
}
|
|
8880
|
+
else if ((verOffset = nAgt.indexOf('SamsungBrowser')) !== -1) {
|
|
8881
|
+
browser = 'Samsung';
|
|
8882
|
+
version = nAgt.substring(verOffset + 15);
|
|
8883
|
+
}
|
|
8884
|
+
else if ((verOffset = nAgt.indexOf('UCBrowser')) !== -1) {
|
|
8885
|
+
browser = 'UC Browser';
|
|
8886
|
+
version = nAgt.substring(verOffset + 10);
|
|
8887
|
+
}
|
|
8888
|
+
else if ((verOffset = nAgt.indexOf('OPR')) !== -1) {
|
|
8889
|
+
browser = 'Opera';
|
|
8890
|
+
version = nAgt.substring(verOffset + 4);
|
|
8891
|
+
}
|
|
8892
|
+
else if ((verOffset = nAgt.indexOf('Opera')) !== -1) {
|
|
8893
|
+
browser = 'Opera';
|
|
8894
|
+
version = nAgt.substring(verOffset + 6);
|
|
8895
|
+
if ((verOffset = nAgt.indexOf('Version')) !== -1) {
|
|
8896
|
+
version = nAgt.substring(verOffset + 8);
|
|
8897
|
+
}
|
|
8898
|
+
}
|
|
8899
|
+
else if ((verOffset = nAgt.indexOf('Edge')) !== -1) {
|
|
8900
|
+
browser = 'Microsoft Legacy Edge';
|
|
8901
|
+
version = nAgt.substring(verOffset + 5);
|
|
8902
|
+
}
|
|
8903
|
+
else if ((verOffset = nAgt.indexOf('Edg')) !== -1) {
|
|
8904
|
+
browser = 'Microsoft Edge';
|
|
8905
|
+
version = nAgt.substring(verOffset + 4);
|
|
8906
|
+
}
|
|
8907
|
+
else if ((verOffset = nAgt.indexOf('MSIE')) !== -1) {
|
|
8908
|
+
browser = 'Microsoft Internet Explorer';
|
|
8909
|
+
version = nAgt.substring(verOffset + 5);
|
|
8910
|
+
}
|
|
8911
|
+
else if ((verOffset = nAgt.indexOf('Chrome')) !== -1) {
|
|
8912
|
+
browser = 'Chrome';
|
|
8913
|
+
version = nAgt.substring(verOffset + 7);
|
|
8914
|
+
}
|
|
8915
|
+
else if ((verOffset = nAgt.indexOf('Safari')) !== -1) {
|
|
8916
|
+
browser = 'Safari';
|
|
8917
|
+
version = nAgt.substring(verOffset + 7);
|
|
8918
|
+
if ((verOffset = nAgt.indexOf('Version')) !== -1) {
|
|
8919
|
+
version = nAgt.substring(verOffset + 8);
|
|
8920
|
+
}
|
|
8921
|
+
}
|
|
8922
|
+
else if ((verOffset = nAgt.indexOf('Firefox')) !== -1) {
|
|
8923
|
+
browser = 'Firefox';
|
|
8924
|
+
version = nAgt.substring(verOffset + 8);
|
|
8925
|
+
}
|
|
8926
|
+
else if (nAgt.indexOf('Trident/') !== -1) {
|
|
8927
|
+
browser = 'Microsoft Internet Explorer';
|
|
8928
|
+
version = nAgt.substring(nAgt.indexOf('rv:') + 3);
|
|
8929
|
+
}
|
|
8930
|
+
else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {
|
|
8931
|
+
browser = nAgt.substring(nameOffset, verOffset);
|
|
8932
|
+
version = nAgt.substring(verOffset + 1);
|
|
8933
|
+
if (browser.toLowerCase() === browser.toUpperCase()) {
|
|
8934
|
+
browser = sWindow.navigator.appName;
|
|
8935
|
+
}
|
|
8936
|
+
}
|
|
8937
|
+
// Trim the version string
|
|
8938
|
+
if ((ix = version.indexOf(';')) !== -1) {
|
|
8939
|
+
version = version.substring(0, ix);
|
|
8940
|
+
}
|
|
8941
|
+
if ((ix = version.indexOf(' ')) !== -1) {
|
|
8942
|
+
version = version.substring(0, ix);
|
|
8943
|
+
}
|
|
8944
|
+
if ((ix = version.indexOf(')')) !== -1) {
|
|
8945
|
+
version = version.substring(0, ix);
|
|
8946
|
+
}
|
|
8947
|
+
let majorVersion = parseInt(version, 10);
|
|
8948
|
+
if (isNaN(majorVersion)) {
|
|
8949
|
+
version = String(parseFloat(nVer));
|
|
8950
|
+
majorVersion = parseInt(nVer, 10);
|
|
8951
|
+
}
|
|
8952
|
+
// Mobile detection
|
|
8953
|
+
const mobile = /Mobile|mini|Fennec|Android|iP(ad|od|hone)/.test(nVer);
|
|
8954
|
+
// Cookie detection
|
|
8955
|
+
let cookieEnabled = sWindow.navigator.cookieEnabled || false;
|
|
8956
|
+
if (typeof navigator.cookieEnabled === 'undefined' && !cookieEnabled) {
|
|
8957
|
+
sWindow.document.cookie = 'testcookie';
|
|
8958
|
+
cookieEnabled = sWindow.document.cookie.indexOf('testcookie') !== -1;
|
|
8959
|
+
}
|
|
8960
|
+
// OS detection
|
|
8961
|
+
let os = unknown;
|
|
8962
|
+
const clientStrings = [
|
|
8963
|
+
{ s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ },
|
|
8964
|
+
{ s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ },
|
|
8965
|
+
{ s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ },
|
|
8966
|
+
{ s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ },
|
|
8967
|
+
{ s: 'Windows Vista', r: /Windows NT 6.0/ },
|
|
8968
|
+
{ s: 'Windows Server 2003', r: /Windows NT 5.2/ },
|
|
8969
|
+
{ s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ },
|
|
8970
|
+
{ s: 'Windows 2000', r: /(Windows NT 5.0|Windows 2000)/ },
|
|
8971
|
+
{ s: 'Windows ME', r: /(Win 9x 4.90|Windows ME)/ },
|
|
8972
|
+
{ s: 'Windows 98', r: /(Windows 98|Win98)/ },
|
|
8973
|
+
{ s: 'Windows 95', r: /(Windows 95|Win95|Windows_95)/ },
|
|
8974
|
+
{ s: 'Windows NT 4.0', r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ },
|
|
8975
|
+
{ s: 'Windows CE', r: /Windows CE/ },
|
|
8976
|
+
{ s: 'Windows 3.11', r: /Win16/ },
|
|
8977
|
+
{ s: 'Android', r: /Android/ },
|
|
8978
|
+
{ s: 'Open BSD', r: /OpenBSD/ },
|
|
8979
|
+
{ s: 'Sun OS', r: /SunOS/ },
|
|
8980
|
+
{ s: 'Chrome OS', r: /CrOS/ },
|
|
8981
|
+
{ s: 'Linux', r: /(Linux|X11(?!.*CrOS))/ },
|
|
8982
|
+
{ s: 'iOS', r: /(iPhone|iPad|iPod)/ },
|
|
8983
|
+
{ s: 'Mac OS X', r: /Mac OS X/ },
|
|
8984
|
+
{ s: 'Mac OS', r: /(Mac OS|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ },
|
|
8985
|
+
{ s: 'QNX', r: /QNX/ },
|
|
8986
|
+
{ s: 'UNIX', r: /UNIX/ },
|
|
8987
|
+
{ s: 'BeOS', r: /BeOS/ },
|
|
8988
|
+
{ s: 'OS/2', r: /OS\/2/ },
|
|
8989
|
+
{
|
|
8990
|
+
s: 'Search Bot',
|
|
8991
|
+
r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/,
|
|
8992
|
+
},
|
|
8993
|
+
];
|
|
8994
|
+
// Find matching OS
|
|
8995
|
+
for (const client of clientStrings) {
|
|
8996
|
+
if (client.r.test(nAgt)) {
|
|
8997
|
+
os = client.s;
|
|
8998
|
+
break;
|
|
8999
|
+
}
|
|
9000
|
+
}
|
|
9001
|
+
// OS Version detection
|
|
9002
|
+
let osVersion = unknown;
|
|
9003
|
+
if (/Windows/.test(os)) {
|
|
9004
|
+
const matches = /Windows (.*)/.exec(os);
|
|
9005
|
+
if (matches && matches[1]) {
|
|
9006
|
+
osVersion = matches[1];
|
|
9007
|
+
// Handle Windows 10/11 detection with newer API if available
|
|
9008
|
+
if (osVersion === '10' && 'userAgentData' in sWindow.navigator) {
|
|
9009
|
+
const nav = navigator;
|
|
9010
|
+
if (nav.userAgentData) {
|
|
9011
|
+
nav.userAgentData
|
|
9012
|
+
.getHighEntropyValues(['platformVersion'])
|
|
9013
|
+
.then((ua) => {
|
|
9014
|
+
const version = parseInt(ua.platformVersion.split('.')[0], 10);
|
|
9015
|
+
osVersion = version < 13 ? '10' : '11';
|
|
9016
|
+
})
|
|
9017
|
+
.catch(() => {
|
|
9018
|
+
// ignore errors and keep osVersion as is
|
|
9019
|
+
});
|
|
9020
|
+
}
|
|
9021
|
+
}
|
|
9022
|
+
}
|
|
9023
|
+
os = 'Windows';
|
|
9024
|
+
}
|
|
9025
|
+
// OS version detection for Mac/Android/iOS
|
|
9026
|
+
switch (os) {
|
|
9027
|
+
case 'Mac OS':
|
|
9028
|
+
case 'Mac OS X':
|
|
9029
|
+
case 'Android': {
|
|
9030
|
+
const matches = /(?:Android|Mac OS|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh) ([\.\_\d]+)/.exec(nAgt);
|
|
9031
|
+
osVersion = matches && matches[1] ? matches[1] : unknown;
|
|
9032
|
+
break;
|
|
9033
|
+
}
|
|
9034
|
+
case 'iOS': {
|
|
9035
|
+
const matches = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer);
|
|
9036
|
+
if (matches && matches[1]) {
|
|
9037
|
+
osVersion = `${matches[1]}.${matches[2]}.${parseInt(matches[3] || '0', 10)}`;
|
|
9038
|
+
}
|
|
9039
|
+
break;
|
|
9040
|
+
}
|
|
9041
|
+
}
|
|
9042
|
+
// Return client data
|
|
9043
|
+
return {
|
|
9044
|
+
screen: screenSize,
|
|
9045
|
+
width,
|
|
9046
|
+
height,
|
|
9047
|
+
browser,
|
|
9048
|
+
browserVersion: version,
|
|
9049
|
+
browserMajorVersion: majorVersion,
|
|
9050
|
+
mobile,
|
|
9051
|
+
os,
|
|
9052
|
+
osVersion,
|
|
9053
|
+
cookies: cookieEnabled,
|
|
9054
|
+
};
|
|
9055
|
+
}
|
|
9056
|
+
function isObject(item) {
|
|
9057
|
+
const isNull = item === null;
|
|
9058
|
+
return Boolean(item && typeof item === 'object' && !Array.isArray(item) && !isNull);
|
|
9059
|
+
}
|
|
9060
|
+
function getUTCOffsetString() {
|
|
9061
|
+
const date = new Date();
|
|
9062
|
+
const offsetMinutes = date.getTimezoneOffset();
|
|
9063
|
+
const hours = Math.abs(Math.floor(offsetMinutes / 60));
|
|
9064
|
+
const minutes = Math.abs(offsetMinutes % 60);
|
|
9065
|
+
const sign = offsetMinutes <= 0 ? '+' : '-';
|
|
9066
|
+
const hoursStr = hours.toString().padStart(2, '0');
|
|
9067
|
+
const minutesStr = minutes.toString().padStart(2, '0');
|
|
9068
|
+
return `UTC${sign}${hoursStr}:${minutesStr}`;
|
|
9069
|
+
}
|
|
9070
|
+
|
|
9071
|
+
const refKey = '$__or__initial_ref__$';
|
|
9072
|
+
const distinctIdKey = '$__or__distinct_device_id__$';
|
|
9073
|
+
const utmParamsKey = '$__or__utm_params__$';
|
|
9074
|
+
const superPropKey = '$__or__super_properties__$';
|
|
9075
|
+
const userIdKey = '$__or__user_id__$';
|
|
9076
|
+
const win = 'window' in globalThis
|
|
9077
|
+
? window
|
|
9078
|
+
: {
|
|
9079
|
+
navigator: { userAgent: '' },
|
|
9080
|
+
screen: {},
|
|
9081
|
+
document: {
|
|
9082
|
+
cookie: '',
|
|
9083
|
+
},
|
|
9084
|
+
location: { search: '' },
|
|
9085
|
+
};
|
|
9086
|
+
const doc = 'document' in globalThis ? document : { referrer: '' };
|
|
9087
|
+
const searchEngineList = [
|
|
9088
|
+
'google',
|
|
9089
|
+
'bing',
|
|
9090
|
+
'yahoo',
|
|
9091
|
+
'baidu',
|
|
9092
|
+
'yandex',
|
|
9093
|
+
'duckduckgo',
|
|
9094
|
+
'ecosia',
|
|
9095
|
+
'ask',
|
|
9096
|
+
'aol',
|
|
9097
|
+
'wolframalpha',
|
|
9098
|
+
'startpage',
|
|
9099
|
+
'swisscows',
|
|
9100
|
+
'qwant',
|
|
9101
|
+
'lycos',
|
|
9102
|
+
'dogpile',
|
|
9103
|
+
'info',
|
|
9104
|
+
'teoma',
|
|
9105
|
+
'webcrawler',
|
|
9106
|
+
'naver',
|
|
9107
|
+
'seznam',
|
|
9108
|
+
'perplexity',
|
|
9109
|
+
];
|
|
9110
|
+
class ConstantProperties {
|
|
9111
|
+
constructor(localStorage, sessionStorage) {
|
|
9112
|
+
this.localStorage = localStorage;
|
|
9113
|
+
this.sessionStorage = sessionStorage;
|
|
9114
|
+
this.user_id = null;
|
|
9115
|
+
this.setUserId = (user_id) => {
|
|
9116
|
+
this.user_id = user_id;
|
|
9117
|
+
this.sessionStorage.setItem(userIdKey, user_id ?? '');
|
|
9118
|
+
};
|
|
9119
|
+
this.resetUserId = (hard) => {
|
|
9120
|
+
this.user_id = null;
|
|
9121
|
+
if (hard) {
|
|
9122
|
+
this.deviceId = this.getDistinctDeviceId(true);
|
|
9123
|
+
}
|
|
9124
|
+
};
|
|
9125
|
+
this.getDistinctDeviceId = (force) => {
|
|
9126
|
+
const potentialStored = this.localStorage.getItem(distinctIdKey);
|
|
9127
|
+
if (potentialStored && !force) {
|
|
9128
|
+
return potentialStored;
|
|
9129
|
+
}
|
|
9130
|
+
else {
|
|
9131
|
+
const distinctId = `${Math.random().toString(36).slice(2)}-${Math.random().toString(36).slice(2)}-${Math.random().toString(36).slice(2)}`;
|
|
9132
|
+
this.localStorage.setItem(distinctIdKey, distinctId);
|
|
9133
|
+
return distinctId;
|
|
9134
|
+
}
|
|
9135
|
+
};
|
|
9136
|
+
this.getReferrer = () => {
|
|
9137
|
+
const potentialStored = this.sessionStorage.getItem(refKey);
|
|
9138
|
+
if (potentialStored) {
|
|
9139
|
+
return potentialStored;
|
|
9140
|
+
}
|
|
9141
|
+
else {
|
|
9142
|
+
const ref = doc.referrer;
|
|
9143
|
+
this.sessionStorage.setItem(refKey, ref);
|
|
9144
|
+
return ref;
|
|
9145
|
+
}
|
|
9146
|
+
};
|
|
9147
|
+
this.parseUTM = () => {
|
|
9148
|
+
const potentialStored = this.sessionStorage.getItem(utmParamsKey);
|
|
9149
|
+
if (potentialStored) {
|
|
9150
|
+
const obj = JSON.parse(potentialStored);
|
|
9151
|
+
this.utmSource = obj.utm_source;
|
|
9152
|
+
this.utmMedium = obj.utm_medium;
|
|
9153
|
+
this.utmCampaign = obj.utm_campaign;
|
|
9154
|
+
}
|
|
9155
|
+
else {
|
|
9156
|
+
const searchParams = new URLSearchParams(win.location.search);
|
|
9157
|
+
this.utmSource = searchParams.get('utm_source') || null;
|
|
9158
|
+
this.utmMedium = searchParams.get('utm_medium') || null;
|
|
9159
|
+
this.utmCampaign = searchParams.get('utm_campaign') || null;
|
|
9160
|
+
const obj = {
|
|
9161
|
+
utm_source: this.utmSource,
|
|
9162
|
+
utm_medium: this.utmMedium,
|
|
9163
|
+
utm_campaign: this.utmCampaign,
|
|
9164
|
+
};
|
|
9165
|
+
this.sessionStorage.setItem(utmParamsKey, JSON.stringify(obj));
|
|
9166
|
+
}
|
|
9167
|
+
};
|
|
9168
|
+
this.getSearchEngine = (ref) => {
|
|
9169
|
+
for (const searchEngine of searchEngineList) {
|
|
9170
|
+
if (ref.includes(searchEngine)) {
|
|
9171
|
+
return searchEngine;
|
|
9172
|
+
}
|
|
9173
|
+
}
|
|
9174
|
+
return null;
|
|
9175
|
+
};
|
|
9176
|
+
this.getSuperProperties = () => {
|
|
9177
|
+
const potentialStored = this.localStorage.getItem(superPropKey);
|
|
9178
|
+
if (potentialStored) {
|
|
9179
|
+
return JSON.parse(potentialStored);
|
|
9180
|
+
}
|
|
9181
|
+
else {
|
|
9182
|
+
return {};
|
|
9183
|
+
}
|
|
9184
|
+
};
|
|
9185
|
+
this.saveSuperProperties = (props) => {
|
|
9186
|
+
this.localStorage.setItem(superPropKey, JSON.stringify(props));
|
|
9187
|
+
};
|
|
9188
|
+
this.clearSuperProperties = () => {
|
|
9189
|
+
this.localStorage.setItem(superPropKey, JSON.stringify({}));
|
|
9190
|
+
};
|
|
9191
|
+
const { width, height, browser, browserVersion, browserMajorVersion, os, osVersion, mobile } = uaParse(win);
|
|
9192
|
+
const storedUserId = this.sessionStorage.getItem(userIdKey);
|
|
9193
|
+
if (storedUserId) {
|
|
9194
|
+
this.user_id = storedUserId;
|
|
9195
|
+
}
|
|
9196
|
+
this.os = os;
|
|
9197
|
+
this.osVersion = osVersion;
|
|
9198
|
+
this.browser = `${browser}`;
|
|
9199
|
+
this.browserVersion = `${browserVersion} (${browserMajorVersion})`;
|
|
9200
|
+
this.platform = mobile ? 'mobile' : 'desktop';
|
|
9201
|
+
this.screenHeight = height;
|
|
9202
|
+
this.screenWidth = width;
|
|
9203
|
+
this.initialReferrer = this.getReferrer();
|
|
9204
|
+
this.deviceId = this.getDistinctDeviceId();
|
|
9205
|
+
this.searchEngine = this.getSearchEngine(this.initialReferrer);
|
|
9206
|
+
this.parseUTM();
|
|
9207
|
+
}
|
|
9208
|
+
get all() {
|
|
9209
|
+
return {
|
|
9210
|
+
os: this.os,
|
|
9211
|
+
os_version: this.osVersion,
|
|
9212
|
+
browser: this.browser,
|
|
9213
|
+
browser_version: this.browserVersion,
|
|
9214
|
+
platform: this.platform,
|
|
9215
|
+
screen_height: this.screenHeight,
|
|
9216
|
+
screen_width: this.screenWidth,
|
|
9217
|
+
initial_referrer: this.initialReferrer,
|
|
9218
|
+
utm_source: this.utmSource,
|
|
9219
|
+
utm_medium: this.utmMedium,
|
|
9220
|
+
utm_campaign: this.utmCampaign,
|
|
9221
|
+
user_id: this.user_id,
|
|
9222
|
+
distinct_id: this.deviceId,
|
|
9223
|
+
sdk_edition: 'web',
|
|
9224
|
+
sdk_version: '17.1.0',
|
|
9225
|
+
timezone: getUTCOffsetString(),
|
|
9226
|
+
search_engine: this.searchEngine,
|
|
9227
|
+
};
|
|
9228
|
+
}
|
|
9229
|
+
get defaultPropertyKeys() {
|
|
9230
|
+
return Object.keys(this.all);
|
|
9231
|
+
}
|
|
9232
|
+
get distinctId() {
|
|
9233
|
+
return this.deviceId;
|
|
9234
|
+
}
|
|
9235
|
+
}
|
|
9236
|
+
|
|
9237
|
+
const mutationTypes = {
|
|
9238
|
+
identity: 'identity',
|
|
9239
|
+
deleteUser: 'delete_user',
|
|
9240
|
+
setProperty: 'set_property',
|
|
9241
|
+
setPropertyOnce: 'set_property_once',
|
|
9242
|
+
appendProperty: 'append_property',
|
|
9243
|
+
appendUniqueProperty: 'append_unique_property',
|
|
9244
|
+
incrementProperty: 'increment_property',
|
|
9245
|
+
};
|
|
9246
|
+
const categories = {
|
|
9247
|
+
people: 'user_actions',
|
|
9248
|
+
events: 'events',
|
|
9249
|
+
};
|
|
9250
|
+
const createEvent = (category, type, timestamp, payload) => {
|
|
9251
|
+
if (category === categories.people) {
|
|
9252
|
+
return {
|
|
9253
|
+
category,
|
|
9254
|
+
data: {
|
|
9255
|
+
type,
|
|
9256
|
+
user_id: payload.user_id,
|
|
9257
|
+
payload: payload.properties,
|
|
9258
|
+
timestamp,
|
|
9259
|
+
},
|
|
9260
|
+
};
|
|
9261
|
+
}
|
|
9262
|
+
else {
|
|
9263
|
+
if (!payload) {
|
|
9264
|
+
throw new Error('Payload is required for event creation');
|
|
9265
|
+
}
|
|
9266
|
+
return {
|
|
9267
|
+
category,
|
|
9268
|
+
data: {
|
|
9269
|
+
name: payload.name,
|
|
9270
|
+
payload: payload.properties,
|
|
9271
|
+
timestamp,
|
|
9272
|
+
},
|
|
9273
|
+
};
|
|
9274
|
+
}
|
|
9275
|
+
};
|
|
9276
|
+
|
|
9277
|
+
const reservedProps = ['properties', 'token', 'timestamp'];
|
|
9278
|
+
class Events {
|
|
9279
|
+
constructor(constantProperties, getTimestamp, batcher) {
|
|
9280
|
+
this.constantProperties = constantProperties;
|
|
9281
|
+
this.getTimestamp = getTimestamp;
|
|
9282
|
+
this.batcher = batcher;
|
|
9283
|
+
this.ownProperties = {};
|
|
9284
|
+
/**
|
|
9285
|
+
* Add event to batch with option to send it immediately,
|
|
9286
|
+
* properties are optional and will not be saved as super prop
|
|
9287
|
+
* */
|
|
9288
|
+
this.sendEvent = (eventName, properties, options) => {
|
|
9289
|
+
// add properties
|
|
9290
|
+
const eventProps = {};
|
|
9291
|
+
if (properties) {
|
|
9292
|
+
if (!isObject(properties)) {
|
|
9293
|
+
throw new Error('Properties must be an object');
|
|
9294
|
+
}
|
|
9295
|
+
Object.entries(properties).forEach(([key, value]) => {
|
|
9296
|
+
if (!this.constantProperties.defaultPropertyKeys.includes(key)) {
|
|
9297
|
+
eventProps[key] = value;
|
|
9298
|
+
}
|
|
9299
|
+
});
|
|
9300
|
+
}
|
|
9301
|
+
const eventPayload = {
|
|
9302
|
+
name: eventName,
|
|
9303
|
+
properties: { ...this.ownProperties, ...eventProps },
|
|
9304
|
+
};
|
|
9305
|
+
const event = createEvent(categories.events, undefined, this.getTimestamp(), eventPayload);
|
|
9306
|
+
if (options?.send_immediately) {
|
|
9307
|
+
void this.batcher.sendImmediately(event);
|
|
9308
|
+
}
|
|
9309
|
+
else {
|
|
9310
|
+
this.batcher.addEvent(event);
|
|
9311
|
+
}
|
|
9312
|
+
};
|
|
9313
|
+
/**
|
|
9314
|
+
* creates super property for all events
|
|
9315
|
+
* */
|
|
9316
|
+
this.setProperty = (nameOrProperties, value) => {
|
|
9317
|
+
let changed = false;
|
|
9318
|
+
if (isObject(nameOrProperties)) {
|
|
9319
|
+
Object.entries(nameOrProperties).forEach(([key, val]) => {
|
|
9320
|
+
if (!this.constantProperties.defaultPropertyKeys.includes(key)) {
|
|
9321
|
+
this.ownProperties[key] = val;
|
|
9322
|
+
changed = true;
|
|
9323
|
+
}
|
|
9324
|
+
});
|
|
9325
|
+
}
|
|
9326
|
+
if (typeof nameOrProperties === 'string' && value !== undefined) {
|
|
9327
|
+
if (!this.constantProperties.defaultPropertyKeys.includes(nameOrProperties)) {
|
|
9328
|
+
this.ownProperties[nameOrProperties] = value;
|
|
9329
|
+
changed = true;
|
|
9330
|
+
}
|
|
9331
|
+
}
|
|
9332
|
+
if (changed) {
|
|
9333
|
+
this.constantProperties.saveSuperProperties(this.ownProperties);
|
|
9334
|
+
}
|
|
9335
|
+
};
|
|
9336
|
+
/**
|
|
9337
|
+
* set super property only if it doesn't exist yet
|
|
9338
|
+
* */
|
|
9339
|
+
this.setPropertiesOnce = (nameOrProperties, value) => {
|
|
9340
|
+
let changed = false;
|
|
9341
|
+
if (isObject(nameOrProperties)) {
|
|
9342
|
+
Object.entries(nameOrProperties).forEach(([key, val]) => {
|
|
9343
|
+
if (!this.ownProperties[key] && !reservedProps.includes(key)) {
|
|
9344
|
+
this.ownProperties[key] = val;
|
|
9345
|
+
changed = true;
|
|
9346
|
+
}
|
|
9347
|
+
});
|
|
9348
|
+
}
|
|
9349
|
+
if (typeof nameOrProperties === 'string' && value !== undefined) {
|
|
9350
|
+
if (!this.ownProperties[nameOrProperties] && !reservedProps.includes(nameOrProperties)) {
|
|
9351
|
+
this.ownProperties[nameOrProperties] = value;
|
|
9352
|
+
changed = true;
|
|
9353
|
+
}
|
|
9354
|
+
}
|
|
9355
|
+
if (changed) {
|
|
9356
|
+
this.constantProperties.saveSuperProperties(this.ownProperties);
|
|
9357
|
+
}
|
|
9358
|
+
};
|
|
9359
|
+
/**
|
|
9360
|
+
* removes properties from list of super properties
|
|
9361
|
+
* */
|
|
9362
|
+
this.unsetProperties = (properties) => {
|
|
9363
|
+
let changed = false;
|
|
9364
|
+
if (Array.isArray(properties)) {
|
|
9365
|
+
properties.forEach((key) => {
|
|
9366
|
+
if (this.ownProperties[key] && !reservedProps.includes(key)) {
|
|
9367
|
+
delete this.ownProperties[key];
|
|
9368
|
+
changed = true;
|
|
9369
|
+
}
|
|
9370
|
+
});
|
|
9371
|
+
}
|
|
9372
|
+
else if (this.ownProperties[properties] && !reservedProps.includes(properties)) {
|
|
9373
|
+
delete this.ownProperties[properties];
|
|
9374
|
+
changed = true;
|
|
9375
|
+
}
|
|
9376
|
+
if (changed) {
|
|
9377
|
+
this.constantProperties.saveSuperProperties(this.ownProperties);
|
|
9378
|
+
}
|
|
9379
|
+
};
|
|
9380
|
+
/** clears all super properties */
|
|
9381
|
+
this.reset = () => {
|
|
9382
|
+
this.ownProperties = {};
|
|
9383
|
+
this.constantProperties.clearSuperProperties();
|
|
9384
|
+
};
|
|
9385
|
+
/** mixpanel compatibility */
|
|
9386
|
+
this.register = this.setProperty;
|
|
9387
|
+
this.register_once = this.setPropertiesOnce;
|
|
9388
|
+
this.unregister = this.unsetProperties;
|
|
9389
|
+
this.track = this.sendEvent;
|
|
9390
|
+
this.ownProperties = this.constantProperties.getSuperProperties();
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
|
|
9394
|
+
class People {
|
|
9395
|
+
constructor(constantProperties, getTimestamp, onId, batcher) {
|
|
9396
|
+
this.constantProperties = constantProperties;
|
|
9397
|
+
this.getTimestamp = getTimestamp;
|
|
9398
|
+
this.onId = onId;
|
|
9399
|
+
this.batcher = batcher;
|
|
9400
|
+
this.ownProperties = {};
|
|
9401
|
+
this.identify = (user_id, options) => {
|
|
9402
|
+
if (!user_id || typeof user_id !== 'string') {
|
|
9403
|
+
throw new Error('OR SDK: user_id (string) is required for .identify()');
|
|
9404
|
+
}
|
|
9405
|
+
// if user exists already, reset properties
|
|
9406
|
+
if (this.constantProperties.user_id && this.constantProperties.user_id !== user_id) {
|
|
9407
|
+
this.reset();
|
|
9408
|
+
}
|
|
9409
|
+
this.constantProperties.setUserId(user_id);
|
|
9410
|
+
if (!options?.fromTracker) {
|
|
9411
|
+
this.onId(user_id);
|
|
9412
|
+
}
|
|
9413
|
+
const identityEvent = createEvent(categories.people, mutationTypes.identity, this.getTimestamp(), { user_id });
|
|
9414
|
+
this.batcher.addEvent(identityEvent);
|
|
9415
|
+
};
|
|
9416
|
+
/** Resets user id and own properties
|
|
9417
|
+
*
|
|
9418
|
+
* !hard reset will destroy persistent device id!
|
|
9419
|
+
* */
|
|
9420
|
+
this.reset = (hard) => {
|
|
9421
|
+
this.constantProperties.resetUserId(hard);
|
|
9422
|
+
this.ownProperties = {};
|
|
9423
|
+
};
|
|
9424
|
+
/**
|
|
9425
|
+
* Will delete user and its data from backend, then reset all local properties
|
|
9426
|
+
*/
|
|
9427
|
+
this.deleteUser = () => {
|
|
9428
|
+
const removedUser = this.constantProperties.user_id;
|
|
9429
|
+
if (!removedUser)
|
|
9430
|
+
return;
|
|
9431
|
+
this.constantProperties.setUserId(null);
|
|
9432
|
+
this.ownProperties = {};
|
|
9433
|
+
const deleteEvent = createEvent(categories.people, mutationTypes.deleteUser, undefined, {
|
|
9434
|
+
user_id: removedUser,
|
|
9435
|
+
});
|
|
9436
|
+
this.batcher.addEvent(deleteEvent);
|
|
9437
|
+
this.reset();
|
|
9438
|
+
};
|
|
9439
|
+
/**
|
|
9440
|
+
* set user properties, overwriting existing ones
|
|
9441
|
+
* */
|
|
9442
|
+
this.setProperties = (propertyOrObj, value) => {
|
|
9443
|
+
if (!propertyOrObj) {
|
|
9444
|
+
throw new Error('OR SDK: no user properties provided to set');
|
|
9445
|
+
}
|
|
9446
|
+
const properties = {};
|
|
9447
|
+
if (typeof propertyOrObj === 'string' && propertyOrObj && value) {
|
|
9448
|
+
properties[propertyOrObj] = value;
|
|
9449
|
+
}
|
|
9450
|
+
else if (isObject(propertyOrObj)) {
|
|
9451
|
+
Object.assign(properties, propertyOrObj);
|
|
9452
|
+
}
|
|
9453
|
+
else {
|
|
9454
|
+
throw new Error('OR SDK: invalid user properties provided to set');
|
|
9455
|
+
}
|
|
9456
|
+
Object.entries(properties).forEach(([key, value]) => {
|
|
9457
|
+
if (!this.constantProperties.defaultPropertyKeys.includes(key)) {
|
|
9458
|
+
this.ownProperties[key] = value;
|
|
9459
|
+
}
|
|
9460
|
+
});
|
|
9461
|
+
const setEvent = createEvent(categories.people, mutationTypes.setProperty, undefined, {
|
|
9462
|
+
user_id: this.user_id,
|
|
9463
|
+
properties,
|
|
9464
|
+
});
|
|
9465
|
+
this.batcher.addEvent(setEvent);
|
|
9466
|
+
};
|
|
9467
|
+
/**
|
|
9468
|
+
* Set property if it doesn't exist yet
|
|
9469
|
+
* */
|
|
9470
|
+
this.setPropertiesOnce = (properties) => {
|
|
9471
|
+
if (!isObject(properties)) {
|
|
9472
|
+
throw new Error('Properties must be an object');
|
|
9473
|
+
}
|
|
9474
|
+
Object.entries(properties).forEach(([key, value]) => {
|
|
9475
|
+
if (!this.constantProperties.defaultPropertyKeys.includes(key) && !this.ownProperties[key]) {
|
|
9476
|
+
this.ownProperties[key] = value;
|
|
9477
|
+
}
|
|
9478
|
+
});
|
|
9479
|
+
const setEvent = createEvent(categories.people, mutationTypes.setPropertyOnce, undefined, {
|
|
9480
|
+
user_id: this.user_id,
|
|
9481
|
+
properties,
|
|
9482
|
+
});
|
|
9483
|
+
this.batcher.addEvent(setEvent);
|
|
9484
|
+
};
|
|
9485
|
+
/**
|
|
9486
|
+
* Add value to property (will turn string prop into array)
|
|
9487
|
+
* */
|
|
9488
|
+
this.appendValues = (key, value) => {
|
|
9489
|
+
if (!this.constantProperties.defaultPropertyKeys.includes(key) && this.ownProperties[key]) {
|
|
9490
|
+
if (Array.isArray(this.ownProperties[key])) {
|
|
9491
|
+
this.ownProperties[key].push(value);
|
|
9492
|
+
}
|
|
9493
|
+
else {
|
|
9494
|
+
this.ownProperties[key] = [this.ownProperties[key], value];
|
|
9495
|
+
}
|
|
9496
|
+
}
|
|
9497
|
+
const appendEvent = createEvent(categories.people, mutationTypes.appendProperty, undefined, {
|
|
9498
|
+
properties: { [key]: value },
|
|
9499
|
+
user_id: this.user_id,
|
|
9500
|
+
});
|
|
9501
|
+
this.batcher.addEvent(appendEvent);
|
|
9502
|
+
};
|
|
9503
|
+
/**
|
|
9504
|
+
* Add unique values to property (will turn string prop into array)
|
|
9505
|
+
* */
|
|
9506
|
+
this.appendUniqueValues = (key, value) => {
|
|
9507
|
+
if (!this.ownProperties[key])
|
|
9508
|
+
return;
|
|
9509
|
+
if (Array.isArray(this.ownProperties[key])) {
|
|
9510
|
+
if (!this.ownProperties[key].includes(value)) {
|
|
9511
|
+
this.appendValues(key, value);
|
|
9512
|
+
}
|
|
9513
|
+
}
|
|
9514
|
+
else if (this.ownProperties[key] !== value) {
|
|
9515
|
+
this.appendValues(key, value);
|
|
9516
|
+
}
|
|
9517
|
+
const unionEvent = createEvent(categories.people, mutationTypes.appendUniqueProperty, undefined, {
|
|
9518
|
+
properties: { [key]: value },
|
|
9519
|
+
user_id: this.user_id,
|
|
9520
|
+
});
|
|
9521
|
+
this.batcher.addEvent(unionEvent);
|
|
9522
|
+
};
|
|
9523
|
+
/**
|
|
9524
|
+
* Adds value (incl. negative) to existing numerical property
|
|
9525
|
+
* */
|
|
9526
|
+
this.increment = (key, value) => {
|
|
9527
|
+
if (!this.ownProperties[key]) {
|
|
9528
|
+
this.ownProperties[key] = 0;
|
|
9529
|
+
}
|
|
9530
|
+
if (this.ownProperties[key] && typeof this.ownProperties[key] !== 'number') {
|
|
9531
|
+
throw new Error('OR SDK: Property must be a number to increment');
|
|
9532
|
+
}
|
|
9533
|
+
// @ts-ignore
|
|
9534
|
+
this.ownProperties[key] += value;
|
|
9535
|
+
const incrementEvent = createEvent(categories.people, mutationTypes.incrementProperty, undefined, {
|
|
9536
|
+
user_id: this.user_id,
|
|
9537
|
+
properties: { [key]: value },
|
|
9538
|
+
});
|
|
9539
|
+
this.batcher.addEvent(incrementEvent);
|
|
9540
|
+
};
|
|
9541
|
+
/** mixpanel compatibility */
|
|
9542
|
+
this.union = this.appendUniqueValues;
|
|
9543
|
+
this.set = this.setProperties;
|
|
9544
|
+
this.set_once = this.setPropertiesOnce;
|
|
9545
|
+
this.append = this.appendValues;
|
|
9546
|
+
this.incrementBy = this.increment;
|
|
9547
|
+
}
|
|
9548
|
+
get user_id() {
|
|
9549
|
+
return this.constantProperties.user_id;
|
|
9550
|
+
}
|
|
9551
|
+
}
|
|
9552
|
+
|
|
9553
|
+
/**
|
|
9554
|
+
* Creates batches of events, then sends them at intervals.
|
|
9555
|
+
*/
|
|
9556
|
+
class Batcher {
|
|
9557
|
+
constructor(backendUrl, getToken, init) {
|
|
9558
|
+
this.backendUrl = backendUrl;
|
|
9559
|
+
this.getToken = getToken;
|
|
9560
|
+
this.init = init;
|
|
9561
|
+
this.autosendInterval = 5 * 1000;
|
|
9562
|
+
this.retryTimeout = 3 * 1000;
|
|
9563
|
+
this.retryLimit = 3;
|
|
9564
|
+
this.apiEdp = '/v1/sdk/i';
|
|
9565
|
+
this.batch = {
|
|
9566
|
+
[categories.people]: [],
|
|
9567
|
+
[categories.events]: [],
|
|
9568
|
+
};
|
|
9569
|
+
this.intervalId = null;
|
|
9570
|
+
}
|
|
9571
|
+
getBatches() {
|
|
9572
|
+
this.batch[categories.people] = this.dedupePeopleEvents();
|
|
9573
|
+
const finalData = { data: this.batch };
|
|
9574
|
+
return finalData;
|
|
9575
|
+
}
|
|
9576
|
+
addEvent(event) {
|
|
9577
|
+
this.batch[event.category].push(event.data);
|
|
9578
|
+
}
|
|
9579
|
+
sendImmediately(event) {
|
|
9580
|
+
this.sendBatch({ [event.category]: [event.data] });
|
|
9581
|
+
}
|
|
9582
|
+
/**
|
|
9583
|
+
*
|
|
9584
|
+
* Essentially we're dividing the batch by identify events and squash all same category events into one in each part,
|
|
9585
|
+
* taking priority to the last one
|
|
9586
|
+
*/
|
|
9587
|
+
dedupePeopleEvents() {
|
|
9588
|
+
const peopleEvents = this.batch[categories.people];
|
|
9589
|
+
const finalEvents = [];
|
|
9590
|
+
const currentPart = [];
|
|
9591
|
+
for (let event of peopleEvents) {
|
|
9592
|
+
if (event.type === 'identity') {
|
|
9593
|
+
if (currentPart.length > 0) {
|
|
9594
|
+
finalEvents.push(...this.squashPeopleEvents(currentPart), event);
|
|
9595
|
+
currentPart.length = 0;
|
|
9596
|
+
}
|
|
9597
|
+
else {
|
|
9598
|
+
finalEvents.push(event);
|
|
9599
|
+
}
|
|
9600
|
+
}
|
|
9601
|
+
else {
|
|
9602
|
+
currentPart.push(event);
|
|
9603
|
+
}
|
|
9604
|
+
}
|
|
9605
|
+
if (currentPart.length > 0) {
|
|
9606
|
+
finalEvents.push(...this.squashPeopleEvents(currentPart));
|
|
9607
|
+
}
|
|
9608
|
+
return finalEvents;
|
|
9609
|
+
}
|
|
9610
|
+
squashPeopleEvents(events) {
|
|
9611
|
+
if (!events || events.length === 0) {
|
|
9612
|
+
return [];
|
|
9613
|
+
}
|
|
9614
|
+
const uniqueEventsByType = new Map();
|
|
9615
|
+
for (let event of events) {
|
|
9616
|
+
const prev = uniqueEventsByType.get(event.type);
|
|
9617
|
+
if (prev) {
|
|
9618
|
+
if (event.type === 'increment_property') {
|
|
9619
|
+
const previousValues = Object.entries(prev.payload);
|
|
9620
|
+
const currentValues = Object.entries(event.payload);
|
|
9621
|
+
const uniqueKeys = new Set([...previousValues.map(([key]) => key), ...currentValues.map(([key]) => key)]);
|
|
9622
|
+
const mergedPayload = {};
|
|
9623
|
+
uniqueKeys.forEach((key) => {
|
|
9624
|
+
const prevValue = typeof prev.payload[key] === 'number' ? prev.payload[key] : 0;
|
|
9625
|
+
const currValue = typeof event.payload[key] === 'number' ? event.payload[key] : 0;
|
|
9626
|
+
mergedPayload[key] = prevValue + currValue;
|
|
9627
|
+
});
|
|
9628
|
+
uniqueEventsByType.set(event.type, {
|
|
9629
|
+
type: event.type,
|
|
9630
|
+
timestamp: event.timestamp,
|
|
9631
|
+
payload: mergedPayload,
|
|
9632
|
+
});
|
|
9633
|
+
continue;
|
|
9634
|
+
}
|
|
9635
|
+
// merge payloads, taking priority to the latest one
|
|
9636
|
+
uniqueEventsByType.set(event.type, {
|
|
9637
|
+
type: event.type,
|
|
9638
|
+
timestamp: event.timestamp,
|
|
9639
|
+
payload: { ...(prev.payload ?? {}), ...(event.payload ?? {}) },
|
|
9640
|
+
});
|
|
9641
|
+
}
|
|
9642
|
+
else {
|
|
9643
|
+
uniqueEventsByType.set(event.type, event);
|
|
9644
|
+
}
|
|
9645
|
+
}
|
|
9646
|
+
return Array.from(uniqueEventsByType.values());
|
|
9647
|
+
}
|
|
9648
|
+
sendBatch(batch) {
|
|
9649
|
+
const sentBatch = batch;
|
|
9650
|
+
let attempts = 0;
|
|
9651
|
+
const send = () => {
|
|
9652
|
+
const token = this.getToken();
|
|
9653
|
+
if (!token) {
|
|
9654
|
+
return;
|
|
9655
|
+
}
|
|
9656
|
+
attempts++;
|
|
9657
|
+
return fetch(`${this.backendUrl}${this.apiEdp}`, {
|
|
9658
|
+
method: 'POST',
|
|
9659
|
+
headers: {
|
|
9660
|
+
'Content-Type': 'application/json',
|
|
9661
|
+
Authorization: `Bearer ${token}`,
|
|
9662
|
+
},
|
|
9663
|
+
body: JSON.stringify(sentBatch),
|
|
9664
|
+
})
|
|
9665
|
+
.then((response) => {
|
|
9666
|
+
if (response.status === 403) {
|
|
9667
|
+
this.init().then(() => {
|
|
9668
|
+
send();
|
|
9669
|
+
});
|
|
9670
|
+
}
|
|
9671
|
+
if (!response.ok) {
|
|
9672
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
9673
|
+
}
|
|
9674
|
+
})
|
|
9675
|
+
.catch(() => {
|
|
9676
|
+
if (attempts < this.retryLimit) {
|
|
9677
|
+
setTimeout(() => void send(), this.retryTimeout);
|
|
9678
|
+
}
|
|
9679
|
+
});
|
|
9680
|
+
};
|
|
9681
|
+
void send();
|
|
9682
|
+
}
|
|
9683
|
+
startAutosend() {
|
|
9684
|
+
this.intervalId = setInterval(() => {
|
|
9685
|
+
this.flush();
|
|
9686
|
+
}, this.autosendInterval);
|
|
9687
|
+
}
|
|
9688
|
+
flush() {
|
|
9689
|
+
const categories = Object.keys(this.batch);
|
|
9690
|
+
const isEmpty = categories.every((category) => this.batch[category].length === 0);
|
|
9691
|
+
if (isEmpty) {
|
|
9692
|
+
return;
|
|
9693
|
+
}
|
|
9694
|
+
this.sendBatch(this.getBatches());
|
|
9695
|
+
categories.forEach((key) => {
|
|
9696
|
+
this.batch[key] = [];
|
|
9697
|
+
});
|
|
9698
|
+
}
|
|
9699
|
+
stop() {
|
|
9700
|
+
this.flush();
|
|
9701
|
+
if (this.intervalId) {
|
|
9702
|
+
clearInterval(this.intervalId);
|
|
9703
|
+
this.intervalId = null;
|
|
9704
|
+
}
|
|
9705
|
+
}
|
|
9706
|
+
}
|
|
9707
|
+
|
|
9708
|
+
const STORAGEKEY = '__or_sdk_analytics_token';
|
|
9709
|
+
class Analytics {
|
|
9710
|
+
/**
|
|
9711
|
+
* @param localStorage Class or Object that implements Storage-like interface that stores
|
|
9712
|
+
* values persistently like window.localStorage or any other file-based storage
|
|
9713
|
+
*
|
|
9714
|
+
* @param sessionStorage Class or Object that implements Storage-like interface that stores values
|
|
9715
|
+
* on per-session basis like window.sessionStorage or any other in-memory storage
|
|
9716
|
+
*
|
|
9717
|
+
* @param getToken Function that returns token to bind events to a session
|
|
9718
|
+
*
|
|
9719
|
+
* @param getTimestamp returns current timestamp
|
|
9720
|
+
*
|
|
9721
|
+
* @param setUserId callback for people.identify
|
|
9722
|
+
*
|
|
9723
|
+
* @param standalone if true, analytics will manage its own token (instead of using with openreplay tracker session)
|
|
9724
|
+
* */
|
|
9725
|
+
constructor(options) {
|
|
9726
|
+
this.token = null;
|
|
9727
|
+
this.standalone = false;
|
|
9728
|
+
this._getToken = () => {
|
|
9729
|
+
if (this.standalone) {
|
|
9730
|
+
return this.token;
|
|
9731
|
+
}
|
|
9732
|
+
return this.getToken();
|
|
9733
|
+
};
|
|
9734
|
+
this._getTimestamp = () => {
|
|
9735
|
+
if (this.standalone) {
|
|
9736
|
+
return Date.now();
|
|
9737
|
+
}
|
|
9738
|
+
return this.getTimestamp();
|
|
9739
|
+
};
|
|
9740
|
+
this.init = async () => {
|
|
9741
|
+
if (!this.standalone) {
|
|
9742
|
+
this.batcher.startAutosend();
|
|
9743
|
+
return;
|
|
9744
|
+
}
|
|
9745
|
+
else {
|
|
9746
|
+
const defaultFields = this.constantProperties.all;
|
|
9747
|
+
const apiEdp = '/v1/sdk/start';
|
|
9748
|
+
const data = {
|
|
9749
|
+
projectKey: this.projectKey,
|
|
9750
|
+
defaultFields,
|
|
9751
|
+
};
|
|
9752
|
+
const resp = await fetch(apiEdp, {
|
|
9753
|
+
method: 'POST',
|
|
9754
|
+
body: JSON.stringify(data),
|
|
9755
|
+
});
|
|
9756
|
+
if (!resp.ok) {
|
|
9757
|
+
throw new Error(`HTTP error! status: ${resp.status}`);
|
|
9758
|
+
}
|
|
9759
|
+
const result = await resp.json();
|
|
9760
|
+
if (result.token) {
|
|
9761
|
+
this.token = result.token;
|
|
9762
|
+
this.sessionStorage.setItem(STORAGEKEY, result.token);
|
|
9763
|
+
}
|
|
9764
|
+
else {
|
|
9765
|
+
throw new Error('No token received from server');
|
|
9766
|
+
}
|
|
9767
|
+
}
|
|
9768
|
+
};
|
|
9769
|
+
this.reset = () => {
|
|
9770
|
+
this.people.reset(true);
|
|
9771
|
+
this.events.reset();
|
|
9772
|
+
this.batcher.stop();
|
|
9773
|
+
if (this.standalone) {
|
|
9774
|
+
this.token = null;
|
|
9775
|
+
this.sessionStorage.setItem(STORAGEKEY, '');
|
|
9776
|
+
}
|
|
9777
|
+
};
|
|
9778
|
+
/**
|
|
9779
|
+
* COMPATIBILITY LAYER
|
|
9780
|
+
* */
|
|
9781
|
+
/**
|
|
9782
|
+
* Identify a user with an id (e.g. email, username, etc.)
|
|
9783
|
+
* will bind all events and properties (including device_id) to this user
|
|
9784
|
+
*
|
|
9785
|
+
* you will need to manually call people.reset() to clear the id on logout event
|
|
9786
|
+
* */
|
|
9787
|
+
this.identify = (user_id) => {
|
|
9788
|
+
return this.people.identify(user_id);
|
|
9789
|
+
};
|
|
9790
|
+
/**
|
|
9791
|
+
* Add event to batch with option to send it immediately,
|
|
9792
|
+
* properties are optional and will not be saved as super prop
|
|
9793
|
+
* */
|
|
9794
|
+
this.track = (eventName, properties, options) => {
|
|
9795
|
+
return this.events.track(eventName, properties, options);
|
|
9796
|
+
};
|
|
9797
|
+
this.sessionStorage = options.sessionStorage || sessionStorage;
|
|
9798
|
+
this.localStorage = options.localStorage || localStorage;
|
|
9799
|
+
this.backendUrl = options.ingestPoint;
|
|
9800
|
+
this.projectKey = options.projectKey;
|
|
9801
|
+
this.getToken = options.getToken || (() => '');
|
|
9802
|
+
this.getTimestamp = options.getTimestamp || (() => Date.now());
|
|
9803
|
+
this.setUserId = options.setUserId || (() => { });
|
|
9804
|
+
this.standalone = !options.notStandalone;
|
|
9805
|
+
this.token = this.sessionStorage.getItem(STORAGEKEY);
|
|
9806
|
+
this.constantProperties = new ConstantProperties(this.localStorage, this.sessionStorage);
|
|
9807
|
+
this.batcher = new Batcher(this.backendUrl, this._getToken, this.init);
|
|
9808
|
+
this.events = new Events(this.constantProperties, this._getTimestamp, this.batcher);
|
|
9809
|
+
this.people = new People(this.constantProperties, this._getTimestamp, this.setUserId, this.batcher);
|
|
9810
|
+
if (options.notStandalone) {
|
|
9811
|
+
this.init();
|
|
9812
|
+
}
|
|
9813
|
+
}
|
|
9814
|
+
}
|
|
9815
|
+
|
|
8831
9816
|
const Messages = _Messages;
|
|
8832
9817
|
const DOCS_SETUP = '/en/sdk';
|
|
8833
9818
|
function processOptions(obj) {
|
|
@@ -8869,6 +9854,7 @@ class API {
|
|
|
8869
9854
|
constructor(options) {
|
|
8870
9855
|
this.options = options;
|
|
8871
9856
|
this.app = null;
|
|
9857
|
+
this.analytics = null;
|
|
8872
9858
|
this.crossdomainMode = false;
|
|
8873
9859
|
this.checkDoNotTrack = () => {
|
|
8874
9860
|
return (this.options.respectDoNotTrack &&
|
|
@@ -8879,7 +9865,7 @@ class API {
|
|
|
8879
9865
|
this.signalStartIssue = (reason, missingApi) => {
|
|
8880
9866
|
const doNotTrack = this.checkDoNotTrack();
|
|
8881
9867
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
8882
|
-
trackerVersion: '17.
|
|
9868
|
+
trackerVersion: '17.1.0',
|
|
8883
9869
|
projectKey: this.options.projectKey,
|
|
8884
9870
|
doNotTrack,
|
|
8885
9871
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|
|
@@ -8891,6 +9877,22 @@ class API {
|
|
|
8891
9877
|
}
|
|
8892
9878
|
this.app.restartCanvasTracking();
|
|
8893
9879
|
};
|
|
9880
|
+
this.getSessionURL = (options) => {
|
|
9881
|
+
if (this.app === null) {
|
|
9882
|
+
return undefined;
|
|
9883
|
+
}
|
|
9884
|
+
return this.app.getSessionURL(options);
|
|
9885
|
+
};
|
|
9886
|
+
this.setUserID = (id) => {
|
|
9887
|
+
if (typeof id === 'string' && this.app !== null) {
|
|
9888
|
+
this.app.session.setUserID(id);
|
|
9889
|
+
this.analytics?.people.identify(id, { fromTracker: true });
|
|
9890
|
+
}
|
|
9891
|
+
};
|
|
9892
|
+
this.userID = (id) => {
|
|
9893
|
+
deprecationWarn("'userID' method", "'setUserID' method", '/');
|
|
9894
|
+
this.setUserID(id);
|
|
9895
|
+
};
|
|
8894
9896
|
this.handleError = (e, metadata = {}) => {
|
|
8895
9897
|
if (this.app === null) {
|
|
8896
9898
|
return;
|
|
@@ -8913,6 +9915,21 @@ class API {
|
|
|
8913
9915
|
}
|
|
8914
9916
|
this.app.send(Incident(options.label ?? '', options.startTime, options.endTime ?? options.startTime));
|
|
8915
9917
|
};
|
|
9918
|
+
this.analyticsToken = null;
|
|
9919
|
+
/**
|
|
9920
|
+
* Use custom token for analytics events without session recording
|
|
9921
|
+
* */
|
|
9922
|
+
this.setAnalyticsToken = (token) => {
|
|
9923
|
+
this.analyticsToken = token;
|
|
9924
|
+
};
|
|
9925
|
+
this.getAnalyticsToken = () => {
|
|
9926
|
+
if (this.analyticsToken) {
|
|
9927
|
+
return this.analyticsToken;
|
|
9928
|
+
}
|
|
9929
|
+
else {
|
|
9930
|
+
return this.app?.session.getSessionToken() ?? '';
|
|
9931
|
+
}
|
|
9932
|
+
};
|
|
8916
9933
|
this.crossdomainMode = Boolean(inIframe() && options.crossdomain?.enabled);
|
|
8917
9934
|
if (!IN_BROWSER || !processOptions(options)) {
|
|
8918
9935
|
return;
|
|
@@ -8971,6 +9988,24 @@ class API {
|
|
|
8971
9988
|
}
|
|
8972
9989
|
const app = new App(options.projectKey, options.sessionToken, options, this.signalStartIssue, this.crossdomainMode);
|
|
8973
9990
|
this.app = app;
|
|
9991
|
+
if (options.projectKey && options.analytics?.active) {
|
|
9992
|
+
const isSaas = !options.ingestPoint || options.ingestPoint.includes('api.openreplay.com');
|
|
9993
|
+
const defaultEdp = 'https://api.openreplay.com/ingest';
|
|
9994
|
+
this.analytics = new Analytics({
|
|
9995
|
+
localStorage: options.localStorage ?? localStorage,
|
|
9996
|
+
sessionStorage: options.sessionStorage ?? sessionStorage,
|
|
9997
|
+
getToken: () => this.getAnalyticsToken(),
|
|
9998
|
+
getTimestamp: () => this.app?.timestamp() ?? Date.now(),
|
|
9999
|
+
setUserId: (id) => {
|
|
10000
|
+
this.app?.session.setUserID(id);
|
|
10001
|
+
},
|
|
10002
|
+
notStandalone: true,
|
|
10003
|
+
ingestPoint: isSaas
|
|
10004
|
+
? defaultEdp
|
|
10005
|
+
: (options.analytics?.ingestPoint ?? options.ingestPoint ?? defaultEdp),
|
|
10006
|
+
projectKey: options.projectKey,
|
|
10007
|
+
});
|
|
10008
|
+
}
|
|
8974
10009
|
if (!this.crossdomainMode) {
|
|
8975
10010
|
// no need to send iframe viewport data since its a node for us
|
|
8976
10011
|
Viewport(app, options.urls);
|
|
@@ -9050,6 +10085,9 @@ class API {
|
|
|
9050
10085
|
if (this.app === null) {
|
|
9051
10086
|
return Promise.reject("Browser doesn't support required api, or doNotTrack is active.");
|
|
9052
10087
|
}
|
|
10088
|
+
if (startOpts?.userID) {
|
|
10089
|
+
this.analytics?.people.identify(startOpts.userID, { fromTracker: true });
|
|
10090
|
+
}
|
|
9053
10091
|
return this.app.start(startOpts);
|
|
9054
10092
|
}
|
|
9055
10093
|
else {
|
|
@@ -9157,21 +10195,6 @@ class API {
|
|
|
9157
10195
|
deprecationWarn("'sessionID' method", "'getSessionID' method", '/');
|
|
9158
10196
|
return this.getSessionID();
|
|
9159
10197
|
}
|
|
9160
|
-
getSessionURL(options) {
|
|
9161
|
-
if (this.app === null) {
|
|
9162
|
-
return undefined;
|
|
9163
|
-
}
|
|
9164
|
-
return this.app.getSessionURL(options);
|
|
9165
|
-
}
|
|
9166
|
-
setUserID(id) {
|
|
9167
|
-
if (typeof id === 'string' && this.app !== null) {
|
|
9168
|
-
this.app.session.setUserID(id);
|
|
9169
|
-
}
|
|
9170
|
-
}
|
|
9171
|
-
userID(id) {
|
|
9172
|
-
deprecationWarn("'userID' method", "'setUserID' method", '/');
|
|
9173
|
-
this.setUserID(id);
|
|
9174
|
-
}
|
|
9175
10198
|
setUserAnonymousID(id) {
|
|
9176
10199
|
if (typeof id === 'string' && this.app !== null) {
|
|
9177
10200
|
this.app.send(UserAnonymousID(id));
|
|
@@ -9458,8 +10481,10 @@ class TrackerSingleton {
|
|
|
9458
10481
|
}
|
|
9459
10482
|
const tracker = new TrackerSingleton();
|
|
9460
10483
|
|
|
10484
|
+
exports.Analytics = Analytics;
|
|
9461
10485
|
exports.App = App;
|
|
9462
10486
|
exports.Messages = Messages;
|
|
9463
10487
|
exports.default = API;
|
|
10488
|
+
exports.openReplay = tracker;
|
|
9464
10489
|
exports.tracker = tracker;
|
|
9465
10490
|
//# sourceMappingURL=entry.js.map
|