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