@journium/react 1.1.1 → 1.1.3
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/hooks.d.ts.map +1 -1
- package/dist/index.cjs +136 -111
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +136 -111
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,gBAId,MAAM,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAOvD,CAAC;AAEF,eAAO,MAAM,WAAW,qBAIP,MAAM,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAO5D,CAAC;AAEF,eAAO,MAAM,QAAQ,kBAQpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,sBAIX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAOxC,CAAC;AAEF,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,gBAId,MAAM,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAOvD,CAAC;AAEF,eAAO,MAAM,WAAW,qBAIP,MAAM,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAO5D,CAAC;AAEF,eAAO,MAAM,QAAQ,kBAQpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,sBAIX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAOxC,CAAC;AAEF,eAAO,MAAM,oBAAoB,kBACjB,KAAK,CAAC,cAAc,eACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAOrC,CAAC;AAEF,eAAO,MAAM,cAAc;;;CAgB1B,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@ var React = require('react');
|
|
|
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 @@ class V7Generator {
|
|
|
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 @@ class V7Generator {
|
|
|
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 @@ class V7Generator {
|
|
|
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 @@ class V7Generator {
|
|
|
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() {
|
|
@@ -705,6 +709,9 @@ class JourniumClient {
|
|
|
705
709
|
this.queue = [];
|
|
706
710
|
this.stagedEvents = [];
|
|
707
711
|
this.flushTimer = null;
|
|
712
|
+
this.remoteOptionsRefreshTimer = null;
|
|
713
|
+
this.isRefreshing = false;
|
|
714
|
+
this.lastRemoteOptions = null;
|
|
708
715
|
this.initializationComplete = false;
|
|
709
716
|
this.initializationFailed = false;
|
|
710
717
|
this.optionsChangeCallbacks = new Set();
|
|
@@ -758,61 +765,24 @@ class JourniumClient {
|
|
|
758
765
|
}
|
|
759
766
|
}
|
|
760
767
|
async initializeAsync() {
|
|
761
|
-
var _a;
|
|
762
768
|
try {
|
|
763
769
|
Logger.log('Journium: Starting initialization - fetching fresh remote config...');
|
|
764
|
-
// Step 1: Try to fetch fresh remote config with timeout and retry
|
|
765
770
|
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
766
|
-
if (remoteOptions) {
|
|
767
|
-
|
|
768
|
-
this.
|
|
769
|
-
|
|
770
|
-
if (this.config.options) {
|
|
771
|
-
this.effectiveOptions = mergeOptions(this.config.options, remoteOptions);
|
|
772
|
-
Logger.log('Journium: Using fresh remote config merged with local options:', this.effectiveOptions);
|
|
773
|
-
}
|
|
774
|
-
else {
|
|
775
|
-
this.effectiveOptions = remoteOptions;
|
|
776
|
-
Logger.log('Journium: Using fresh remote config:', this.effectiveOptions);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
else {
|
|
780
|
-
// Step 4: Fallback to cached config if fresh fetch failed
|
|
781
|
-
/* const cachedRemoteOptions = this.loadCachedOptions();
|
|
782
|
-
|
|
783
|
-
if (cachedRemoteOptions) {
|
|
784
|
-
if (this.config.options) {
|
|
785
|
-
this.effectiveOptions = mergeOptions(this.config.options, cachedRemoteOptions);
|
|
786
|
-
Logger.log('Journium: Fresh config failed, using cached remote config merged with local options:', this.effectiveOptions);
|
|
787
|
-
} else {
|
|
788
|
-
this.effectiveOptions = cachedRemoteOptions;
|
|
789
|
-
Logger.log('Journium: Fresh config failed, using cached remote config:', this.effectiveOptions);
|
|
790
|
-
}
|
|
791
|
-
} else {
|
|
792
|
-
// Step 5: No remote config and no cached config - initialization fails
|
|
793
|
-
Logger.error('Journium: Initialization failed - no remote config available and no cached config found');
|
|
794
|
-
this.initializationFailed = true;
|
|
795
|
-
this.initializationComplete = false;
|
|
796
|
-
return;
|
|
797
|
-
} */
|
|
798
|
-
}
|
|
799
|
-
// Step 6: Update identity manager session timeout if provided
|
|
800
|
-
if (this.effectiveOptions.sessionTimeout) {
|
|
801
|
-
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
771
|
+
if (!remoteOptions) {
|
|
772
|
+
Logger.error('Journium: Initialization failed - no remote config available');
|
|
773
|
+
this.initializationFailed = true;
|
|
774
|
+
return;
|
|
802
775
|
}
|
|
803
|
-
|
|
804
|
-
Logger.
|
|
805
|
-
// Step 8: Mark initialization as complete
|
|
776
|
+
this.applyRemoteOptions(remoteOptions);
|
|
777
|
+
Logger.log('Journium: Effective options after init:', this.effectiveOptions);
|
|
806
778
|
this.initializationComplete = true;
|
|
807
779
|
this.initializationFailed = false;
|
|
808
|
-
// Step 9: Process any staged events
|
|
809
780
|
this.processStagedEvents();
|
|
810
|
-
// Step 10: Start flush timer
|
|
811
781
|
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
812
782
|
this.startFlushTimer();
|
|
813
783
|
}
|
|
814
|
-
|
|
815
|
-
|
|
784
|
+
this.startRemoteOptionsRefreshTimer();
|
|
785
|
+
Logger.log('Journium: Initialization complete');
|
|
816
786
|
this.notifyOptionsChange();
|
|
817
787
|
}
|
|
818
788
|
catch (error) {
|
|
@@ -883,35 +853,21 @@ class JourniumClient {
|
|
|
883
853
|
processStagedEvents() {
|
|
884
854
|
if (this.stagedEvents.length === 0)
|
|
885
855
|
return;
|
|
856
|
+
if (this.ingestionPaused) {
|
|
857
|
+
Logger.warn(`Journium: Ingestion is paused — discarding ${this.stagedEvents.length} staged events`);
|
|
858
|
+
this.stagedEvents = [];
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
886
861
|
Logger.log(`Journium: Processing ${this.stagedEvents.length} staged events`);
|
|
887
|
-
// Move staged events to main queue, adding identity properties now
|
|
888
|
-
const identity = this.identityManager.getIdentity();
|
|
889
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
890
862
|
for (const stagedEvent of this.stagedEvents) {
|
|
891
|
-
|
|
892
|
-
const eventWithIdentity = {
|
|
863
|
+
this.queue.push({
|
|
893
864
|
...stagedEvent,
|
|
894
|
-
properties:
|
|
895
|
-
|
|
896
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
897
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
898
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
899
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
900
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
901
|
-
...userAgentInfo,
|
|
902
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
903
|
-
$platform: 'web',
|
|
904
|
-
...stagedEvent.properties, // Original properties override system properties
|
|
905
|
-
},
|
|
906
|
-
};
|
|
907
|
-
this.queue.push(eventWithIdentity);
|
|
865
|
+
properties: this.buildIdentityProperties(stagedEvent.properties),
|
|
866
|
+
});
|
|
908
867
|
}
|
|
909
|
-
// Clear staged events
|
|
910
868
|
this.stagedEvents = [];
|
|
911
869
|
Logger.log('Journium: Staged events processed and moved to main queue');
|
|
912
|
-
// Check if we should flush immediately
|
|
913
870
|
if (this.queue.length >= this.effectiveOptions.flushAt) {
|
|
914
|
-
// console.log('1 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
915
871
|
this.flush();
|
|
916
872
|
}
|
|
917
873
|
}
|
|
@@ -919,12 +875,88 @@ class JourniumClient {
|
|
|
919
875
|
if (this.flushTimer) {
|
|
920
876
|
clearInterval(this.flushTimer);
|
|
921
877
|
}
|
|
922
|
-
// Use universal setInterval (works in both browser and Node.js)
|
|
923
878
|
this.flushTimer = setInterval(() => {
|
|
924
|
-
// console.log('2 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
925
879
|
this.flush();
|
|
926
880
|
}, this.effectiveOptions.flushInterval);
|
|
927
881
|
}
|
|
882
|
+
startRemoteOptionsRefreshTimer() {
|
|
883
|
+
// Clear any existing timer to prevent duplicate intervals
|
|
884
|
+
if (this.remoteOptionsRefreshTimer) {
|
|
885
|
+
clearInterval(this.remoteOptionsRefreshTimer);
|
|
886
|
+
this.remoteOptionsRefreshTimer = null;
|
|
887
|
+
}
|
|
888
|
+
this.remoteOptionsRefreshTimer = setInterval(() => {
|
|
889
|
+
this.refreshRemoteOptions();
|
|
890
|
+
}, JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL);
|
|
891
|
+
Logger.log(`Journium: Scheduling remote options refresh every ${JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL}ms`);
|
|
892
|
+
}
|
|
893
|
+
async refreshRemoteOptions() {
|
|
894
|
+
if (this.isRefreshing) {
|
|
895
|
+
Logger.log('Journium: Remote options refresh already in progress, skipping');
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
this.isRefreshing = true;
|
|
899
|
+
Logger.log('Journium: Periodic remote options refresh triggered');
|
|
900
|
+
try {
|
|
901
|
+
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
902
|
+
if (!remoteOptions) {
|
|
903
|
+
Logger.warn('Journium: Periodic remote options refresh failed, keeping current options');
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const prevRemoteSnapshot = JSON.stringify(this.lastRemoteOptions);
|
|
907
|
+
const prevFlushInterval = this.effectiveOptions.flushInterval;
|
|
908
|
+
this.applyRemoteOptions(remoteOptions);
|
|
909
|
+
if (prevRemoteSnapshot === JSON.stringify(this.lastRemoteOptions)) {
|
|
910
|
+
Logger.log('Journium: Remote options unchanged after refresh, no update needed');
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
Logger.log('Journium: Remote options updated after refresh:', this.effectiveOptions);
|
|
914
|
+
if (this.effectiveOptions.flushInterval !== prevFlushInterval) {
|
|
915
|
+
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
916
|
+
this.startFlushTimer();
|
|
917
|
+
}
|
|
918
|
+
else if (this.flushTimer) {
|
|
919
|
+
clearInterval(this.flushTimer);
|
|
920
|
+
this.flushTimer = null;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
this.notifyOptionsChange();
|
|
924
|
+
}
|
|
925
|
+
catch (error) {
|
|
926
|
+
Logger.error('Journium: Periodic remote options refresh encountered an error:', error);
|
|
927
|
+
}
|
|
928
|
+
finally {
|
|
929
|
+
this.isRefreshing = false;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
applyRemoteOptions(remoteOptions) {
|
|
933
|
+
var _a;
|
|
934
|
+
this.lastRemoteOptions = remoteOptions;
|
|
935
|
+
this.effectiveOptions = this.config.options
|
|
936
|
+
? mergeOptions(this.config.options, remoteOptions)
|
|
937
|
+
: remoteOptions;
|
|
938
|
+
this.saveCachedOptions(remoteOptions);
|
|
939
|
+
if (this.effectiveOptions.sessionTimeout) {
|
|
940
|
+
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
941
|
+
}
|
|
942
|
+
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
943
|
+
}
|
|
944
|
+
buildIdentityProperties(userProperties = {}) {
|
|
945
|
+
const identity = this.identityManager.getIdentity();
|
|
946
|
+
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
947
|
+
return {
|
|
948
|
+
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
949
|
+
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
950
|
+
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
951
|
+
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
952
|
+
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
953
|
+
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
954
|
+
...userAgentInfo,
|
|
955
|
+
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
956
|
+
$platform: 'web',
|
|
957
|
+
...userProperties,
|
|
958
|
+
};
|
|
959
|
+
}
|
|
928
960
|
async sendEvents(events) {
|
|
929
961
|
if (!events.length)
|
|
930
962
|
return;
|
|
@@ -984,9 +1016,7 @@ class JourniumClient {
|
|
|
984
1016
|
event,
|
|
985
1017
|
properties: { ...properties }, // Only user properties for now
|
|
986
1018
|
};
|
|
987
|
-
// Stage events during initialization, add to queue after initialization
|
|
988
1019
|
if (!this.initializationComplete) {
|
|
989
|
-
// If initialization failed, reject events
|
|
990
1020
|
if (this.initializationFailed) {
|
|
991
1021
|
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
992
1022
|
return;
|
|
@@ -995,34 +1025,17 @@ class JourniumClient {
|
|
|
995
1025
|
Logger.log('Journium: Event staged during initialization', journiumEvent);
|
|
996
1026
|
return;
|
|
997
1027
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
1028
|
+
if (this.ingestionPaused) {
|
|
1029
|
+
Logger.warn('Journium: Ingestion is paused — event dropped:', journiumEvent.event);
|
|
1001
1030
|
return;
|
|
1002
1031
|
}
|
|
1003
|
-
// Add identity properties for immediate events (after initialization)
|
|
1004
|
-
const identity = this.identityManager.getIdentity();
|
|
1005
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
1006
1032
|
const eventWithIdentity = {
|
|
1007
1033
|
...journiumEvent,
|
|
1008
|
-
properties:
|
|
1009
|
-
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
1010
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
1011
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
1012
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
1013
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
1014
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
1015
|
-
...userAgentInfo,
|
|
1016
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
1017
|
-
$platform: 'web',
|
|
1018
|
-
...properties, // User-provided properties override system properties
|
|
1019
|
-
},
|
|
1034
|
+
properties: this.buildIdentityProperties(properties),
|
|
1020
1035
|
};
|
|
1021
1036
|
this.queue.push(eventWithIdentity);
|
|
1022
1037
|
Logger.log('Journium: Event tracked', eventWithIdentity);
|
|
1023
|
-
// Only flush if we have effective options (after initialization)
|
|
1024
1038
|
if (this.effectiveOptions.flushAt && this.queue.length >= this.effectiveOptions.flushAt) {
|
|
1025
|
-
// console.log('3 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
1026
1039
|
this.flush();
|
|
1027
1040
|
}
|
|
1028
1041
|
}
|
|
@@ -1049,12 +1062,20 @@ class JourniumClient {
|
|
|
1049
1062
|
clearInterval(this.flushTimer);
|
|
1050
1063
|
this.flushTimer = null;
|
|
1051
1064
|
}
|
|
1065
|
+
if (this.remoteOptionsRefreshTimer) {
|
|
1066
|
+
clearInterval(this.remoteOptionsRefreshTimer);
|
|
1067
|
+
this.remoteOptionsRefreshTimer = null;
|
|
1068
|
+
}
|
|
1052
1069
|
this.flush();
|
|
1053
1070
|
}
|
|
1054
1071
|
getEffectiveOptions() {
|
|
1055
1072
|
return this.effectiveOptions;
|
|
1056
1073
|
}
|
|
1074
|
+
get ingestionPaused() {
|
|
1075
|
+
return this.effectiveOptions['ingestionPaused'] === true;
|
|
1076
|
+
}
|
|
1057
1077
|
}
|
|
1078
|
+
JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL = 15 * 60 * 1000; // 15 minutes
|
|
1058
1079
|
|
|
1059
1080
|
class PageviewTracker {
|
|
1060
1081
|
constructor(client) {
|
|
@@ -1081,10 +1102,13 @@ class PageviewTracker {
|
|
|
1081
1102
|
}
|
|
1082
1103
|
/**
|
|
1083
1104
|
* Start automatic autocapture for pageviews
|
|
1084
|
-
* @
|
|
1105
|
+
* @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
|
|
1106
|
+
* Pass false when restarting after a remote options update to avoid a spurious pageview.
|
|
1085
1107
|
*/
|
|
1086
|
-
startAutoPageviewTracking() {
|
|
1087
|
-
|
|
1108
|
+
startAutoPageviewTracking(captureInitialPageview = true) {
|
|
1109
|
+
if (captureInitialPageview) {
|
|
1110
|
+
this.capturePageview();
|
|
1111
|
+
}
|
|
1088
1112
|
if (typeof window !== 'undefined') {
|
|
1089
1113
|
// Store original methods for cleanup
|
|
1090
1114
|
this.originalPushState = window.history.pushState;
|
|
@@ -1603,21 +1627,22 @@ class JourniumAnalytics {
|
|
|
1603
1627
|
* Handle effective options change (e.g., when remote options are fetched)
|
|
1604
1628
|
*/
|
|
1605
1629
|
handleOptionsChange(effectiveOptions) {
|
|
1606
|
-
//
|
|
1630
|
+
// If autocapture was never started before, this is the initial options application
|
|
1631
|
+
// (async init completed) — treat it like a page load and capture a pageview.
|
|
1632
|
+
// If it was already started, this is a periodic remote options update — only
|
|
1633
|
+
// re-register listeners without emitting a spurious pageview.
|
|
1634
|
+
const isFirstStart = !this.autocaptureStarted;
|
|
1607
1635
|
if (this.autocaptureStarted) {
|
|
1608
1636
|
this.pageviewTracker.stopAutocapture();
|
|
1609
1637
|
this.autocaptureTracker.stop();
|
|
1610
1638
|
this.autocaptureStarted = false;
|
|
1611
1639
|
}
|
|
1612
|
-
// Evaluate if autocapture should be enabled with new options
|
|
1613
1640
|
const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
|
|
1614
1641
|
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1615
|
-
// Update autocapture tracker options
|
|
1616
1642
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1617
1643
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1618
|
-
// Start autocapture based on new options (even if it wasn't started before)
|
|
1619
1644
|
if (autoTrackPageviews) {
|
|
1620
|
-
this.pageviewTracker.startAutoPageviewTracking();
|
|
1645
|
+
this.pageviewTracker.startAutoPageviewTracking(isFirstStart);
|
|
1621
1646
|
}
|
|
1622
1647
|
if (autocaptureEnabled) {
|
|
1623
1648
|
this.autocaptureTracker.start();
|