@journium/js 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AutocaptureTracker.d.ts +2 -0
- package/dist/AutocaptureTracker.d.ts.map +1 -1
- package/dist/JourniumAnalytics.d.ts +15 -0
- package/dist/JourniumAnalytics.d.ts.map +1 -1
- package/dist/PageviewTracker.d.ts +5 -2
- package/dist/PageviewTracker.d.ts.map +1 -1
- package/dist/index.cjs +145 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +22 -3
- package/dist/index.mjs +145 -42
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +145 -42
- package/dist/index.umd.js.map +1 -1
- package/dist/journium.js +145 -42
- package/dist/journium.js.map +1 -1
- package/dist/journium.min.js +1 -1
- package/dist/journium.min.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -27,6 +27,8 @@ export declare class AutocaptureTracker {
|
|
|
27
27
|
private getElementType;
|
|
28
28
|
private getElementText;
|
|
29
29
|
private getElementsChain;
|
|
30
|
+
private extractSemanticClasses;
|
|
31
|
+
private isHashLike;
|
|
30
32
|
private isSafeInputType;
|
|
31
33
|
}
|
|
32
34
|
//# sourceMappingURL=AutocaptureTracker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocaptureTracker.d.ts","sourceRoot":"","sources":["../src/AutocaptureTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAa,kBAAkB,
|
|
1
|
+
{"version":3,"file":"AutocaptureTracker.d.ts","sourceRoot":"","sources":["../src/AutocaptureTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAa,kBAAkB,EAA6B,MAAM,gBAAgB,CAAC;AAE1F;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,kBAAuB;IAgBpE;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IA4BhD,KAAK,IAAI,IAAI;IAwBb,IAAI,IAAI,IAAI;IAcZ,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,qBAAqB;IAgB7B,OAAO,CAAC,qBAAqB;IAgB7B,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,oBAAoB;IAoG5B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,gBAAgB;IAqFxB,OAAO,CAAC,sBAAsB;IA0B9B,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,eAAe;CAKxB"}
|
|
@@ -7,12 +7,23 @@ export declare class JourniumAnalytics {
|
|
|
7
7
|
private autocaptureStarted;
|
|
8
8
|
private unsubscribeOptionsChange?;
|
|
9
9
|
constructor(config: JourniumConfig);
|
|
10
|
+
private resolvePageviewOptions;
|
|
10
11
|
private resolveAutocaptureOptions;
|
|
12
|
+
/** Track a custom event with optional properties. */
|
|
11
13
|
track(event: string, properties?: Record<string, unknown>): void;
|
|
14
|
+
/** Associate the current session with a known user identity and optional attributes. */
|
|
12
15
|
identify(distinctId: string, attributes?: Record<string, unknown>): void;
|
|
16
|
+
/** Clear the current identity, starting a new anonymous session. */
|
|
13
17
|
reset(): void;
|
|
18
|
+
/** Manually capture a $pageview event with optional custom properties. */
|
|
14
19
|
capturePageview(properties?: Record<string, unknown>): void;
|
|
20
|
+
/**
|
|
21
|
+
* Manually start autocapture (pageview tracking + DOM event capture).
|
|
22
|
+
* Under normal usage this is not needed — the SDK starts automatically on init.
|
|
23
|
+
* Useful only if autocapture was explicitly stopped and needs to be restarted.
|
|
24
|
+
*/
|
|
15
25
|
startAutocapture(): void;
|
|
26
|
+
/** Stop autocapture — pauses pageview tracking and DOM event capture. */
|
|
16
27
|
stopAutocapture(): void;
|
|
17
28
|
/**
|
|
18
29
|
* Automatically start autocapture if enabled in options
|
|
@@ -23,14 +34,18 @@ export declare class JourniumAnalytics {
|
|
|
23
34
|
* Handle effective options change (e.g., when remote options are fetched)
|
|
24
35
|
*/
|
|
25
36
|
private handleOptionsChange;
|
|
37
|
+
/** Flush all queued events to the ingestion endpoint immediately. */
|
|
26
38
|
flush(): Promise<void>;
|
|
39
|
+
/** Return the currently active options (merged local + remote config). */
|
|
27
40
|
getEffectiveOptions(): JourniumLocalOptions;
|
|
28
41
|
/**
|
|
29
42
|
* Register a callback to be notified when effective options change
|
|
30
43
|
*/
|
|
31
44
|
onOptionsChange(callback: (options: JourniumLocalOptions) => void): () => void;
|
|
45
|
+
/** Tear down the analytics instance: stop all tracking, flush pending events, and release resources. */
|
|
32
46
|
destroy(): void;
|
|
33
47
|
}
|
|
48
|
+
/** Create and return a new JourniumAnalytics instance for the given config. */
|
|
34
49
|
export declare const init: (config: JourniumConfig) => JourniumAnalytics;
|
|
35
50
|
declare const _default: {
|
|
36
51
|
init: (config: JourniumConfig) => JourniumAnalytics;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JourniumAnalytics.d.ts","sourceRoot":"","sources":["../src/JourniumAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"JourniumAnalytics.d.ts","sourceRoot":"","sources":["../src/JourniumAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiD,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMrH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,kBAAkB,CAAkB;IAC5C,OAAO,CAAC,wBAAwB,CAAC,CAAa;gBAElC,MAAM,EAAE,cAAc;IAqBlC,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,yBAAyB;IAiBjC,qDAAqD;IACrD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhE,wFAAwF;IACxF,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxE,oEAAoE;IACpE,KAAK,IAAI,IAAI;IAIb,0EAA0E;IAC1E,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D;;;;OAIG;IACH,gBAAgB,IAAI,IAAI;IA6BxB,yEAAyE;IACzE,eAAe,IAAI,IAAI;IAMvB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAoCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,qEAAqE;IAC/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,0EAA0E;IAC1E,mBAAmB;IAInB;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAI9E,wGAAwG;IACxG,OAAO,IAAI,IAAI;CAQhB;AAED,+EAA+E;AAC/E,eAAO,MAAM,IAAI,GAAI,QAAQ,cAAc,KAAG,iBAS7C,CAAC;;mBAT2B,cAAc,KAAG,iBAAiB;;AAW/D,wBAAwB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PageviewProperties } from '@journium/core';
|
|
1
2
|
import { JourniumClient } from './JourniumClient';
|
|
2
3
|
export declare class PageviewTracker {
|
|
3
4
|
private client;
|
|
@@ -6,13 +7,15 @@ export declare class PageviewTracker {
|
|
|
6
7
|
private originalReplaceState;
|
|
7
8
|
private popStateHandler;
|
|
8
9
|
constructor(client: JourniumClient);
|
|
9
|
-
capturePageview(customProperties?:
|
|
10
|
+
capturePageview(customProperties?: PageviewProperties): void;
|
|
10
11
|
/**
|
|
11
12
|
* Start automatic autocapture for pageviews
|
|
12
13
|
* @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
|
|
13
14
|
* Pass false when restarting after a remote options update to avoid a spurious pageview.
|
|
15
|
+
* @param patchHistory - whether to monkey-patch pushState/replaceState/popstate (default: true).
|
|
16
|
+
* Pass false when a framework-native router tracker (e.g. Next.js) owns SPA pageviews.
|
|
14
17
|
*/
|
|
15
|
-
startAutoPageviewTracking(captureInitialPageview?: boolean): void;
|
|
18
|
+
startAutoPageviewTracking(captureInitialPageview?: boolean, patchHistory?: boolean): void;
|
|
16
19
|
/**
|
|
17
20
|
* Stop automatic autocapture for pageviews
|
|
18
21
|
* @returns void
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageviewTracker.d.ts","sourceRoot":"","sources":["../src/PageviewTracker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PageviewTracker.d.ts","sourceRoot":"","sources":["../src/PageviewTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA4C,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,iBAAiB,CAAgD;IACzE,OAAO,CAAC,oBAAoB,CAAmD;IAC/E,OAAO,CAAC,eAAe,CAA6B;gBAExC,MAAM,EAAE,cAAc;IAIlC,eAAe,CAAC,gBAAgB,GAAE,kBAAuB,GAAG,IAAI;IAkBhE;;;;;;OAMG;IACH,yBAAyB,CAAC,sBAAsB,GAAE,OAAc,EAAE,YAAY,GAAE,OAAc,GAAG,IAAI;IA8BrG;;;OAGG;IACH,eAAe,IAAI,IAAI;CAmBxB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// @journium/js@1.3.0 is replaced at build time by @rollup/plugin-replace
|
|
4
|
+
const SDK_VERSION = '@journium/js@1.3.0';
|
|
5
|
+
|
|
3
6
|
/**
|
|
4
7
|
* uuidv7: A JavaScript implementation of UUID version 7
|
|
5
8
|
*
|
|
@@ -940,6 +943,7 @@ class JourniumClient {
|
|
|
940
943
|
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
941
944
|
}
|
|
942
945
|
buildIdentityProperties(userProperties = {}) {
|
|
946
|
+
var _a, _b;
|
|
943
947
|
const identity = this.identityManager.getIdentity();
|
|
944
948
|
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
945
949
|
return {
|
|
@@ -950,7 +954,7 @@ class JourniumClient {
|
|
|
950
954
|
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
951
955
|
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
952
956
|
...userAgentInfo,
|
|
953
|
-
$
|
|
957
|
+
$sdk_version: (_b = (_a = this.config.options) === null || _a === void 0 ? void 0 : _a._sdkVersion) !== null && _b !== void 0 ? _b : 'unknown',
|
|
954
958
|
$platform: 'web',
|
|
955
959
|
...userProperties,
|
|
956
960
|
};
|
|
@@ -1091,7 +1095,7 @@ class PageviewTracker {
|
|
|
1091
1095
|
$host: url.host,
|
|
1092
1096
|
$pathname: url.pathname,
|
|
1093
1097
|
$search: url.search,
|
|
1094
|
-
$
|
|
1098
|
+
$page_title: getPageTitle(),
|
|
1095
1099
|
$referrer: getReferrer(),
|
|
1096
1100
|
...customProperties,
|
|
1097
1101
|
};
|
|
@@ -1102,28 +1106,31 @@ class PageviewTracker {
|
|
|
1102
1106
|
* Start automatic autocapture for pageviews
|
|
1103
1107
|
* @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
|
|
1104
1108
|
* Pass false when restarting after a remote options update to avoid a spurious pageview.
|
|
1109
|
+
* @param patchHistory - whether to monkey-patch pushState/replaceState/popstate (default: true).
|
|
1110
|
+
* Pass false when a framework-native router tracker (e.g. Next.js) owns SPA pageviews.
|
|
1105
1111
|
*/
|
|
1106
|
-
startAutoPageviewTracking(captureInitialPageview = true) {
|
|
1112
|
+
startAutoPageviewTracking(captureInitialPageview = true, patchHistory = true) {
|
|
1107
1113
|
if (captureInitialPageview) {
|
|
1108
1114
|
this.capturePageview();
|
|
1109
1115
|
}
|
|
1110
|
-
if (typeof window
|
|
1111
|
-
|
|
1112
|
-
this.originalPushState = window.history.pushState;
|
|
1113
|
-
this.originalReplaceState = window.history.replaceState;
|
|
1114
|
-
window.history.pushState = (...args) => {
|
|
1115
|
-
this.originalPushState.apply(window.history, args);
|
|
1116
|
-
setTimeout(() => this.capturePageview(), 0);
|
|
1117
|
-
};
|
|
1118
|
-
window.history.replaceState = (...args) => {
|
|
1119
|
-
this.originalReplaceState.apply(window.history, args);
|
|
1120
|
-
setTimeout(() => this.capturePageview(), 0);
|
|
1121
|
-
};
|
|
1122
|
-
this.popStateHandler = () => {
|
|
1123
|
-
setTimeout(() => this.capturePageview(), 0);
|
|
1124
|
-
};
|
|
1125
|
-
window.addEventListener('popstate', this.popStateHandler);
|
|
1116
|
+
if (!patchHistory || typeof window === 'undefined') {
|
|
1117
|
+
return;
|
|
1126
1118
|
}
|
|
1119
|
+
// Store original methods for cleanup
|
|
1120
|
+
this.originalPushState = window.history.pushState;
|
|
1121
|
+
this.originalReplaceState = window.history.replaceState;
|
|
1122
|
+
window.history.pushState = (...args) => {
|
|
1123
|
+
this.originalPushState.apply(window.history, args);
|
|
1124
|
+
setTimeout(() => this.capturePageview(), 0);
|
|
1125
|
+
};
|
|
1126
|
+
window.history.replaceState = (...args) => {
|
|
1127
|
+
this.originalReplaceState.apply(window.history, args);
|
|
1128
|
+
setTimeout(() => this.capturePageview(), 0);
|
|
1129
|
+
};
|
|
1130
|
+
this.popStateHandler = () => {
|
|
1131
|
+
setTimeout(() => this.capturePageview(), 0);
|
|
1132
|
+
};
|
|
1133
|
+
window.addEventListener('popstate', this.popStateHandler);
|
|
1127
1134
|
}
|
|
1128
1135
|
/**
|
|
1129
1136
|
* Stop automatic autocapture for pageviews
|
|
@@ -1164,6 +1171,8 @@ class AutocaptureTracker {
|
|
|
1164
1171
|
ignoreClasses: ['journium-ignore'],
|
|
1165
1172
|
ignoreElements: ['script', 'style', 'noscript'],
|
|
1166
1173
|
captureContentText: true,
|
|
1174
|
+
dataAttributePrefixes: ['jrnm-'],
|
|
1175
|
+
dataAttributeNames: ['data-testid', 'data-track'],
|
|
1167
1176
|
...options,
|
|
1168
1177
|
};
|
|
1169
1178
|
}
|
|
@@ -1185,6 +1194,8 @@ class AutocaptureTracker {
|
|
|
1185
1194
|
ignoreClasses: ['journium-ignore'],
|
|
1186
1195
|
ignoreElements: ['script', 'style', 'noscript'],
|
|
1187
1196
|
captureContentText: true,
|
|
1197
|
+
dataAttributePrefixes: ['jrnm-'],
|
|
1198
|
+
dataAttributeNames: ['data-testid', 'data-track'],
|
|
1188
1199
|
...options,
|
|
1189
1200
|
};
|
|
1190
1201
|
// Restart if it was active before
|
|
@@ -1227,10 +1238,7 @@ class AutocaptureTracker {
|
|
|
1227
1238
|
return;
|
|
1228
1239
|
}
|
|
1229
1240
|
const properties = this.getElementProperties(target, 'click');
|
|
1230
|
-
this.client.track('$autocapture',
|
|
1231
|
-
$event_type: 'click',
|
|
1232
|
-
...properties,
|
|
1233
|
-
});
|
|
1241
|
+
this.client.track('$autocapture', properties);
|
|
1234
1242
|
};
|
|
1235
1243
|
document.addEventListener('click', clickListener, true);
|
|
1236
1244
|
this.listeners.set('click', clickListener);
|
|
@@ -1242,10 +1250,7 @@ class AutocaptureTracker {
|
|
|
1242
1250
|
return;
|
|
1243
1251
|
}
|
|
1244
1252
|
const properties = this.getFormProperties(target, 'submit');
|
|
1245
|
-
this.client.track('$autocapture',
|
|
1246
|
-
$event_type: 'submit',
|
|
1247
|
-
...properties,
|
|
1248
|
-
});
|
|
1253
|
+
this.client.track('$autocapture', properties);
|
|
1249
1254
|
};
|
|
1250
1255
|
document.addEventListener('submit', submitListener, true);
|
|
1251
1256
|
this.listeners.set('submit', submitListener);
|
|
@@ -1257,10 +1262,7 @@ class AutocaptureTracker {
|
|
|
1257
1262
|
return;
|
|
1258
1263
|
}
|
|
1259
1264
|
const properties = this.getInputProperties(target, 'change');
|
|
1260
|
-
this.client.track('$autocapture',
|
|
1261
|
-
$event_type: 'change',
|
|
1262
|
-
...properties,
|
|
1263
|
-
});
|
|
1265
|
+
this.client.track('$autocapture', properties);
|
|
1264
1266
|
};
|
|
1265
1267
|
document.addEventListener('change', changeListener, true);
|
|
1266
1268
|
this.listeners.set('change', changeListener);
|
|
@@ -1313,6 +1315,7 @@ class AutocaptureTracker {
|
|
|
1313
1315
|
}
|
|
1314
1316
|
getElementProperties(element, eventType) {
|
|
1315
1317
|
const properties = {
|
|
1318
|
+
$event_type: eventType,
|
|
1316
1319
|
$element_tag: element.tagName.toLowerCase(),
|
|
1317
1320
|
$element_type: this.getElementType(element),
|
|
1318
1321
|
};
|
|
@@ -1322,6 +1325,7 @@ class AutocaptureTracker {
|
|
|
1322
1325
|
}
|
|
1323
1326
|
if (element.className) {
|
|
1324
1327
|
properties.$element_classes = Array.from(element.classList);
|
|
1328
|
+
properties.$element_semantic_classes = this.extractSemanticClasses(element.classList);
|
|
1325
1329
|
}
|
|
1326
1330
|
// Element attributes
|
|
1327
1331
|
const relevantAttributes = ['name', 'role', 'aria-label', 'data-testid', 'data-track'];
|
|
@@ -1331,6 +1335,33 @@ class AutocaptureTracker {
|
|
|
1331
1335
|
properties[`$element_${attr.replace('-', '_')}`] = value;
|
|
1332
1336
|
}
|
|
1333
1337
|
});
|
|
1338
|
+
// Configurable data-* attribute capture
|
|
1339
|
+
const prefixes = this.options.dataAttributePrefixes || ['jrnm-'];
|
|
1340
|
+
const exactNames = new Set(this.options.dataAttributeNames || ['data-testid', 'data-track']);
|
|
1341
|
+
const relevantSet = new Set(relevantAttributes);
|
|
1342
|
+
let dataAttrCount = 0;
|
|
1343
|
+
for (let i = 0; i < element.attributes.length && dataAttrCount < 10; i++) {
|
|
1344
|
+
const attr = element.attributes.item(i);
|
|
1345
|
+
if (!attr || !attr.name.startsWith('data-'))
|
|
1346
|
+
continue;
|
|
1347
|
+
if (relevantSet.has(attr.name))
|
|
1348
|
+
continue;
|
|
1349
|
+
const suffix = attr.name.slice(5); // strip 'data-'
|
|
1350
|
+
const matchesPrefix = prefixes.some(p => suffix.startsWith(p));
|
|
1351
|
+
const matchesName = exactNames.has(attr.name);
|
|
1352
|
+
if (matchesPrefix || matchesName) {
|
|
1353
|
+
const propName = `$attr_${attr.name.replace(/-/g, '_')}`;
|
|
1354
|
+
properties[propName] = attr.value;
|
|
1355
|
+
dataAttrCount++;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
// Link href as first-class property
|
|
1359
|
+
if (element.tagName.toLowerCase() === 'a') {
|
|
1360
|
+
const href = element.getAttribute('href');
|
|
1361
|
+
if (href) {
|
|
1362
|
+
properties.$element_href = href;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1334
1365
|
// Element content
|
|
1335
1366
|
if (this.options.captureContentText) {
|
|
1336
1367
|
const text = this.getElementText(element);
|
|
@@ -1360,10 +1391,13 @@ class AutocaptureTracker {
|
|
|
1360
1391
|
properties.$parent_id = element.parentElement.id;
|
|
1361
1392
|
}
|
|
1362
1393
|
}
|
|
1363
|
-
// URL
|
|
1394
|
+
// URL and page context
|
|
1364
1395
|
properties.$current_url = window.location.href;
|
|
1365
1396
|
properties.$host = window.location.host;
|
|
1366
1397
|
properties.$pathname = window.location.pathname;
|
|
1398
|
+
properties.$search = window.location.search;
|
|
1399
|
+
properties.$page_title = document.title;
|
|
1400
|
+
properties.$referrer = document.referrer;
|
|
1367
1401
|
return properties;
|
|
1368
1402
|
}
|
|
1369
1403
|
getFormProperties(form, eventType) {
|
|
@@ -1512,6 +1546,38 @@ class AutocaptureTracker {
|
|
|
1512
1546
|
ids: ids.reverse()
|
|
1513
1547
|
};
|
|
1514
1548
|
}
|
|
1549
|
+
extractSemanticClasses(classList) {
|
|
1550
|
+
const results = new Set();
|
|
1551
|
+
for (let i = 0; i < classList.length; i++) {
|
|
1552
|
+
const cls = classList.item(i);
|
|
1553
|
+
if (!cls)
|
|
1554
|
+
continue;
|
|
1555
|
+
const parts = cls.split('__');
|
|
1556
|
+
if (parts.length >= 3) {
|
|
1557
|
+
// CSS module pattern: Module__hash__name → take last segment
|
|
1558
|
+
const last = parts[parts.length - 1];
|
|
1559
|
+
if (last)
|
|
1560
|
+
results.add(last);
|
|
1561
|
+
}
|
|
1562
|
+
else if (parts.length === 2) {
|
|
1563
|
+
// 2-part __ class (e.g., Module__hash) → drop, no semantic name
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
// Single-part class — keep unless it looks like a hash
|
|
1568
|
+
if (!this.isHashLike(cls)) {
|
|
1569
|
+
results.add(cls);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return Array.from(results);
|
|
1574
|
+
}
|
|
1575
|
+
isHashLike(value) {
|
|
1576
|
+
// Hash-like: alphanumeric, 5-10 chars, contains both letters and digits
|
|
1577
|
+
return /^[a-zA-Z0-9]{5,10}$/.test(value)
|
|
1578
|
+
&& /[a-zA-Z]/.test(value)
|
|
1579
|
+
&& /[0-9]/.test(value);
|
|
1580
|
+
}
|
|
1515
1581
|
isSafeInputType(type) {
|
|
1516
1582
|
// Don't capture values for sensitive input types
|
|
1517
1583
|
const sensitiveTypes = ['password', 'email', 'tel', 'credit-card-number'];
|
|
@@ -1538,6 +1604,20 @@ class JourniumAnalytics {
|
|
|
1538
1604
|
// This handles cached remote options or local options with autocapture enabled
|
|
1539
1605
|
this.startAutocaptureIfEnabled(initialEffectiveOptions);
|
|
1540
1606
|
}
|
|
1607
|
+
resolvePageviewOptions(autoTrackPageviews, frameworkHandlesPageviews) {
|
|
1608
|
+
if (autoTrackPageviews === false || frameworkHandlesPageviews) {
|
|
1609
|
+
return { enabled: false, trackSpaPageviews: false, captureInitialPageview: false };
|
|
1610
|
+
}
|
|
1611
|
+
if (autoTrackPageviews === true || autoTrackPageviews === undefined) {
|
|
1612
|
+
return { enabled: true, trackSpaPageviews: true, captureInitialPageview: true };
|
|
1613
|
+
}
|
|
1614
|
+
// object form implies enabled
|
|
1615
|
+
return {
|
|
1616
|
+
enabled: true,
|
|
1617
|
+
trackSpaPageviews: autoTrackPageviews.trackSpaPageviews !== false,
|
|
1618
|
+
captureInitialPageview: autoTrackPageviews.trackInitialPageview !== false,
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1541
1621
|
resolveAutocaptureOptions(autocapture) {
|
|
1542
1622
|
if (autocapture === false) {
|
|
1543
1623
|
return {
|
|
@@ -1552,39 +1632,50 @@ class JourniumAnalytics {
|
|
|
1552
1632
|
}
|
|
1553
1633
|
return autocapture;
|
|
1554
1634
|
}
|
|
1635
|
+
/** Track a custom event with optional properties. */
|
|
1555
1636
|
track(event, properties) {
|
|
1556
1637
|
this.client.track(event, properties);
|
|
1557
1638
|
}
|
|
1639
|
+
/** Associate the current session with a known user identity and optional attributes. */
|
|
1558
1640
|
identify(distinctId, attributes) {
|
|
1559
1641
|
this.client.identify(distinctId, attributes);
|
|
1560
1642
|
}
|
|
1643
|
+
/** Clear the current identity, starting a new anonymous session. */
|
|
1561
1644
|
reset() {
|
|
1562
1645
|
this.client.reset();
|
|
1563
1646
|
}
|
|
1647
|
+
/** Manually capture a $pageview event with optional custom properties. */
|
|
1564
1648
|
capturePageview(properties) {
|
|
1565
1649
|
this.pageviewTracker.capturePageview(properties);
|
|
1566
1650
|
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Manually start autocapture (pageview tracking + DOM event capture).
|
|
1653
|
+
* Under normal usage this is not needed — the SDK starts automatically on init.
|
|
1654
|
+
* Useful only if autocapture was explicitly stopped and needs to be restarted.
|
|
1655
|
+
*/
|
|
1567
1656
|
startAutocapture() {
|
|
1568
1657
|
// Always check effective options (which may include remote options)
|
|
1569
1658
|
const effectiveOptions = this.client.getEffectiveOptions();
|
|
1570
|
-
// Only
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1659
|
+
// Only start if effectiveOptions are actually loaded (non-empty)
|
|
1660
|
+
const hasOptions = effectiveOptions && Object.keys(effectiveOptions).length > 0;
|
|
1661
|
+
const { enabled: autoTrackPageviews, trackSpaPageviews, captureInitialPageview } = hasOptions
|
|
1662
|
+
? this.resolvePageviewOptions(effectiveOptions.autoTrackPageviews, effectiveOptions._frameworkHandlesPageviews)
|
|
1663
|
+
: { enabled: false, trackSpaPageviews: false, captureInitialPageview: false };
|
|
1664
|
+
const autocaptureEnabled = hasOptions
|
|
1575
1665
|
? effectiveOptions.autocapture !== false
|
|
1576
1666
|
: false;
|
|
1577
1667
|
// Update autocapture tracker options if they've changed
|
|
1578
1668
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1579
1669
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1580
1670
|
if (autoTrackPageviews) {
|
|
1581
|
-
this.pageviewTracker.startAutoPageviewTracking();
|
|
1671
|
+
this.pageviewTracker.startAutoPageviewTracking(captureInitialPageview, trackSpaPageviews);
|
|
1582
1672
|
}
|
|
1583
1673
|
if (autocaptureEnabled) {
|
|
1584
1674
|
this.autocaptureTracker.start();
|
|
1585
1675
|
}
|
|
1586
1676
|
this.autocaptureStarted = true;
|
|
1587
1677
|
}
|
|
1678
|
+
/** Stop autocapture — pauses pageview tracking and DOM event capture. */
|
|
1588
1679
|
stopAutocapture() {
|
|
1589
1680
|
this.pageviewTracker.stopAutocapture();
|
|
1590
1681
|
this.autocaptureTracker.stop();
|
|
@@ -1604,13 +1695,13 @@ class JourniumAnalytics {
|
|
|
1604
1695
|
const hasActualOptions = effectiveOptions && Object.keys(effectiveOptions).length > 0;
|
|
1605
1696
|
if (hasActualOptions) {
|
|
1606
1697
|
// Use same logic as manual startAutocapture() but only start automatically
|
|
1607
|
-
const autoTrackPageviews = effectiveOptions.autoTrackPageviews
|
|
1698
|
+
const { enabled: autoTrackPageviews, trackSpaPageviews, captureInitialPageview } = this.resolvePageviewOptions(effectiveOptions.autoTrackPageviews, effectiveOptions._frameworkHandlesPageviews);
|
|
1608
1699
|
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1609
1700
|
// Update autocapture tracker options
|
|
1610
1701
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1611
1702
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1612
1703
|
if (autoTrackPageviews) {
|
|
1613
|
-
this.pageviewTracker.startAutoPageviewTracking();
|
|
1704
|
+
this.pageviewTracker.startAutoPageviewTracking(captureInitialPageview, trackSpaPageviews);
|
|
1614
1705
|
}
|
|
1615
1706
|
if (autocaptureEnabled) {
|
|
1616
1707
|
this.autocaptureTracker.start();
|
|
@@ -1635,21 +1726,23 @@ class JourniumAnalytics {
|
|
|
1635
1726
|
this.autocaptureTracker.stop();
|
|
1636
1727
|
this.autocaptureStarted = false;
|
|
1637
1728
|
}
|
|
1638
|
-
const autoTrackPageviews = effectiveOptions.autoTrackPageviews
|
|
1729
|
+
const { enabled: autoTrackPageviews, trackSpaPageviews, captureInitialPageview } = this.resolvePageviewOptions(effectiveOptions.autoTrackPageviews, effectiveOptions._frameworkHandlesPageviews);
|
|
1639
1730
|
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1640
1731
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1641
1732
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1642
1733
|
if (autoTrackPageviews) {
|
|
1643
|
-
this.pageviewTracker.startAutoPageviewTracking(isFirstStart);
|
|
1734
|
+
this.pageviewTracker.startAutoPageviewTracking(isFirstStart && captureInitialPageview, trackSpaPageviews);
|
|
1644
1735
|
}
|
|
1645
1736
|
if (autocaptureEnabled) {
|
|
1646
1737
|
this.autocaptureTracker.start();
|
|
1647
1738
|
}
|
|
1648
1739
|
this.autocaptureStarted = autoTrackPageviews || autocaptureEnabled;
|
|
1649
1740
|
}
|
|
1741
|
+
/** Flush all queued events to the ingestion endpoint immediately. */
|
|
1650
1742
|
async flush() {
|
|
1651
1743
|
return this.client.flush();
|
|
1652
1744
|
}
|
|
1745
|
+
/** Return the currently active options (merged local + remote config). */
|
|
1653
1746
|
getEffectiveOptions() {
|
|
1654
1747
|
return this.client.getEffectiveOptions();
|
|
1655
1748
|
}
|
|
@@ -1659,6 +1752,7 @@ class JourniumAnalytics {
|
|
|
1659
1752
|
onOptionsChange(callback) {
|
|
1660
1753
|
return this.client.onOptionsChange(callback);
|
|
1661
1754
|
}
|
|
1755
|
+
/** Tear down the analytics instance: stop all tracking, flush pending events, and release resources. */
|
|
1662
1756
|
destroy() {
|
|
1663
1757
|
this.pageviewTracker.stopAutocapture();
|
|
1664
1758
|
this.autocaptureTracker.stop();
|
|
@@ -1668,7 +1762,16 @@ class JourniumAnalytics {
|
|
|
1668
1762
|
this.client.destroy();
|
|
1669
1763
|
}
|
|
1670
1764
|
}
|
|
1765
|
+
/** Create and return a new JourniumAnalytics instance for the given config. */
|
|
1671
1766
|
const init = (config) => {
|
|
1767
|
+
var _a;
|
|
1768
|
+
// Set SDK version if not already set by a framework SDK (React, Next.js, Angular)
|
|
1769
|
+
if (!((_a = config.options) === null || _a === void 0 ? void 0 : _a._sdkVersion)) {
|
|
1770
|
+
config = {
|
|
1771
|
+
...config,
|
|
1772
|
+
options: { ...config.options, _sdkVersion: SDK_VERSION },
|
|
1773
|
+
};
|
|
1774
|
+
}
|
|
1672
1775
|
return new JourniumAnalytics(config);
|
|
1673
1776
|
};
|
|
1674
1777
|
|