@journium/react 1.0.7 → 1.1.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/context.d.ts +3 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/index.cjs +257 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.mjs +258 -138
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -3
- package/readme.md +30 -326
package/dist/index.mjs
CHANGED
|
@@ -448,9 +448,9 @@ const fetchRemoteOptions = async (apiHost, publishableKey, fetchFn) => {
|
|
|
448
448
|
'Content-Type': 'application/json',
|
|
449
449
|
},
|
|
450
450
|
});
|
|
451
|
-
if (!response.ok) {
|
|
452
|
-
|
|
453
|
-
}
|
|
451
|
+
// if (!response.ok) {
|
|
452
|
+
// throw new Error(`Options fetch failed: ${response.status} ${response.statusText}`);
|
|
453
|
+
// }
|
|
454
454
|
const data = await response.json();
|
|
455
455
|
return data;
|
|
456
456
|
}
|
|
@@ -699,16 +699,20 @@ Logger.isDebugEnabled = false;
|
|
|
699
699
|
|
|
700
700
|
class JourniumClient {
|
|
701
701
|
constructor(config) {
|
|
702
|
-
var _a;
|
|
702
|
+
var _a, _b, _c, _d;
|
|
703
703
|
this.queue = [];
|
|
704
|
+
this.stagedEvents = [];
|
|
704
705
|
this.flushTimer = null;
|
|
705
|
-
this.
|
|
706
|
+
this.initializationComplete = false;
|
|
707
|
+
this.initializationFailed = false;
|
|
706
708
|
this.optionsChangeCallbacks = new Set();
|
|
707
709
|
// Validate required configuration
|
|
708
|
-
if (!config.publishableKey) {
|
|
710
|
+
if (!config.publishableKey || config.publishableKey.trim() === '') {
|
|
711
|
+
// Reject initialization with clear error
|
|
712
|
+
const errorMsg = 'Journium: publishableKey is required but not provided or is empty. SDK cannot be initialized.';
|
|
709
713
|
Logger.setDebug(true);
|
|
710
|
-
Logger.error(
|
|
711
|
-
|
|
714
|
+
Logger.error(errorMsg);
|
|
715
|
+
throw new Error(errorMsg);
|
|
712
716
|
}
|
|
713
717
|
// Set default apiHost if not provided
|
|
714
718
|
this.config = {
|
|
@@ -717,25 +721,15 @@ class JourniumClient {
|
|
|
717
721
|
};
|
|
718
722
|
// Generate storage key for options caching
|
|
719
723
|
this.optionsStorageKey = `jrnm_${config.publishableKey}_options`;
|
|
720
|
-
//
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
// Initialize
|
|
728
|
-
this.
|
|
729
|
-
if (this.config.options) {
|
|
730
|
-
this.effectiveOptions = mergeOptions(defaultOptions, this.config.options);
|
|
731
|
-
}
|
|
732
|
-
// Initialize Logger with debug setting
|
|
733
|
-
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
734
|
-
// Initialize identity manager
|
|
735
|
-
this.identityManager = new BrowserIdentityManager(this.effectiveOptions.sessionTimeout, this.config.publishableKey);
|
|
736
|
-
// Initialize synchronously with cached config, fetch fresh config in background
|
|
737
|
-
this.initializeSync();
|
|
738
|
-
this.fetchRemoteOptionsAsync();
|
|
724
|
+
// Initialize with minimal defaults for identity manager
|
|
725
|
+
const fallbackSessionTimeout = 30 * 60 * 1000; // 30 minutes
|
|
726
|
+
this.effectiveOptions = {}; // Will be set after remote config
|
|
727
|
+
// Initialize Logger with local debug setting or false
|
|
728
|
+
Logger.setDebug((_b = (_a = this.config.options) === null || _a === void 0 ? void 0 : _a.debug) !== null && _b !== void 0 ? _b : false);
|
|
729
|
+
// Initialize identity manager with fallback timeout
|
|
730
|
+
this.identityManager = new BrowserIdentityManager((_d = (_c = this.config.options) === null || _c === void 0 ? void 0 : _c.sessionTimeout) !== null && _d !== void 0 ? _d : fallbackSessionTimeout, this.config.publishableKey);
|
|
731
|
+
// Initialize asynchronously - wait for remote config first
|
|
732
|
+
this.initializeAsync();
|
|
739
733
|
}
|
|
740
734
|
loadCachedOptions() {
|
|
741
735
|
if (typeof window === 'undefined' || !window.localStorage) {
|
|
@@ -761,70 +755,108 @@ class JourniumClient {
|
|
|
761
755
|
Logger.warn('Journium: Failed to save config to cache:', error);
|
|
762
756
|
}
|
|
763
757
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
if (
|
|
771
|
-
//
|
|
772
|
-
this.
|
|
773
|
-
|
|
758
|
+
async initializeAsync() {
|
|
759
|
+
var _a;
|
|
760
|
+
try {
|
|
761
|
+
Logger.log('Journium: Starting initialization - fetching fresh remote config...');
|
|
762
|
+
// Step 1: Try to fetch fresh remote config with timeout and retry
|
|
763
|
+
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
764
|
+
if (remoteOptions) {
|
|
765
|
+
// Step 2: Cache the fresh remote config
|
|
766
|
+
this.saveCachedOptions(remoteOptions);
|
|
767
|
+
// Step 3: Merge local options over remote config (local overrides remote)
|
|
768
|
+
if (this.config.options) {
|
|
769
|
+
this.effectiveOptions = mergeOptions(this.config.options, remoteOptions);
|
|
770
|
+
Logger.log('Journium: Using fresh remote config merged with local options:', this.effectiveOptions);
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
this.effectiveOptions = remoteOptions;
|
|
774
|
+
Logger.log('Journium: Using fresh remote config:', this.effectiveOptions);
|
|
775
|
+
}
|
|
774
776
|
}
|
|
775
777
|
else {
|
|
776
|
-
//
|
|
777
|
-
|
|
778
|
-
|
|
778
|
+
// Step 4: Fallback to cached config if fresh fetch failed
|
|
779
|
+
/* const cachedRemoteOptions = this.loadCachedOptions();
|
|
780
|
+
|
|
781
|
+
if (cachedRemoteOptions) {
|
|
782
|
+
if (this.config.options) {
|
|
783
|
+
this.effectiveOptions = mergeOptions(this.config.options, cachedRemoteOptions);
|
|
784
|
+
Logger.log('Journium: Fresh config failed, using cached remote config merged with local options:', this.effectiveOptions);
|
|
785
|
+
} else {
|
|
786
|
+
this.effectiveOptions = cachedRemoteOptions;
|
|
787
|
+
Logger.log('Journium: Fresh config failed, using cached remote config:', this.effectiveOptions);
|
|
788
|
+
}
|
|
789
|
+
} else {
|
|
790
|
+
// Step 5: No remote config and no cached config - initialization fails
|
|
791
|
+
Logger.error('Journium: Initialization failed - no remote config available and no cached config found');
|
|
792
|
+
this.initializationFailed = true;
|
|
793
|
+
this.initializationComplete = false;
|
|
794
|
+
return;
|
|
795
|
+
} */
|
|
779
796
|
}
|
|
797
|
+
// Step 6: Update identity manager session timeout if provided
|
|
798
|
+
if (this.effectiveOptions.sessionTimeout) {
|
|
799
|
+
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
800
|
+
}
|
|
801
|
+
// Step 7: Update Logger debug setting
|
|
802
|
+
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
803
|
+
// Step 8: Mark initialization as complete
|
|
804
|
+
this.initializationComplete = true;
|
|
805
|
+
this.initializationFailed = false;
|
|
806
|
+
// Step 9: Process any staged events
|
|
807
|
+
this.processStagedEvents();
|
|
808
|
+
// Step 10: Start flush timer
|
|
809
|
+
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
810
|
+
this.startFlushTimer();
|
|
811
|
+
}
|
|
812
|
+
Logger.log('Journium: Initialization complete with options:', this.effectiveOptions);
|
|
813
|
+
// Step 11: Notify callbacks about options
|
|
814
|
+
this.notifyOptionsChange();
|
|
780
815
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
786
|
-
this.startFlushTimer();
|
|
787
|
-
}
|
|
788
|
-
Logger.log('Journium: Client initialized with effective options:', this.effectiveOptions);
|
|
789
|
-
}
|
|
790
|
-
async fetchRemoteOptionsAsync() {
|
|
791
|
-
// Fetch fresh config in background
|
|
792
|
-
if (this.config.publishableKey) {
|
|
793
|
-
await this.fetchAndCacheRemoteOptions();
|
|
816
|
+
catch (error) {
|
|
817
|
+
Logger.error('Journium: Initialization failed:', error);
|
|
818
|
+
this.initializationFailed = true;
|
|
819
|
+
this.initializationComplete = false;
|
|
794
820
|
}
|
|
795
821
|
}
|
|
796
|
-
async
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
//
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
822
|
+
async fetchRemoteOptionsWithRetry() {
|
|
823
|
+
const maxRetries = 2;
|
|
824
|
+
const timeoutMs = 15000; // 15 seconds
|
|
825
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
826
|
+
try {
|
|
827
|
+
Logger.log(`Journium: Fetching remote config (attempt ${attempt}/${maxRetries})...`);
|
|
828
|
+
// Create timeout promise
|
|
829
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
830
|
+
setTimeout(() => reject(new Error('Timeout')), timeoutMs);
|
|
831
|
+
});
|
|
832
|
+
// Race fetch against timeout
|
|
833
|
+
const fetchPromise = fetchRemoteOptions(this.config.apiHost, this.config.publishableKey);
|
|
834
|
+
const remoteOptionsResponse = await Promise.race([fetchPromise, timeoutPromise]);
|
|
835
|
+
if (remoteOptionsResponse && remoteOptionsResponse.status === 'success') {
|
|
836
|
+
Logger.log('Journium: Successfully fetched fresh remote config:', remoteOptionsResponse.config);
|
|
837
|
+
return remoteOptionsResponse.config || null;
|
|
808
838
|
}
|
|
809
|
-
else {
|
|
810
|
-
|
|
811
|
-
|
|
839
|
+
else if (remoteOptionsResponse && remoteOptionsResponse.status === 'error' && remoteOptionsResponse.errorCode === 'J_ERR_TENANT_NOT_FOUND') {
|
|
840
|
+
Logger.error('Journium: Invalid publishableKey is being used.');
|
|
841
|
+
return null;
|
|
812
842
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
843
|
+
{
|
|
844
|
+
throw new Error('Remote config fetch unsuccessful');
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
catch (error) {
|
|
848
|
+
Logger.warn(`Journium: Remote config fetch attempt ${attempt} failed:`, error);
|
|
849
|
+
if (attempt === maxRetries) {
|
|
850
|
+
Logger.warn('Journium: All remote config fetch attempts failed, falling back to cached config');
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
// Wait 1 second before retry (except on last attempt)
|
|
854
|
+
if (attempt < maxRetries) {
|
|
855
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
816
856
|
}
|
|
817
|
-
Logger.log('Journium: Background remote options applied:', remoteOptionsResponse.config);
|
|
818
|
-
Logger.log('Journium: New effective options:', this.effectiveOptions);
|
|
819
|
-
// Update Logger debug setting with new options
|
|
820
|
-
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
821
|
-
// Notify all registered callbacks about the options change
|
|
822
|
-
this.notifyOptionsChange();
|
|
823
857
|
}
|
|
824
858
|
}
|
|
825
|
-
|
|
826
|
-
Logger.warn('Journium: Background remote options fetch failed:', error);
|
|
827
|
-
}
|
|
859
|
+
return null;
|
|
828
860
|
}
|
|
829
861
|
/**
|
|
830
862
|
* Register a callback to be notified when effective options change (e.g., when remote options are fetched)
|
|
@@ -846,12 +878,48 @@ class JourniumClient {
|
|
|
846
878
|
}
|
|
847
879
|
});
|
|
848
880
|
}
|
|
881
|
+
processStagedEvents() {
|
|
882
|
+
if (this.stagedEvents.length === 0)
|
|
883
|
+
return;
|
|
884
|
+
Logger.log(`Journium: Processing ${this.stagedEvents.length} staged events`);
|
|
885
|
+
// Move staged events to main queue, adding identity properties now
|
|
886
|
+
const identity = this.identityManager.getIdentity();
|
|
887
|
+
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
888
|
+
for (const stagedEvent of this.stagedEvents) {
|
|
889
|
+
// Add identity properties that weren't available during staging
|
|
890
|
+
const eventWithIdentity = {
|
|
891
|
+
...stagedEvent,
|
|
892
|
+
properties: {
|
|
893
|
+
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
894
|
+
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
895
|
+
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
896
|
+
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
897
|
+
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
898
|
+
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
899
|
+
...userAgentInfo,
|
|
900
|
+
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
901
|
+
$platform: 'web',
|
|
902
|
+
...stagedEvent.properties, // Original properties override system properties
|
|
903
|
+
},
|
|
904
|
+
};
|
|
905
|
+
this.queue.push(eventWithIdentity);
|
|
906
|
+
}
|
|
907
|
+
// Clear staged events
|
|
908
|
+
this.stagedEvents = [];
|
|
909
|
+
Logger.log('Journium: Staged events processed and moved to main queue');
|
|
910
|
+
// Check if we should flush immediately
|
|
911
|
+
if (this.queue.length >= this.effectiveOptions.flushAt) {
|
|
912
|
+
// console.log('1 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
913
|
+
this.flush();
|
|
914
|
+
}
|
|
915
|
+
}
|
|
849
916
|
startFlushTimer() {
|
|
850
917
|
if (this.flushTimer) {
|
|
851
918
|
clearInterval(this.flushTimer);
|
|
852
919
|
}
|
|
853
920
|
// Use universal setInterval (works in both browser and Node.js)
|
|
854
921
|
this.flushTimer = setInterval(() => {
|
|
922
|
+
// console.log('2 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
855
923
|
this.flush();
|
|
856
924
|
}, this.effectiveOptions.flushInterval);
|
|
857
925
|
}
|
|
@@ -880,9 +948,9 @@ class JourniumClient {
|
|
|
880
948
|
}
|
|
881
949
|
}
|
|
882
950
|
identify(distinctId, attributes = {}) {
|
|
883
|
-
// Don't identify if
|
|
884
|
-
if (
|
|
885
|
-
Logger.warn('Journium: identify() call rejected -
|
|
951
|
+
// Don't identify if initialization failed
|
|
952
|
+
if (this.initializationFailed) {
|
|
953
|
+
Logger.warn('Journium: identify() call rejected - initialization failed');
|
|
886
954
|
return;
|
|
887
955
|
}
|
|
888
956
|
// Call identify on identity manager to get previous distinct ID
|
|
@@ -896,9 +964,9 @@ class JourniumClient {
|
|
|
896
964
|
Logger.log('Journium: User identified', { distinctId, attributes, previousDistinctId });
|
|
897
965
|
}
|
|
898
966
|
reset() {
|
|
899
|
-
// Don't reset if
|
|
900
|
-
if (
|
|
901
|
-
Logger.warn('Journium: reset() call rejected -
|
|
967
|
+
// Don't reset if initialization failed
|
|
968
|
+
if (this.initializationFailed) {
|
|
969
|
+
Logger.warn('Journium: reset() call rejected - initialization failed');
|
|
902
970
|
return;
|
|
903
971
|
}
|
|
904
972
|
// Reset identity in identity manager
|
|
@@ -906,42 +974,60 @@ class JourniumClient {
|
|
|
906
974
|
Logger.log('Journium: User identity reset');
|
|
907
975
|
}
|
|
908
976
|
track(event, properties = {}) {
|
|
909
|
-
//
|
|
910
|
-
if (!this.config || !this.config.publishableKey || !this.initialized) {
|
|
911
|
-
Logger.warn('Journium: track() call rejected - SDK not ready');
|
|
912
|
-
return;
|
|
913
|
-
}
|
|
914
|
-
const identity = this.identityManager.getIdentity();
|
|
915
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
916
|
-
// Create standardized event properties
|
|
917
|
-
const eventProperties = {
|
|
918
|
-
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
919
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
920
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
921
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
922
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
923
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
924
|
-
...userAgentInfo,
|
|
925
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
926
|
-
$platform: 'web',
|
|
927
|
-
...properties, // User-provided properties override defaults
|
|
928
|
-
};
|
|
977
|
+
// Create minimal event without identity properties (will be added later if staging)
|
|
929
978
|
const journiumEvent = {
|
|
930
979
|
uuid: generateUuidv7(),
|
|
931
980
|
ingestion_key: this.config.publishableKey,
|
|
932
981
|
client_timestamp: getCurrentTimestamp(),
|
|
933
982
|
event,
|
|
934
|
-
properties:
|
|
983
|
+
properties: { ...properties }, // Only user properties for now
|
|
935
984
|
};
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
985
|
+
// Stage events during initialization, add to queue after initialization
|
|
986
|
+
if (!this.initializationComplete) {
|
|
987
|
+
// If initialization failed, reject events
|
|
988
|
+
if (this.initializationFailed) {
|
|
989
|
+
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
this.stagedEvents.push(journiumEvent);
|
|
993
|
+
Logger.log('Journium: Event staged during initialization', journiumEvent);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
// If initialization failed, reject events
|
|
997
|
+
if (this.initializationFailed) {
|
|
998
|
+
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
// Add identity properties for immediate events (after initialization)
|
|
1002
|
+
const identity = this.identityManager.getIdentity();
|
|
1003
|
+
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
1004
|
+
const eventWithIdentity = {
|
|
1005
|
+
...journiumEvent,
|
|
1006
|
+
properties: {
|
|
1007
|
+
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
1008
|
+
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
1009
|
+
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
1010
|
+
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
1011
|
+
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
1012
|
+
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
1013
|
+
...userAgentInfo,
|
|
1014
|
+
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
1015
|
+
$platform: 'web',
|
|
1016
|
+
...properties, // User-provided properties override system properties
|
|
1017
|
+
},
|
|
1018
|
+
};
|
|
1019
|
+
this.queue.push(eventWithIdentity);
|
|
1020
|
+
Logger.log('Journium: Event tracked', eventWithIdentity);
|
|
1021
|
+
// Only flush if we have effective options (after initialization)
|
|
1022
|
+
if (this.effectiveOptions.flushAt && this.queue.length >= this.effectiveOptions.flushAt) {
|
|
1023
|
+
// console.log('3 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
939
1024
|
this.flush();
|
|
940
1025
|
}
|
|
941
1026
|
}
|
|
942
1027
|
async flush() {
|
|
943
|
-
// Don't flush if
|
|
944
|
-
if (
|
|
1028
|
+
// Don't flush if initialization failed
|
|
1029
|
+
if (this.initializationFailed) {
|
|
1030
|
+
Logger.warn('Journium: flush() call rejected - initialization failed');
|
|
945
1031
|
return;
|
|
946
1032
|
}
|
|
947
1033
|
if (this.queue.length === 0)
|
|
@@ -995,7 +1081,7 @@ class PageviewTracker {
|
|
|
995
1081
|
* Start automatic autocapture for pageviews
|
|
996
1082
|
* @returns void
|
|
997
1083
|
*/
|
|
998
|
-
|
|
1084
|
+
startAutoPageviewTracking() {
|
|
999
1085
|
this.capturePageview();
|
|
1000
1086
|
if (typeof window !== 'undefined') {
|
|
1001
1087
|
// Store original methods for cleanup
|
|
@@ -1424,6 +1510,9 @@ class JourniumAnalytics {
|
|
|
1424
1510
|
this.unsubscribeOptionsChange = this.client.onOptionsChange((effectiveOptions) => {
|
|
1425
1511
|
this.handleOptionsChange(effectiveOptions);
|
|
1426
1512
|
});
|
|
1513
|
+
// Start automatic autocapture immediately if initial options support it
|
|
1514
|
+
// This handles cached remote options or local options with autocapture enabled
|
|
1515
|
+
this.startAutocaptureIfEnabled(initialEffectiveOptions);
|
|
1427
1516
|
}
|
|
1428
1517
|
resolveAutocaptureOptions(autocapture) {
|
|
1429
1518
|
if (autocapture === false) {
|
|
@@ -1454,13 +1543,18 @@ class JourniumAnalytics {
|
|
|
1454
1543
|
startAutocapture() {
|
|
1455
1544
|
// Always check effective options (which may include remote options)
|
|
1456
1545
|
const effectiveOptions = this.client.getEffectiveOptions();
|
|
1457
|
-
|
|
1458
|
-
const
|
|
1546
|
+
// Only enable if effectiveOptions are loaded and autoTrackPageviews is not explicitly false
|
|
1547
|
+
const autoTrackPageviews = effectiveOptions && Object.keys(effectiveOptions).length > 0
|
|
1548
|
+
? effectiveOptions.autoTrackPageviews !== false
|
|
1549
|
+
: false;
|
|
1550
|
+
const autocaptureEnabled = effectiveOptions && Object.keys(effectiveOptions).length > 0
|
|
1551
|
+
? effectiveOptions.autocapture !== false
|
|
1552
|
+
: false;
|
|
1459
1553
|
// Update autocapture tracker options if they've changed
|
|
1460
1554
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1461
1555
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1462
1556
|
if (autoTrackPageviews) {
|
|
1463
|
-
this.pageviewTracker.
|
|
1557
|
+
this.pageviewTracker.startAutoPageviewTracking();
|
|
1464
1558
|
}
|
|
1465
1559
|
if (autocaptureEnabled) {
|
|
1466
1560
|
this.autocaptureTracker.start();
|
|
@@ -1473,30 +1567,60 @@ class JourniumAnalytics {
|
|
|
1473
1567
|
this.autocaptureStarted = false;
|
|
1474
1568
|
}
|
|
1475
1569
|
/**
|
|
1476
|
-
*
|
|
1570
|
+
* Automatically start autocapture if enabled in options
|
|
1571
|
+
* Handles both initial options and empty options during remote-first initialization
|
|
1477
1572
|
*/
|
|
1478
|
-
|
|
1479
|
-
//
|
|
1573
|
+
startAutocaptureIfEnabled(effectiveOptions) {
|
|
1574
|
+
// Skip if autocapture was already started manually
|
|
1480
1575
|
if (this.autocaptureStarted) {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
// During remote-first initialization, effective options might be empty initially
|
|
1579
|
+
// Only auto-start if we have actual options loaded, not empty options
|
|
1580
|
+
const hasActualOptions = effectiveOptions && Object.keys(effectiveOptions).length > 0;
|
|
1581
|
+
if (hasActualOptions) {
|
|
1582
|
+
// Use same logic as manual startAutocapture() but only start automatically
|
|
1486
1583
|
const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
|
|
1487
1584
|
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1488
1585
|
// Update autocapture tracker options
|
|
1489
1586
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1490
1587
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1491
|
-
// Restart only if still enabled
|
|
1492
1588
|
if (autoTrackPageviews) {
|
|
1493
|
-
this.pageviewTracker.
|
|
1589
|
+
this.pageviewTracker.startAutoPageviewTracking();
|
|
1494
1590
|
}
|
|
1495
1591
|
if (autocaptureEnabled) {
|
|
1496
1592
|
this.autocaptureTracker.start();
|
|
1497
1593
|
}
|
|
1498
|
-
|
|
1594
|
+
if (autoTrackPageviews || autocaptureEnabled) {
|
|
1595
|
+
this.autocaptureStarted = true;
|
|
1596
|
+
}
|
|
1499
1597
|
}
|
|
1598
|
+
// If options are empty (during initialization), wait for options change callback
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Handle effective options change (e.g., when remote options are fetched)
|
|
1602
|
+
*/
|
|
1603
|
+
handleOptionsChange(effectiveOptions) {
|
|
1604
|
+
// Stop current autocapture if it was already started
|
|
1605
|
+
if (this.autocaptureStarted) {
|
|
1606
|
+
this.pageviewTracker.stopAutocapture();
|
|
1607
|
+
this.autocaptureTracker.stop();
|
|
1608
|
+
this.autocaptureStarted = false;
|
|
1609
|
+
}
|
|
1610
|
+
// Evaluate if autocapture should be enabled with new options
|
|
1611
|
+
const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
|
|
1612
|
+
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1613
|
+
// Update autocapture tracker options
|
|
1614
|
+
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1615
|
+
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1616
|
+
// Start autocapture based on new options (even if it wasn't started before)
|
|
1617
|
+
if (autoTrackPageviews) {
|
|
1618
|
+
this.pageviewTracker.startAutoPageviewTracking();
|
|
1619
|
+
}
|
|
1620
|
+
if (autocaptureEnabled) {
|
|
1621
|
+
this.autocaptureTracker.start();
|
|
1622
|
+
}
|
|
1623
|
+
this.autocaptureStarted = autoTrackPageviews || autocaptureEnabled;
|
|
1500
1624
|
}
|
|
1501
1625
|
async flush() {
|
|
1502
1626
|
return this.client.flush();
|
|
@@ -1523,24 +1647,20 @@ const init = (config) => {
|
|
|
1523
1647
|
return new JourniumAnalytics(config);
|
|
1524
1648
|
};
|
|
1525
1649
|
|
|
1526
|
-
const JourniumContext = createContext(
|
|
1650
|
+
const JourniumContext = createContext(undefined);
|
|
1527
1651
|
const JourniumProvider = ({ children, config, }) => {
|
|
1528
1652
|
const [analytics, setAnalytics] = useState(null);
|
|
1529
1653
|
const [effectiveOptions, setEffectiveOptions] = useState(null);
|
|
1530
1654
|
useEffect(() => {
|
|
1531
|
-
const analyticsInstance =
|
|
1532
|
-
// Get initial effective options (may
|
|
1655
|
+
const analyticsInstance = init(config);
|
|
1656
|
+
// Get initial effective options (may be empty during remote-first initialization)
|
|
1533
1657
|
const initialEffective = analyticsInstance.getEffectiveOptions();
|
|
1534
1658
|
setEffectiveOptions(initialEffective);
|
|
1535
|
-
//
|
|
1536
|
-
|
|
1537
|
-
if (autocaptureEnabled) {
|
|
1538
|
-
analyticsInstance.startAutocapture();
|
|
1539
|
-
}
|
|
1659
|
+
// Don't start autocapture immediately with potentially empty options
|
|
1660
|
+
// Let the analytics instance handle autocapture after initialization completes
|
|
1540
1661
|
setAnalytics(analyticsInstance);
|
|
1541
1662
|
// Listen for options changes (when remote options are fetched)
|
|
1542
|
-
//
|
|
1543
|
-
// We just need to update the effectiveOptions state for consumers
|
|
1663
|
+
// The JourniumAnalytics will automatically start autocapture when initialization completes
|
|
1544
1664
|
const unsubscribe = analyticsInstance.onOptionsChange((newOptions) => {
|
|
1545
1665
|
setEffectiveOptions(newOptions);
|
|
1546
1666
|
});
|
|
@@ -1616,5 +1736,5 @@ const useAutocapture = () => {
|
|
|
1616
1736
|
return { startAutocapture, stopAutocapture };
|
|
1617
1737
|
};
|
|
1618
1738
|
|
|
1619
|
-
export { AutocaptureTracker, BrowserIdentityManager,
|
|
1739
|
+
export { AutocaptureTracker, BrowserIdentityManager, JourniumClient, JourniumProvider, Logger, PageviewTracker, fetchRemoteOptions, generateId, generateUuidv7, getCurrentTimestamp, getCurrentUrl, getPageTitle, getReferrer, init, isBrowser, isNode, mergeOptions, useAutoTrackPageview, useAutocapture, useIdentify, useJournium, useReset, useTrackEvent, useTrackPageview };
|
|
1620
1740
|
//# sourceMappingURL=index.mjs.map
|