@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.
@@ -1 +1 @@
1
- {"version":3,"file":"JourniumAnalytics.d.ts","sourceRoot":"","sources":["../src/JourniumAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAK1F,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,yBAAyB;IAiBjC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxE,KAAK,IAAI,IAAI;IAIb,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D,gBAAgB,IAAI,IAAI;IA4BxB,eAAe,IAAI,IAAI;IAMvB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAkCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA6BrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,mBAAmB;IAInB;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAI9E,OAAO,IAAI,IAAI;CAQhB;AAED,eAAO,MAAM,IAAI,GAAI,QAAQ,cAAc,KAAG,iBAE7C,CAAC;;mBAF2B,cAAc,KAAG,iBAAiB;;AAI/D,wBAAwB"}
1
+ {"version":3,"file":"JourniumAnalytics.d.ts","sourceRoot":"","sources":["../src/JourniumAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAK1F,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,yBAAyB;IAiBjC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxE,KAAK,IAAI,IAAI;IAIb,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D,gBAAgB,IAAI,IAAI;IA4BxB,eAAe,IAAI,IAAI;IAMvB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAkCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+BrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,mBAAmB;IAInB;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAI9E,OAAO,IAAI,IAAI;CAQhB;AAED,eAAO,MAAM,IAAI,GAAI,QAAQ,cAAc,KAAG,iBAE7C,CAAC;;mBAF2B,cAAc,KAAG,iBAAiB;;AAI/D,wBAAwB"}
@@ -1,10 +1,14 @@
1
1
  import { JourniumConfig, JourniumLocalOptions } from '@journium/core';
2
2
  export declare class JourniumClient {
3
+ private static readonly REMOTE_OPTIONS_REFRESH_INTERVAL;
3
4
  private config;
4
5
  private effectiveOptions;
5
6
  private queue;
6
7
  private stagedEvents;
7
8
  private flushTimer;
9
+ private remoteOptionsRefreshTimer;
10
+ private isRefreshing;
11
+ private lastRemoteOptions;
8
12
  private initializationComplete;
9
13
  private initializationFailed;
10
14
  private identityManager;
@@ -22,6 +26,10 @@ export declare class JourniumClient {
22
26
  private notifyOptionsChange;
23
27
  private processStagedEvents;
24
28
  private startFlushTimer;
29
+ private startRemoteOptionsRefreshTimer;
30
+ private refreshRemoteOptions;
31
+ private applyRemoteOptions;
32
+ private buildIdentityProperties;
25
33
  private sendEvents;
26
34
  identify(distinctId: string, attributes?: Record<string, unknown>): void;
27
35
  reset(): void;
@@ -29,5 +37,6 @@ export declare class JourniumClient {
29
37
  flush(): Promise<void>;
30
38
  destroy(): void;
31
39
  getEffectiveOptions(): JourniumLocalOptions;
40
+ private get ingestionPaused();
32
41
  }
33
42
  //# sourceMappingURL=JourniumClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JourniumClient.d.ts","sourceRoot":"","sources":["../src/JourniumClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAyB,oBAAoB,EAAyG,MAAM,gBAAgB,CAAC;AAEnN,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,sBAAsB,CAAkB;IAChD,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,sBAAsB,CAA2D;gBAE7E,MAAM,EAAE,cAAc;IAiClC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,iBAAiB;YAYX,eAAe;YAyEf,2BAA2B;IAiDzC;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAQ9E,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,mBAAmB;IA0C3B,OAAO,CAAC,eAAe;YAYT,UAAU;IA0BxB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAqB5E,KAAK,IAAI,IAAI;IAab,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IA2D9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B,OAAO,IAAI,IAAI;IAQf,mBAAmB,IAAI,oBAAoB;CAG5C"}
1
+ {"version":3,"file":"JourniumClient.d.ts","sourceRoot":"","sources":["../src/JourniumClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAyB,oBAAoB,EAAyG,MAAM,gBAAgB,CAAC;AAEnN,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,+BAA+B,CAAkB;IAEzE,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,yBAAyB,CAA+C;IAChF,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,sBAAsB,CAAkB;IAChD,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,sBAAsB,CAA2D;gBAE7E,MAAM,EAAE,cAAc;IAiClC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,iBAAiB;YAYX,eAAe;YAoCf,2BAA2B;IAiDzC;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAQ9E,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,8BAA8B;YAcxB,oBAAoB;IA6ClC,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,uBAAuB;YAiBjB,UAAU;IA0BxB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAqB5E,KAAK,IAAI,IAAI;IAab,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAsC9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B,OAAO,IAAI,IAAI;IAYf,mBAAmB,IAAI,oBAAoB;IAI3C,OAAO,KAAK,eAAe,GAE1B;CACF"}
@@ -9,9 +9,10 @@ export declare class PageviewTracker {
9
9
  capturePageview(customProperties?: Record<string, unknown>): void;
10
10
  /**
11
11
  * Start automatic autocapture for pageviews
12
- * @returns void
12
+ * @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
13
+ * Pass false when restarting after a remote options update to avoid a spurious pageview.
13
14
  */
14
- startAutoPageviewTracking(): void;
15
+ startAutoPageviewTracking(captureInitialPageview?: boolean): void;
15
16
  /**
16
17
  * Stop automatic autocapture for pageviews
17
18
  * @returns void
@@ -1 +1 @@
1
- {"version":3,"file":"PageviewTracker.d.ts","sourceRoot":"","sources":["../src/PageviewTracker.ts"],"names":[],"mappings":"AACA,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,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAkBrE;;;OAGG;IACH,yBAAyB,IAAI,IAAI;IA0BjC;;;OAGG;IACH,eAAe,IAAI,IAAI;CAmBxB"}
1
+ {"version":3,"file":"PageviewTracker.d.ts","sourceRoot":"","sources":["../src/PageviewTracker.ts"],"names":[],"mappings":"AACA,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,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAkBrE;;;;OAIG;IACH,yBAAyB,CAAC,sBAAsB,GAAE,OAAc,GAAG,IAAI;IA4BvE;;;OAGG;IACH,eAAe,IAAI,IAAI;CAmBxB"}
package/dist/index.cjs CHANGED
@@ -703,6 +703,9 @@ class JourniumClient {
703
703
  this.queue = [];
704
704
  this.stagedEvents = [];
705
705
  this.flushTimer = null;
706
+ this.remoteOptionsRefreshTimer = null;
707
+ this.isRefreshing = false;
708
+ this.lastRemoteOptions = null;
706
709
  this.initializationComplete = false;
707
710
  this.initializationFailed = false;
708
711
  this.optionsChangeCallbacks = new Set();
@@ -756,61 +759,24 @@ class JourniumClient {
756
759
  }
757
760
  }
758
761
  async initializeAsync() {
759
- var _a;
760
762
  try {
761
763
  Logger.log('Journium: Starting initialization - fetching fresh remote config...');
762
- // Step 1: Try to fetch fresh remote config with timeout and retry
763
764
  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
- }
776
- }
777
- else {
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
- } */
796
- }
797
- // Step 6: Update identity manager session timeout if provided
798
- if (this.effectiveOptions.sessionTimeout) {
799
- this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
765
+ if (!remoteOptions) {
766
+ Logger.error('Journium: Initialization failed - no remote config available');
767
+ this.initializationFailed = true;
768
+ return;
800
769
  }
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
770
+ this.applyRemoteOptions(remoteOptions);
771
+ Logger.log('Journium: Effective options after init:', this.effectiveOptions);
804
772
  this.initializationComplete = true;
805
773
  this.initializationFailed = false;
806
- // Step 9: Process any staged events
807
774
  this.processStagedEvents();
808
- // Step 10: Start flush timer
809
775
  if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
810
776
  this.startFlushTimer();
811
777
  }
812
- Logger.log('Journium: Initialization complete with options:', this.effectiveOptions);
813
- // Step 11: Notify callbacks about options
778
+ this.startRemoteOptionsRefreshTimer();
779
+ Logger.log('Journium: Initialization complete');
814
780
  this.notifyOptionsChange();
815
781
  }
816
782
  catch (error) {
@@ -881,35 +847,21 @@ class JourniumClient {
881
847
  processStagedEvents() {
882
848
  if (this.stagedEvents.length === 0)
883
849
  return;
850
+ if (this.ingestionPaused) {
851
+ Logger.warn(`Journium: Ingestion is paused — discarding ${this.stagedEvents.length} staged events`);
852
+ this.stagedEvents = [];
853
+ return;
854
+ }
884
855
  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
856
  for (const stagedEvent of this.stagedEvents) {
889
- // Add identity properties that weren't available during staging
890
- const eventWithIdentity = {
857
+ this.queue.push({
891
858
  ...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);
859
+ properties: this.buildIdentityProperties(stagedEvent.properties),
860
+ });
906
861
  }
907
- // Clear staged events
908
862
  this.stagedEvents = [];
909
863
  Logger.log('Journium: Staged events processed and moved to main queue');
910
- // Check if we should flush immediately
911
864
  if (this.queue.length >= this.effectiveOptions.flushAt) {
912
- // console.log('1 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
913
865
  this.flush();
914
866
  }
915
867
  }
@@ -917,12 +869,88 @@ class JourniumClient {
917
869
  if (this.flushTimer) {
918
870
  clearInterval(this.flushTimer);
919
871
  }
920
- // Use universal setInterval (works in both browser and Node.js)
921
872
  this.flushTimer = setInterval(() => {
922
- // console.log('2 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
923
873
  this.flush();
924
874
  }, this.effectiveOptions.flushInterval);
925
875
  }
876
+ startRemoteOptionsRefreshTimer() {
877
+ // Clear any existing timer to prevent duplicate intervals
878
+ if (this.remoteOptionsRefreshTimer) {
879
+ clearInterval(this.remoteOptionsRefreshTimer);
880
+ this.remoteOptionsRefreshTimer = null;
881
+ }
882
+ this.remoteOptionsRefreshTimer = setInterval(() => {
883
+ this.refreshRemoteOptions();
884
+ }, JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL);
885
+ Logger.log(`Journium: Scheduling remote options refresh every ${JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL}ms`);
886
+ }
887
+ async refreshRemoteOptions() {
888
+ if (this.isRefreshing) {
889
+ Logger.log('Journium: Remote options refresh already in progress, skipping');
890
+ return;
891
+ }
892
+ this.isRefreshing = true;
893
+ Logger.log('Journium: Periodic remote options refresh triggered');
894
+ try {
895
+ const remoteOptions = await this.fetchRemoteOptionsWithRetry();
896
+ if (!remoteOptions) {
897
+ Logger.warn('Journium: Periodic remote options refresh failed, keeping current options');
898
+ return;
899
+ }
900
+ const prevRemoteSnapshot = JSON.stringify(this.lastRemoteOptions);
901
+ const prevFlushInterval = this.effectiveOptions.flushInterval;
902
+ this.applyRemoteOptions(remoteOptions);
903
+ if (prevRemoteSnapshot === JSON.stringify(this.lastRemoteOptions)) {
904
+ Logger.log('Journium: Remote options unchanged after refresh, no update needed');
905
+ return;
906
+ }
907
+ Logger.log('Journium: Remote options updated after refresh:', this.effectiveOptions);
908
+ if (this.effectiveOptions.flushInterval !== prevFlushInterval) {
909
+ if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
910
+ this.startFlushTimer();
911
+ }
912
+ else if (this.flushTimer) {
913
+ clearInterval(this.flushTimer);
914
+ this.flushTimer = null;
915
+ }
916
+ }
917
+ this.notifyOptionsChange();
918
+ }
919
+ catch (error) {
920
+ Logger.error('Journium: Periodic remote options refresh encountered an error:', error);
921
+ }
922
+ finally {
923
+ this.isRefreshing = false;
924
+ }
925
+ }
926
+ applyRemoteOptions(remoteOptions) {
927
+ var _a;
928
+ this.lastRemoteOptions = remoteOptions;
929
+ this.effectiveOptions = this.config.options
930
+ ? mergeOptions(this.config.options, remoteOptions)
931
+ : remoteOptions;
932
+ this.saveCachedOptions(remoteOptions);
933
+ if (this.effectiveOptions.sessionTimeout) {
934
+ this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
935
+ }
936
+ Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
937
+ }
938
+ buildIdentityProperties(userProperties = {}) {
939
+ const identity = this.identityManager.getIdentity();
940
+ const userAgentInfo = this.identityManager.getUserAgentInfo();
941
+ return {
942
+ $device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
943
+ distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
944
+ $session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
945
+ $is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
946
+ $current_url: typeof window !== 'undefined' ? window.location.href : '',
947
+ $pathname: typeof window !== 'undefined' ? window.location.pathname : '',
948
+ ...userAgentInfo,
949
+ $lib_version: '0.1.0', // TODO: Get from package.json
950
+ $platform: 'web',
951
+ ...userProperties,
952
+ };
953
+ }
926
954
  async sendEvents(events) {
927
955
  if (!events.length)
928
956
  return;
@@ -982,9 +1010,7 @@ class JourniumClient {
982
1010
  event,
983
1011
  properties: { ...properties }, // Only user properties for now
984
1012
  };
985
- // Stage events during initialization, add to queue after initialization
986
1013
  if (!this.initializationComplete) {
987
- // If initialization failed, reject events
988
1014
  if (this.initializationFailed) {
989
1015
  Logger.warn('Journium: track() call rejected - initialization failed');
990
1016
  return;
@@ -993,34 +1019,17 @@ class JourniumClient {
993
1019
  Logger.log('Journium: Event staged during initialization', journiumEvent);
994
1020
  return;
995
1021
  }
996
- // If initialization failed, reject events
997
- if (this.initializationFailed) {
998
- Logger.warn('Journium: track() call rejected - initialization failed');
1022
+ if (this.ingestionPaused) {
1023
+ Logger.warn('Journium: Ingestion is paused — event dropped:', journiumEvent.event);
999
1024
  return;
1000
1025
  }
1001
- // Add identity properties for immediate events (after initialization)
1002
- const identity = this.identityManager.getIdentity();
1003
- const userAgentInfo = this.identityManager.getUserAgentInfo();
1004
1026
  const eventWithIdentity = {
1005
1027
  ...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
- },
1028
+ properties: this.buildIdentityProperties(properties),
1018
1029
  };
1019
1030
  this.queue.push(eventWithIdentity);
1020
1031
  Logger.log('Journium: Event tracked', eventWithIdentity);
1021
- // Only flush if we have effective options (after initialization)
1022
1032
  if (this.effectiveOptions.flushAt && this.queue.length >= this.effectiveOptions.flushAt) {
1023
- // console.log('3 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
1024
1033
  this.flush();
1025
1034
  }
1026
1035
  }
@@ -1047,12 +1056,20 @@ class JourniumClient {
1047
1056
  clearInterval(this.flushTimer);
1048
1057
  this.flushTimer = null;
1049
1058
  }
1059
+ if (this.remoteOptionsRefreshTimer) {
1060
+ clearInterval(this.remoteOptionsRefreshTimer);
1061
+ this.remoteOptionsRefreshTimer = null;
1062
+ }
1050
1063
  this.flush();
1051
1064
  }
1052
1065
  getEffectiveOptions() {
1053
1066
  return this.effectiveOptions;
1054
1067
  }
1068
+ get ingestionPaused() {
1069
+ return this.effectiveOptions['ingestionPaused'] === true;
1070
+ }
1055
1071
  }
1072
+ JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL = 15 * 60 * 1000; // 15 minutes
1056
1073
 
1057
1074
  class PageviewTracker {
1058
1075
  constructor(client) {
@@ -1079,10 +1096,13 @@ class PageviewTracker {
1079
1096
  }
1080
1097
  /**
1081
1098
  * Start automatic autocapture for pageviews
1082
- * @returns void
1099
+ * @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
1100
+ * Pass false when restarting after a remote options update to avoid a spurious pageview.
1083
1101
  */
1084
- startAutoPageviewTracking() {
1085
- this.capturePageview();
1102
+ startAutoPageviewTracking(captureInitialPageview = true) {
1103
+ if (captureInitialPageview) {
1104
+ this.capturePageview();
1105
+ }
1086
1106
  if (typeof window !== 'undefined') {
1087
1107
  // Store original methods for cleanup
1088
1108
  this.originalPushState = window.history.pushState;
@@ -1601,21 +1621,22 @@ class JourniumAnalytics {
1601
1621
  * Handle effective options change (e.g., when remote options are fetched)
1602
1622
  */
1603
1623
  handleOptionsChange(effectiveOptions) {
1604
- // Stop current autocapture if it was already started
1624
+ // If autocapture was never started before, this is the initial options application
1625
+ // (async init completed) — treat it like a page load and capture a pageview.
1626
+ // If it was already started, this is a periodic remote options update — only
1627
+ // re-register listeners without emitting a spurious pageview.
1628
+ const isFirstStart = !this.autocaptureStarted;
1605
1629
  if (this.autocaptureStarted) {
1606
1630
  this.pageviewTracker.stopAutocapture();
1607
1631
  this.autocaptureTracker.stop();
1608
1632
  this.autocaptureStarted = false;
1609
1633
  }
1610
- // Evaluate if autocapture should be enabled with new options
1611
1634
  const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
1612
1635
  const autocaptureEnabled = effectiveOptions.autocapture !== false;
1613
- // Update autocapture tracker options
1614
1636
  const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
1615
1637
  this.autocaptureTracker.updateOptions(autocaptureOptions);
1616
- // Start autocapture based on new options (even if it wasn't started before)
1617
1638
  if (autoTrackPageviews) {
1618
- this.pageviewTracker.startAutoPageviewTracking();
1639
+ this.pageviewTracker.startAutoPageviewTracking(isFirstStart);
1619
1640
  }
1620
1641
  if (autocaptureEnabled) {
1621
1642
  this.autocaptureTracker.start();