@journium/js 1.0.1 → 1.0.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/index.cjs CHANGED
@@ -427,7 +427,7 @@ const isNode = () => {
427
427
  var _a;
428
428
  return typeof process !== 'undefined' && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
429
429
  };
430
- const fetchRemoteConfig = async (apiHost, publishableKey, fetchFn) => {
430
+ const fetchRemoteOptions = async (apiHost, publishableKey, fetchFn) => {
431
431
  const endpoint = '/v1/configs';
432
432
  const url = `${apiHost}${endpoint}?ingestion_key=${encodeURIComponent(publishableKey)}`;
433
433
  try {
@@ -449,42 +449,43 @@ const fetchRemoteConfig = async (apiHost, publishableKey, fetchFn) => {
449
449
  },
450
450
  });
451
451
  if (!response.ok) {
452
- throw new Error(`Config fetch failed: ${response.status} ${response.statusText}`);
452
+ throw new Error(`Options fetch failed: ${response.status} ${response.statusText}`);
453
453
  }
454
454
  const data = await response.json();
455
455
  return data;
456
456
  }
457
457
  catch (error) {
458
- console.warn('Failed to fetch remote config:', error);
458
+ console.warn('Failed to fetch remote options:', error);
459
459
  return null;
460
460
  }
461
461
  };
