@journium/js 1.1.1 → 1.2.1
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/JourniumAnalytics.d.ts.map +1 -1
- package/dist/JourniumClient.d.ts +9 -0
- package/dist/JourniumClient.d.ts.map +1 -1
- package/dist/PageviewTracker.d.ts +3 -2
- package/dist/PageviewTracker.d.ts.map +1 -1
- package/dist/index.cjs +136 -111
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.mjs +136 -111
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +136 -111
- package/dist/index.umd.js.map +1 -1
- package/dist/journium.js +136 -111
- package/dist/journium.js.map +1 -1
- package/dist/journium.min.js +1 -1
- package/dist/journium.min.js.map +1 -1
- package/package.json +4 -4
package/dist/journium.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* uuidv7: A JavaScript implementation of UUID version 7
|
|
7
7
|
*
|
|
8
|
-
* Copyright 2021-
|
|
8
|
+
* Copyright 2021-2025 LiosK
|
|
9
9
|
*
|
|
10
10
|
* @license Apache-2.0
|
|
11
11
|
* @packageDocumentation
|
|
@@ -234,7 +234,10 @@
|
|
|
234
234
|
* number generator should be cryptographically strong and securely seeded.
|
|
235
235
|
*/
|
|
236
236
|
constructor(randomNumberGenerator) {
|
|
237
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Biased by one to distinguish zero (uninitialized) and zero (UNIX epoch).
|
|
239
|
+
*/
|
|
240
|
+
this.timestamp_biased = 0;
|
|
238
241
|
this.counter = 0;
|
|
239
242
|
this.random = randomNumberGenerator !== null && randomNumberGenerator !== void 0 ? randomNumberGenerator : getDefaultRandom();
|
|
240
243
|
}
|
|
@@ -280,13 +283,13 @@
|
|
|
280
283
|
*
|
|
281
284
|
* @param rollbackAllowance - The amount of `unixTsMs` rollback that is
|
|
282
285
|
* considered significant. A suggested value is `10_000` (milliseconds).
|
|
283
|
-
* @throws RangeError if `unixTsMs` is not a 48-bit
|
|
286
|
+
* @throws RangeError if `unixTsMs` is not a 48-bit unsigned integer.
|
|
284
287
|
*/
|
|
285
288
|
generateOrResetCore(unixTsMs, rollbackAllowance) {
|
|
286
289
|
let value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
287
290
|
if (value === undefined) {
|
|
288
291
|
// reset state and resume
|
|
289
|
-
this.
|
|
292
|
+
this.timestamp_biased = 0;
|
|
290
293
|
value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
291
294
|
}
|
|
292
295
|
return value;
|
|
@@ -300,28 +303,29 @@
|
|
|
300
303
|
*
|
|
301
304
|
* @param rollbackAllowance - The amount of `unixTsMs` rollback that is
|
|
302
305
|
* considered significant. A suggested value is `10_000` (milliseconds).
|
|
303
|
-
* @throws RangeError if `unixTsMs` is not a 48-bit
|
|
306
|
+
* @throws RangeError if `unixTsMs` is not a 48-bit unsigned integer.
|
|
304
307
|
*/
|
|
305
308
|
generateOrAbortCore(unixTsMs, rollbackAllowance) {
|
|
306
309
|
const MAX_COUNTER = 4398046511103;
|
|
307
310
|
if (!Number.isInteger(unixTsMs) ||
|
|
308
|
-
unixTsMs <
|
|
311
|
+
unixTsMs < 0 ||
|
|
309
312
|
unixTsMs > 281474976710655) {
|
|
310
|
-
throw new RangeError("`unixTsMs` must be a 48-bit
|
|
313
|
+
throw new RangeError("`unixTsMs` must be a 48-bit unsigned integer");
|
|
311
314
|
}
|
|
312
315
|
else if (rollbackAllowance < 0 || rollbackAllowance > 281474976710655) {
|
|
313
316
|
throw new RangeError("`rollbackAllowance` out of reasonable range");
|
|
314
317
|
}
|
|
315
|
-
|
|
316
|
-
|
|
318
|
+
unixTsMs++;
|
|
319
|
+
if (unixTsMs > this.timestamp_biased) {
|
|
320
|
+
this.timestamp_biased = unixTsMs;
|
|
317
321
|
this.resetCounter();
|
|
318
322
|
}
|
|
319
|
-
else if (unixTsMs + rollbackAllowance >= this.
|
|
323
|
+
else if (unixTsMs + rollbackAllowance >= this.timestamp_biased) {
|
|
320
324
|
// go on with previous timestamp if new one is not much smaller
|
|
321
325
|
this.counter++;
|
|
322
326
|
if (this.counter > MAX_COUNTER) {
|
|
323
327
|
// increment timestamp at counter overflow
|
|
324
|
-
this.
|
|
328
|
+
this.timestamp_biased++;
|
|
325
329
|
this.resetCounter();
|
|
326
330
|
}
|
|
327
331
|
}
|
|
@@ -329,7 +333,7 @@
|
|
|
329
333
|
// abort if clock went backwards to unbearable extent
|
|
330
334
|
return undefined;
|
|
331
335
|
}
|
|
332
|
-
return UUID.fromFieldsV7(this.
|
|
336
|
+
return UUID.fromFieldsV7(this.timestamp_biased - 1, Math.trunc(this.counter / 2 ** 30), this.counter & (2 ** 30 - 1), this.random.nextUint32());
|
|
333
337
|
}
|
|
334
338
|
/** Initializes the counter at a 42-bit random integer. */
|
|
335
339
|
resetCounter() {
|
|
@@ -701,6 +705,9 @@
|
|
|
701
705
|
this.queue = [];
|
|
702
706
|
this.stagedEvents = [];
|
|
703
707
|
this.flushTimer = null;
|
|
708
|
+
this.remoteOptionsRefreshTimer = null;
|
|
709
|
+
this.isRefreshing = false;
|
|
710
|
+
this.lastRemoteOptions = null;
|
|
704
711
|
this.initializationComplete = false;
|
|
705
712
|
this.initializationFailed = false;
|
|
706
713
|
this.optionsChangeCallbacks = new Set();
|
|
@@ -754,61 +761,24 @@
|
|
|
754
761
|
}
|
|
755
762
|
}
|
|
756
763
|
async initializeAsync() {
|
|
757
|
-
var _a;
|
|
758
764
|
try {
|
|
759
765
|
Logger.log('Journium: Starting initialization - fetching fresh remote config...');
|
|
760
|
-
// Step 1: Try to fetch fresh remote config with timeout and retry
|
|
761
766
|
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
762
|
-
if (remoteOptions) {
|
|
763
|
-
|
|
764
|
-
this.
|
|
765
|
-
|
|
766
|
-
if (this.config.options) {
|
|
767
|
-
this.effectiveOptions = mergeOptions(this.config.options, remoteOptions);
|
|
768
|
-
Logger.log('Journium: Using fresh remote config merged with local options:', this.effectiveOptions);
|
|
769
|
-
}
|
|
770
|
-
else {
|
|
771
|
-
this.effectiveOptions = remoteOptions;
|
|
772
|
-
Logger.log('Journium: Using fresh remote config:', this.effectiveOptions);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
else {
|
|
776
|
-
// Step 4: Fallback to cached config if fresh fetch failed
|
|
777
|
-
/* const cachedRemoteOptions = this.loadCachedOptions();
|
|
778
|
-
|
|
779
|
-
if (cachedRemoteOptions) {
|
|
780
|
-
if (this.config.options) {
|
|
781
|
-
this.effectiveOptions = mergeOptions(this.config.options, cachedRemoteOptions);
|
|
782
|
-
Logger.log('Journium: Fresh config failed, using cached remote config merged with local options:', this.effectiveOptions);
|
|
783
|
-
} else {
|
|
784
|
-
this.effectiveOptions = cachedRemoteOptions;
|
|
785
|
-
Logger.log('Journium: Fresh config failed, using cached remote config:', this.effectiveOptions);
|
|
786
|
-
}
|
|
787
|
-
} else {
|
|
788
|
-
// Step 5: No remote config and no cached config - initialization fails
|
|
789
|
-
Logger.error('Journium: Initialization failed - no remote config available and no cached config found');
|
|
790
|
-
this.initializationFailed = true;
|
|
791
|
-
this.initializationComplete = false;
|
|
792
|
-
return;
|
|
793
|
-
} */
|
|
794
|
-
}
|
|
795
|
-
// Step 6: Update identity manager session timeout if provided
|
|
796
|
-
if (this.effectiveOptions.sessionTimeout) {
|
|
797
|
-
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
767
|
+
if (!remoteOptions) {
|
|
768
|
+
Logger.error('Journium: Initialization failed - no remote config available');
|
|
769
|
+
this.initializationFailed = true;
|
|
770
|
+
return;
|
|
798
771
|
}
|
|
799
|
-
|
|
800
|
-
Logger.
|
|
801
|
-
// Step 8: Mark initialization as complete
|
|
772
|
+
this.applyRemoteOptions(remoteOptions);
|
|
773
|
+
Logger.log('Journium: Effective options after init:', this.effectiveOptions);
|
|
802
774
|
this.initializationComplete = true;
|
|
803
775
|
this.initializationFailed = false;
|
|
804
|
-
// Step 9: Process any staged events
|
|
805
776
|
this.processStagedEvents();
|
|
806
|
-
// Step 10: Start flush timer
|
|
807
777
|
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
808
778
|
this.startFlushTimer();
|
|
809
779
|
}
|
|
810
|
-
|
|
811
|
-
|
|
780
|
+
this.startRemoteOptionsRefreshTimer();
|
|
781
|
+
Logger.log('Journium: Initialization complete');
|
|
812
782
|
this.notifyOptionsChange();
|
|
813
783
|
}
|
|
814
784
|
catch (error) {
|
|
@@ -879,35 +849,21 @@
|
|
|
879
849
|
processStagedEvents() {
|
|
880
850
|
if (this.stagedEvents.length === 0)
|
|
881
851
|
return;
|
|
852
|
+
if (this.ingestionPaused) {
|
|
853
|
+
Logger.warn(`Journium: Ingestion is paused — discarding ${this.stagedEvents.length} staged events`);
|
|
854
|
+
this.stagedEvents = [];
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
882
857
|
Logger.log(`Journium: Processing ${this.stagedEvents.length} staged events`);
|
|
883
|
-
// Move staged events to main queue, adding identity properties now
|
|
884
|
-
const identity = this.identityManager.getIdentity();
|
|
885
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
886
858
|
for (const stagedEvent of this.stagedEvents) {
|
|
887
|
-
|
|
888
|
-
const eventWithIdentity = {
|
|
859
|
+
this.queue.push({
|
|
889
860
|
...stagedEvent,
|
|
890
|
-
properties:
|
|
891
|
-
|
|
892
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
893
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
894
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
895
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
896
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
897
|
-
...userAgentInfo,
|
|
898
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
899
|
-
$platform: 'web',
|
|
900
|
-
...stagedEvent.properties, // Original properties override system properties
|
|
901
|
-
},
|
|
902
|
-
};
|
|
903
|
-
this.queue.push(eventWithIdentity);
|
|
861
|
+
properties: this.buildIdentityProperties(stagedEvent.properties),
|
|
862
|
+
});
|
|
904
863
|
}
|
|
905
|
-
// Clear staged events
|
|
906
864
|
this.stagedEvents = [];
|
|
907
865
|
Logger.log('Journium: Staged events processed and moved to main queue');
|
|
908
|
-
// Check if we should flush immediately
|
|
909
866
|
if (this.queue.length >= this.effectiveOptions.flushAt) {
|
|
910
|
-
// console.log('1 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
911
867
|
this.flush();
|
|
912
868
|
}
|
|
913
869
|
}
|
|
@@ -915,12 +871,88 @@
|
|
|
915
871
|
if (this.flushTimer) {
|
|
916
872
|
clearInterval(this.flushTimer);
|
|
917
873
|
}
|
|
918
|
-
// Use universal setInterval (works in both browser and Node.js)
|
|
919
874
|
this.flushTimer = setInterval(() => {
|
|
920
|
-
// console.log('2 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
921
875
|
this.flush();
|
|
922
876
|
}, this.effectiveOptions.flushInterval);
|
|
923
877
|
}
|
|
878
|
+
startRemoteOptionsRefreshTimer() {
|
|
879
|
+
// Clear any existing timer to prevent duplicate intervals
|
|
880
|
+
if (this.remoteOptionsRefreshTimer) {
|
|
881
|
+
clearInterval(this.remoteOptionsRefreshTimer);
|
|
882
|
+
this.remoteOptionsRefreshTimer = null;
|
|
883
|
+
}
|
|
884
|
+
this.remoteOptionsRefreshTimer = setInterval(() => {
|
|
885
|
+
this.refreshRemoteOptions();
|
|
886
|
+
}, JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL);
|
|
887
|
+
Logger.log(`Journium: Scheduling remote options refresh every ${JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL}ms`);
|
|
888
|
+
}
|
|
889
|
+
async refreshRemoteOptions() {
|
|
890
|
+
if (this.isRefreshing) {
|
|
891
|
+
Logger.log('Journium: Remote options refresh already in progress, skipping');
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
this.isRefreshing = true;
|
|
895
|
+
Logger.log('Journium: Periodic remote options refresh triggered');
|
|
896
|
+
try {
|
|
897
|
+
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
898
|
+
if (!remoteOptions) {
|
|
899
|
+
Logger.warn('Journium: Periodic remote options refresh failed, keeping current options');
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
const prevRemoteSnapshot = JSON.stringify(this.lastRemoteOptions);
|
|
903
|
+
const prevFlushInterval = this.effectiveOptions.flushInterval;
|
|
904
|
+
this.applyRemoteOptions(remoteOptions);
|
|
905
|
+
if (prevRemoteSnapshot === JSON.stringify(this.lastRemoteOptions)) {
|
|
906
|
+
Logger.log('Journium: Remote options unchanged after refresh, no update needed');
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
Logger.log('Journium: Remote options updated after refresh:', this.effectiveOptions);
|
|
910
|
+
if (this.effectiveOptions.flushInterval !== prevFlushInterval) {
|
|
911
|
+
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
912
|
+
this.startFlushTimer();
|
|
913
|
+
}
|
|
914
|
+
else if (this.flushTimer) {
|
|
915
|
+
clearInterval(this.flushTimer);
|
|
916
|
+
this.flushTimer = null;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
this.notifyOptionsChange();
|
|
920
|
+
}
|
|
921
|
+
catch (error) {
|
|
922
|
+
Logger.error('Journium: Periodic remote options refresh encountered an error:', error);
|
|
923
|
+
}
|
|
924
|
+
finally {
|
|
925
|
+
this.isRefreshing = false;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
applyRemoteOptions(remoteOptions) {
|
|
929
|
+
var _a;
|
|
930
|
+
this.lastRemoteOptions = remoteOptions;
|
|
931
|
+
this.effectiveOptions = this.config.options
|
|
932
|
+
? mergeOptions(this.config.options, remoteOptions)
|
|
933
|
+
: remoteOptions;
|
|
934
|
+
this.saveCachedOptions(remoteOptions);
|
|
935
|
+
if (this.effectiveOptions.sessionTimeout) {
|
|
936
|
+
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
937
|
+
}
|
|
938
|
+
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
939
|
+
}
|
|
940
|
+
buildIdentityProperties(userProperties = {}) {
|
|
941
|
+
const identity = this.identityManager.getIdentity();
|
|
942
|
+
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
943
|
+
return {
|
|
944
|
+
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
945
|
+
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
946
|
+
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
947
|
+
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
948
|
+
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
949
|
+
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
950
|
+
...userAgentInfo,
|
|
951
|
+
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
952
|
+
$platform: 'web',
|
|
953
|
+
...userProperties,
|
|
954
|
+
};
|
|
955
|
+
}
|
|
924
956
|
async sendEvents(events) {
|
|
925
957
|
if (!events.length)
|
|
926
958
|
return;
|
|
@@ -980,9 +1012,7 @@
|
|
|
980
1012
|
event,
|
|
981
1013
|
properties: { ...properties }, // Only user properties for now
|
|
982
1014
|
};
|
|
983
|
-
// Stage events during initialization, add to queue after initialization
|
|
984
1015
|
if (!this.initializationComplete) {
|
|
985
|
-
// If initialization failed, reject events
|
|
986
1016
|
if (this.initializationFailed) {
|
|
987
1017
|
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
988
1018
|
return;
|
|
@@ -991,34 +1021,17 @@
|
|
|
991
1021
|
Logger.log('Journium: Event staged during initialization', journiumEvent);
|
|
992
1022
|
return;
|
|
993
1023
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
1024
|
+
if (this.ingestionPaused) {
|
|
1025
|
+
Logger.warn('Journium: Ingestion is paused — event dropped:', journiumEvent.event);
|
|
997
1026
|
return;
|
|
998
1027
|
}
|
|
999
|
-
// Add identity properties for immediate events (after initialization)
|
|
1000
|
-
const identity = this.identityManager.getIdentity();
|
|
1001
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
1002
1028
|
const eventWithIdentity = {
|
|
1003
1029
|
...journiumEvent,
|
|
1004
|
-
properties:
|
|
1005
|
-
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
1006
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
1007
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
1008
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
1009
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
1010
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
1011
|
-
...userAgentInfo,
|
|
1012
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
1013
|
-
$platform: 'web',
|
|
1014
|
-
...properties, // User-provided properties override system properties
|
|
1015
|
-
},
|
|
1030
|
+
properties: this.buildIdentityProperties(properties),
|
|
1016
1031
|
};
|
|
1017
1032
|
this.queue.push(eventWithIdentity);
|
|
1018
1033
|
Logger.log('Journium: Event tracked', eventWithIdentity);
|
|
1019
|
-
// Only flush if we have effective options (after initialization)
|
|
1020
1034
|
if (this.effectiveOptions.flushAt && this.queue.length >= this.effectiveOptions.flushAt) {
|
|
1021
|
-
// console.log('3 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
1022
1035
|
this.flush();
|
|
1023
1036
|
}
|
|
1024
1037
|
}
|
|
@@ -1045,12 +1058,20 @@
|
|
|
1045
1058
|
clearInterval(this.flushTimer);
|
|
1046
1059
|
this.flushTimer = null;
|
|
1047
1060
|
}
|
|
1061
|
+
if (this.remoteOptionsRefreshTimer) {
|
|
1062
|
+
clearInterval(this.remoteOptionsRefreshTimer);
|
|
1063
|
+
this.remoteOptionsRefreshTimer = null;
|
|
1064
|
+
}
|
|
1048
1065
|
this.flush();
|
|
1049
1066
|
}
|
|
1050
1067
|
getEffectiveOptions() {
|
|
1051
1068
|
return this.effectiveOptions;
|
|
1052
1069
|
}
|
|
1070
|
+
get ingestionPaused() {
|
|
1071
|
+
return this.effectiveOptions['ingestionPaused'] === true;
|
|
1072
|
+
}
|
|
1053
1073
|
}
|
|
1074
|
+
JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL = 15 * 60 * 1000; // 15 minutes
|
|
1054
1075
|
|
|
1055
1076
|
class PageviewTracker {
|
|
1056
1077
|
constructor(client) {
|
|
@@ -1077,10 +1098,13 @@
|
|
|
1077
1098
|
}
|
|
1078
1099
|
/**
|
|
1079
1100
|
* Start automatic autocapture for pageviews
|
|
1080
|
-
* @
|
|
1101
|
+
* @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
|
|
1102
|
+
* Pass false when restarting after a remote options update to avoid a spurious pageview.
|
|
1081
1103
|
*/
|
|
1082
|
-
startAutoPageviewTracking() {
|
|
1083
|
-
|
|
1104
|
+
startAutoPageviewTracking(captureInitialPageview = true) {
|
|
1105
|
+
if (captureInitialPageview) {
|
|
1106
|
+
this.capturePageview();
|
|
1107
|
+
}
|
|
1084
1108
|
if (typeof window !== 'undefined') {
|
|
1085
1109
|
// Store original methods for cleanup
|
|
1086
1110
|
this.originalPushState = window.history.pushState;
|
|
@@ -1599,21 +1623,22 @@
|
|
|
1599
1623
|
* Handle effective options change (e.g., when remote options are fetched)
|
|
1600
1624
|
*/
|
|
1601
1625
|
handleOptionsChange(effectiveOptions) {
|
|
1602
|
-
//
|
|
1626
|
+
// If autocapture was never started before, this is the initial options application
|
|
1627
|
+
// (async init completed) — treat it like a page load and capture a pageview.
|
|
1628
|
+
// If it was already started, this is a periodic remote options update — only
|
|
1629
|
+
// re-register listeners without emitting a spurious pageview.
|
|
1630
|
+
const isFirstStart = !this.autocaptureStarted;
|
|
1603
1631
|
if (this.autocaptureStarted) {
|
|
1604
1632
|
this.pageviewTracker.stopAutocapture();
|
|
1605
1633
|
this.autocaptureTracker.stop();
|
|
1606
1634
|
this.autocaptureStarted = false;
|
|
1607
1635
|
}
|
|
1608
|
-
// Evaluate if autocapture should be enabled with new options
|
|
1609
1636
|
const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
|
|
1610
1637
|
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1611
|
-
// Update autocapture tracker options
|
|
1612
1638
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1613
1639
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1614
|
-
// Start autocapture based on new options (even if it wasn't started before)
|
|
1615
1640
|
if (autoTrackPageviews) {
|
|
1616
|
-
this.pageviewTracker.startAutoPageviewTracking();
|
|
1641
|
+
this.pageviewTracker.startAutoPageviewTracking(isFirstStart);
|
|
1617
1642
|
}
|
|
1618
1643
|
if (autocaptureEnabled) {
|
|
1619
1644
|
this.autocaptureTracker.start();
|