462
- const mergeConfigs = (localConfig, remoteConfig) => {
463
- if (!remoteConfig && !localConfig) {
462
+ const mergeOptions = (localOptions, remoteOptions) => {
463
+ if (!remoteOptions && !localOptions) {
464
464
  return {};
465
465
  }
466
- if (!remoteConfig) {
467
- return localConfig;
466
+ if (!remoteOptions) {
467
+ return localOptions;
468
468
  }
469
- if (!localConfig) {
470
- return remoteConfig;
469
+ if (!localOptions) {
470
+ return remoteOptions;
471
471
  }
472
- // Deep merge local config into remote config
473
- // Local config takes precedence over remote config
474
- const merged = { ...remoteConfig };
472
+ // Deep merge local options into remote options
473
+ // Local options takes precedence over remote options
474
+ const merged = { ...remoteOptions };
475
475
  // Handle primitive values
476
- Object.keys(localConfig).forEach(key => {
477
- if (localConfig[key] !== undefined && localConfig[key] !== null) {
478
- if (typeof localConfig[key] === 'object' && !Array.isArray(localConfig[key])) {
479
- // Deep merge objects - local config overrides remote
476
+ Object.keys(localOptions).forEach(key => {
477
+ const localValue = localOptions[key];
478
+ if (localValue !== undefined && localValue !== null) {
479
+ if (typeof localValue === 'object' && !Array.isArray(localValue)) {
480
+ // Deep merge objects - local options overrides remote
480
481
  merged[key] = {
481
482
  ...(merged[key] || {}),
482
- ...localConfig[key]
483
+ ...localValue
483
484
  };
484
485
  }
485
486
  else {
486
- // Override primitive values and arrays with local config
487
- merged[key] = localConfig[key];
487
+ // Override primitive values and arrays with local options
488
+ merged[key] = localValue;
488
489
  }
489
490
  }
490
491
  });
@@ -588,7 +589,7 @@ class BrowserIdentityManager {
588
589
  };
589
590
  this.saveIdentity();
590
591
  }
591
- identify(distinctId, attributes = {}) {
592
+ identify(distinctId, _attributes = {}) {
592
593
  if (!this.identity)
593
594
  return { previousDistinctId: null };
594
595
  const previousDistinctId = this.identity.distinct_id;
@@ -681,113 +682,113 @@ class JourniumClient {
681
682
  ...config,
682
683
  apiHost: config.apiHost || 'https://events.journium.app'
683
684
  };
684
- // Generate storage key for config caching
685
- this.configStorageKey = `jrnm_${config.publishableKey}_config`;
685
+ // Generate storage key for options caching
686
+ this.optionsStorageKey = `jrnm_${config.publishableKey}_options`;
686
687
  // Generate default values
687
- const defaultConfig = {
688
+ const defaultOptions = {
688
689
  debug: false,
689
690
  flushAt: 20,
690
691
  flushInterval: 10000,
691
692
  sessionTimeout: 30 * 60 * 1000, // 30 minutes
692
693
  };
693
- // Initialize effective config with local config taking precedence over defaults
694
- this.effectiveConfig = { ...defaultConfig };
695
- if (this.config.config) {
696
- this.effectiveConfig = mergeConfigs(this.config.config, defaultConfig);
694
+ // Initialize effective options with local options taking precedence over defaults
695
+ this.effectiveOptions = { ...defaultOptions };
696
+ if (this.config.options) {
697
+ this.effectiveOptions = mergeOptions(defaultOptions, this.config.options);
697
698
  }
698
699
  // Initialize identity manager
699
- this.identityManager = new BrowserIdentityManager(this.effectiveConfig.sessionTimeout, this.config.publishableKey);
700
+ this.identityManager = new BrowserIdentityManager(this.effectiveOptions.sessionTimeout, this.config.publishableKey);
700
701
  // Initialize synchronously with cached config, fetch fresh config in background
701
702
  this.initializeSync();
702
- this.fetchRemoteConfigAsync();
703
+ this.fetchRemoteOptionsAsync();
703
704
  }
704
- loadCachedConfig() {
705
+ loadCachedOptions() {
705
706
  var _a;
706
707
  if (typeof window === 'undefined' || !window.localStorage) {
707
708
  return null;
708
709
  }
709
710
  try {
710
- const cached = window.localStorage.getItem(this.configStorageKey);
711
+ const cached = window.localStorage.getItem(this.optionsStorageKey);
711
712
  return cached ? JSON.parse(cached) : null;
712
713
  }
713
714
  catch (error) {
714
- if ((_a = this.effectiveConfig) === null || _a === void 0 ? void 0 : _a.debug) {
715
+ if ((_a = this.effectiveOptions) === null || _a === void 0 ? void 0 : _a.debug) {
715
716
  console.warn('Journium: Failed to load cached config:', error);
716
717
  }
717
718
  return null;
718
719
  }
719
720
  }
720
- saveCachedConfig(config) {
721
+ saveCachedOptions(options) {
721
722
  var _a;
722
723
  if (typeof window === 'undefined' || !window.localStorage) {
723
724
  return;
724
725
  }
725
726
  try {
726
- window.localStorage.setItem(this.configStorageKey, JSON.stringify(config));
727
+ window.localStorage.setItem(this.optionsStorageKey, JSON.stringify(options));
727
728
  }
728
729
  catch (error) {
729
- if ((_a = this.effectiveConfig) === null || _a === void 0 ? void 0 : _a.debug) {
730
+ if ((_a = this.effectiveOptions) === null || _a === void 0 ? void 0 : _a.debug) {
730
731
  console.warn('Journium: Failed to save config to cache:', error);
731
732
  }
732
733
  }
733
734
  }
734
735
  initializeSync() {
735
- // Step 1: Load cached remote config from localStorage (synchronous)
736
- const cachedRemoteConfig = this.loadCachedConfig();
737
- // Step 2: If no local config provided, use cached remote config
738
- if (!this.config.config && cachedRemoteConfig) {
739
- this.effectiveConfig = mergeConfigs(undefined, cachedRemoteConfig);
740
- if (this.effectiveConfig.debug) {
741
- console.log('Journium: Using cached remote configuration:', cachedRemoteConfig);
736
+ // Step 1: Load cached remote options from localStorage (synchronous)
737
+ const cachedRemoteOptions = this.loadCachedOptions();
738
+ // Step 2: If no local options provided, use cached remote options
739
+ if (!this.config.options && cachedRemoteOptions) {
740
+ this.effectiveOptions = cachedRemoteOptions;
741
+ if (this.effectiveOptions.debug) {
742
+ console.log('Journium: Using cached remote options:', cachedRemoteOptions);
742
743
  }
743
744
  }
744
745
  // Step 3: Mark as initialized immediately - no need to wait for remote fetch
745
746
  this.initialized = true;
746
747
  // Step 4: Start flush timer immediately
747
- if (this.effectiveConfig.flushInterval && this.effectiveConfig.flushInterval > 0) {
748
+ if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
748
749
  this.startFlushTimer();
749
750
  }
750
- if (this.effectiveConfig.debug) {
751
- console.log('Journium: Client initialized with effective config:', this.effectiveConfig);
751
+ if (this.effectiveOptions.debug) {
752
+ console.log('Journium: Client initialized with effective options:', this.effectiveOptions);
752
753
  }
753
754
  }
754
- async fetchRemoteConfigAsync() {
755
+ async fetchRemoteOptionsAsync() {
755
756
  // Fetch fresh config in background
756
757
  if (this.config.publishableKey) {
757
- await this.fetchAndCacheRemoteConfig();
758
+ await this.fetchAndCacheRemoteOptions();
758
759
  }
759
760
  }
760
- async fetchAndCacheRemoteConfig() {
761
+ async fetchAndCacheRemoteOptions() {
761
762
  try {
762
- if (this.effectiveConfig.debug) {
763
+ if (this.effectiveOptions.debug) {
763
764
  console.log('Journium: Fetching remote configuration in background...');
764
765
  }
765
- const remoteConfigResponse = await fetchRemoteConfig(this.config.apiHost, this.config.publishableKey);
766
- if (remoteConfigResponse && remoteConfigResponse.success) {
766
+ const remoteOptionsResponse = await fetchRemoteOptions(this.config.apiHost, this.config.publishableKey);
767
+ if (remoteOptionsResponse && remoteOptionsResponse.success) {
767
768
  // Save remote config to cache for next session
768
- this.saveCachedConfig(remoteConfigResponse.config);
769
- // Update effective config: local config (if provided) overrides fresh remote config
770
- if (!this.config.config) {
771
- // No local config provided, use fresh remote config
772
- this.effectiveConfig = mergeConfigs(undefined, remoteConfigResponse.config);
769
+ this.saveCachedOptions(remoteOptionsResponse.config);
770
+ // Update effective options: local options (if provided) overrides fresh remote options
771
+ if (!this.config.options) {
772
+ // No local options provided, use fresh remote options
773
+ this.effectiveOptions = remoteOptionsResponse.config;
773
774
  }
774
775
  else {
775
- // Local config provided, merge it over fresh remote config
776
- this.effectiveConfig = mergeConfigs(this.config.config, remoteConfigResponse.config);
776
+ // Local options provided, merge it over fresh remote options
777
+ this.effectiveOptions = mergeOptions(remoteOptionsResponse.config, this.config.options);
777
778
  }
778
- // Update session timeout if provided in fresh effective config
779
- if (this.effectiveConfig.sessionTimeout) {
780
- this.identityManager.updateSessionTimeout(this.effectiveConfig.sessionTimeout);
779
+ // Update session timeout if provided in fresh effective options
780
+ if (this.effectiveOptions.sessionTimeout) {
781
+ this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
781
782
  }
782
- if (this.effectiveConfig.debug) {
783
- console.log('Journium: Background remote configuration applied:', remoteConfigResponse.config);
784
- console.log('Journium: New effective configuration:', this.effectiveConfig);
783
+ if (this.effectiveOptions.debug) {
784
+ console.log('Journium: Background remote options applied:', remoteOptionsResponse.config);
785
+ console.log('Journium: New effective options:', this.effectiveOptions);
785
786
  }
786
787
  }
787
788
  }
788
789
  catch (error) {
789
- if (this.effectiveConfig.debug) {
790
- console.warn('Journium: Background remote config fetch failed:', error);
790
+ if (this.effectiveOptions.debug) {
791
+ console.warn('Journium: Background remote options fetch failed:', error);
791
792
  }
792
793
  }
793
794
  }
@@ -798,7 +799,7 @@ class JourniumClient {
798
799
  // Use universal setInterval (works in both browser and Node.js)
799
800
  this.flushTimer = setInterval(() => {
800
801
  this.flush();
801
- }, this.effectiveConfig.flushInterval);
802
+ }, this.effectiveOptions.flushInterval);
802
803
  }
803
804
  async sendEvents(events) {
804
805
  if (!events.length)
@@ -817,12 +818,12 @@ class JourniumClient {
817
818
  if (!response.ok) {
818
819
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
819
820
  }
820
- if (this.effectiveConfig.debug) {
821
+ if (this.effectiveOptions.debug) {
821
822
  console.log('Journium: Successfully sent events', events);
822
823
  }
823
824
  }
824
825
  catch (error) {
825
- if (this.effectiveConfig.debug) {
826
+ if (this.effectiveOptions.debug) {
826
827
  console.error('Journium: Failed to send events', error);
827
828
  }
828
829
  throw error;
@@ -832,7 +833,7 @@ class JourniumClient {
832
833
  var _a;
833
834
  // Don't identify if SDK is not properly configured
834
835
  if (!this.config || !this.config.publishableKey || !this.initialized) {
835
- if ((_a = this.effectiveConfig) === null || _a === void 0 ? void 0 : _a.debug) {
836
+ if ((_a = this.effectiveOptions) === null || _a === void 0 ? void 0 : _a.debug) {
836
837
  console.warn('Journium: identify() call rejected - SDK not ready');
837
838
  }
838
839
  return;
@@ -845,7 +846,7 @@ class JourniumClient {
845
846
  $anon_distinct_id: previousDistinctId,
846
847
  };
847
848
  this.track('$identify', identifyProperties);
848
- if (this.effectiveConfig.debug) {
849
+ if (this.effectiveOptions.debug) {
849
850
  console.log('Journium: User identified', { distinctId, attributes, previousDistinctId });
850
851
  }
851
852
  }
@@ -853,14 +854,14 @@ class JourniumClient {
853
854
  var _a;
854
855
  // Don't reset if SDK is not properly configured
855
856
  if (!this.config || !this.config.publishableKey || !this.initialized) {
856
- if ((_a = this.effectiveConfig) === null || _a === void 0 ? void 0 : _a.debug) {
857
+ if ((_a = this.effectiveOptions) === null || _a === void 0 ? void 0 : _a.debug) {
857
858
  console.warn('Journium: reset() call rejected - SDK not ready');
858
859
  }
859
860
  return;
860
861
  }
861
862
  // Reset identity in identity manager
862
863
  this.identityManager.reset();
863
- if (this.effectiveConfig.debug) {
864
+ if (this.effectiveOptions.debug) {
864
865
  console.log('Journium: User identity reset');
865
866
  }
866
867
  }
@@ -868,7 +869,7 @@ class JourniumClient {
868
869
  var _a;
869
870
  // Don't track if SDK is not properly configured
870
871
  if (!this.config || !this.config.publishableKey || !this.initialized) {
871
- if ((_a = this.effectiveConfig) === null || _a === void 0 ? void 0 : _a.debug) {
872
+ if ((_a = this.effectiveOptions) === null || _a === void 0 ? void 0 : _a.debug) {
872
873
  console.warn('Journium: track() call rejected - SDK not ready');
873
874
  }
874
875
  return;
@@ -896,10 +897,10 @@ class JourniumClient {
896
897
  properties: eventProperties,
897
898
  };
898
899
  this.queue.push(journiumEvent);
899
- if (this.effectiveConfig.debug) {
900
+ if (this.effectiveOptions.debug) {
900
901
  console.log('Journium: Event tracked', journiumEvent);
901
902
  }
902
- if (this.queue.length >= this.effectiveConfig.flushAt) {
903
+ if (this.queue.length >= this.effectiveOptions.flushAt) {
903
904
  this.flush();
904
905
  }
905
906
  }
@@ -927,6 +928,9 @@ class JourniumClient {
927
928
  }
928
929
  this.flush();
929
930
  }
931
+ getEffectiveOptions() {
932
+ return this.effectiveOptions;
933
+ }
930
934
  }
931
935
 
932
936
  class PageviewTracker {
@@ -992,11 +996,11 @@ class PageviewTracker {
992
996
  }
993
997
 
994
998
  class AutocaptureTracker {
995
- constructor(client, config = {}) {
999
+ constructor(client, options = {}) {
996
1000
  this.listeners = new Map();
997
1001
  this.isActive = false;
998
1002
  this.client = client;
999
- this.config = {
1003
+ this.options = {
1000
1004
  captureClicks: true,
1001
1005
  captureFormSubmits: true,
1002
1006
  captureFormChanges: true,
@@ -1004,7 +1008,7 @@ class AutocaptureTracker {
1004
1008
  ignoreClasses: ['journium-ignore'],
1005
1009
  ignoreElements: ['script', 'style', 'noscript'],
1006
1010
  captureContentText: true,
1007
- ...config,
1011
+ ...options,
1008
1012
  };
1009
1013
  }
1010
1014
  start() {
@@ -1012,16 +1016,16 @@ class AutocaptureTracker {
1012
1016
  return;
1013
1017
  }
1014
1018
  this.isActive = true;
1015
- if (this.config.captureClicks) {
1019
+ if (this.options.captureClicks) {
1016
1020
  this.addClickListener();
1017
1021
  }
1018
- if (this.config.captureFormSubmits) {
1022
+ if (this.options.captureFormSubmits) {
1019
1023
  this.addFormSubmitListener();
1020
1024
  }
1021
- if (this.config.captureFormChanges) {
1025
+ if (this.options.captureFormChanges) {
1022
1026
  this.addFormChangeListener();
1023
1027
  }
1024
- if (this.config.captureTextSelection) {
1028
+ if (this.options.captureTextSelection) {
1025
1029
  this.addTextSelectionListener();
1026
1030
  }
1027
1031
  }
@@ -1105,17 +1109,17 @@ class AutocaptureTracker {
1105
1109
  return true;
1106
1110
  }
1107
1111
  // Check if element should be ignored by tag name
1108
- if ((_a = this.config.ignoreElements) === null || _a === void 0 ? void 0 : _a.includes(element.tagName.toLowerCase())) {
1112
+ if ((_a = this.options.ignoreElements) === null || _a === void 0 ? void 0 : _a.includes(element.tagName.toLowerCase())) {
1109
1113
  return true;
1110
1114
  }
1111
1115
  // Check if element has ignore classes
1112
- if ((_b = this.config.ignoreClasses) === null || _b === void 0 ? void 0 : _b.some(cls => element.classList.contains(cls))) {
1116
+ if ((_b = this.options.ignoreClasses) === null || _b === void 0 ? void 0 : _b.some(cls => element.classList.contains(cls))) {
1113
1117
  return true;
1114
1118
  }
1115
1119
  // Check parent elements for ignore classes
1116
1120
  let parent = element.parentElement;
1117
1121
  while (parent) {
1118
- if ((_c = this.config.ignoreClasses) === null || _c === void 0 ? void 0 : _c.some(cls => parent.classList.contains(cls))) {
1122
+ if ((_c = this.options.ignoreClasses) === null || _c === void 0 ? void 0 : _c.some(cls => parent.classList.contains(cls))) {
1119
1123
  return true;
1120
1124
  }
1121
1125
  parent = parent.parentElement;
@@ -1147,7 +1151,7 @@ class AutocaptureTracker {
1147
1151
  }
1148
1152
  });
1149
1153
  // Element content
1150
- if (this.config.captureContentText) {
1154
+ if (this.options.captureContentText) {
1151
1155
  const text = this.getElementText(element);
1152
1156
  if (text) {
1153
1157
  properties.$element_text = text.substring(0, 200); // Limit text length
@@ -1334,18 +1338,18 @@ class AutocaptureTracker {
1334
1338
  }
1335
1339
  }
1336
1340
 
1337
- class Journium {
1341
+ class JourniumAnalytics {
1338
1342
  constructor(config) {
1339
1343
  var _a, _b;
1340
1344
  this.config = config;
1341
1345
  this.client = new JourniumClient(config);
1342
1346
  this.pageviewTracker = new PageviewTracker(this.client);
1343
- const autocaptureConfig = this.resolveAutocaptureConfig((_a = config.config) === null || _a === void 0 ? void 0 : _a.autocapture);
1344
- this.autocaptureTracker = new AutocaptureTracker(this.client, autocaptureConfig);
1347
+ const autocaptureOptions = this.resolveAutocaptureOptions((_a = config.options) === null || _a === void 0 ? void 0 : _a.autocapture);
1348
+ this.autocaptureTracker = new AutocaptureTracker(this.client, autocaptureOptions);
1345
1349
  // Store resolved autocapture state for startAutocapture method
1346
- this.autocaptureEnabled = ((_b = config.config) === null || _b === void 0 ? void 0 : _b.autocapture) !== false;
1350
+ this.autocaptureEnabled = ((_b = config.options) === null || _b === void 0 ? void 0 : _b.autocapture) !== false;
1347
1351
  }
1348
- resolveAutocaptureConfig(autocapture) {
1352
+ resolveAutocaptureOptions(autocapture) {
1349
1353
  if (autocapture === false) {
1350
1354
  return {
1351
1355
  captureClicks: false,
@@ -1372,7 +1376,12 @@ class Journium {
1372
1376
  this.pageviewTracker.capturePageview(properties);
1373
1377
  }
1374
1378
  startAutocapture() {
1375
- this.pageviewTracker.startAutocapture();
1379
+ // Check if automatic pageview tracking is enabled (defaults to true)
1380
+ const effectiveOptions = this.client.getEffectiveOptions();
1381
+ const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
1382
+ if (autoTrackPageviews) {
1383
+ this.pageviewTracker.startAutocapture();
1384
+ }
1376
1385
  if (this.autocaptureEnabled) {
1377
1386
  this.autocaptureTracker.start();
1378
1387
  }
@@ -1384,6 +1393,9 @@ class Journium {
1384
1393
  async flush() {
1385
1394
  return this.client.flush();
1386
1395
  }
1396
+ getEffectiveOptions() {
1397
+ return this.client.getEffectiveOptions();
1398
+ }
1387
1399
  destroy() {
1388
1400
  this.pageviewTracker.stopAutocapture();
1389
1401
  this.autocaptureTracker.stop();
@@ -1391,15 +1403,15 @@ class Journium {
1391
1403
  }
1392
1404
  }
1393
1405
  const init = (config) => {
1394
- return new Journium(config);
1406
+ return new JourniumAnalytics(config);
1395
1407
  };
1396
1408
 
1397
1409
  exports.AutocaptureTracker = AutocaptureTracker;
1398
1410
  exports.BrowserIdentityManager = BrowserIdentityManager;
1399
- exports.Journium = Journium;
1411
+ exports.JourniumAnalytics = JourniumAnalytics;
1400
1412
  exports.JourniumClient = JourniumClient;
1401
1413
  exports.PageviewTracker = PageviewTracker;
1402
- exports.fetchRemoteConfig = fetchRemoteConfig;
1414
+ exports.fetchRemoteOptions = fetchRemoteOptions;
1403
1415
  exports.generateId = generateId;
1404
1416
  exports.generateUuidv7 = generateUuidv7;
1405
1417
  exports.getCurrentTimestamp = getCurrentTimestamp;
@@ -1409,5 +1421,5 @@ exports.getReferrer = getReferrer;
1409
1421
  exports.init = init;
1410
1422
  exports.isBrowser = isBrowser;
1411
1423
  exports.isNode = isNode;
1412
- exports.mergeConfigs = mergeConfigs;
1424
+ exports.mergeOptions = mergeOptions;
1413
1425
  //# sourceMappingURL=index.cjs.map