@loamly/tracker 2.0.1 → 2.1.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.
@@ -26,7 +26,7 @@ var Loamly = (() => {
26
26
  });
27
27
 
28
28
  // src/config.ts
29
- var VERSION = "2.0.1";
29
+ var VERSION = "2.1.0";
30
30
  var DEFAULT_CONFIG = {
31
31
  apiHost: "https://app.loamly.ai",
32
32
  endpoints: {
@@ -1774,16 +1774,32 @@ var Loamly = (() => {
1774
1774
  apiHost: userConfig.apiHost || DEFAULT_CONFIG.apiHost
1775
1775
  };
1776
1776
  debugMode = userConfig.debug ?? false;
1777
+ const features = {
1778
+ scroll: true,
1779
+ time: true,
1780
+ forms: true,
1781
+ spa: true,
1782
+ behavioralML: true,
1783
+ focusBlur: true,
1784
+ agentic: true,
1785
+ eventQueue: true,
1786
+ ping: false,
1787
+ // Opt-in only
1788
+ ...userConfig.features
1789
+ };
1777
1790
  log("Initializing Loamly Tracker v" + VERSION);
1791
+ log("Features:", features);
1778
1792
  visitorId = getVisitorId();
1779
1793
  log("Visitor ID:", visitorId);
1780
1794
  const session = getSessionId();
1781
1795
  sessionId = session.sessionId;
1782
1796
  log("Session ID:", sessionId, session.isNew ? "(new)" : "(existing)");
1783
- eventQueue = new EventQueue(endpoint(DEFAULT_CONFIG.endpoints.behavioral), {
1784
- batchSize: DEFAULT_CONFIG.batchSize,
1785
- batchTimeout: DEFAULT_CONFIG.batchTimeout
1786
- });
1797
+ if (features.eventQueue) {
1798
+ eventQueue = new EventQueue(endpoint(DEFAULT_CONFIG.endpoints.behavioral), {
1799
+ batchSize: DEFAULT_CONFIG.batchSize,
1800
+ batchTimeout: DEFAULT_CONFIG.batchTimeout
1801
+ });
1802
+ }
1787
1803
  navigationTiming = detectNavigationType();
1788
1804
  log("Navigation timing:", navigationTiming);
1789
1805
  aiDetection = detectAIFromReferrer(document.referrer) || detectAIFromUTM(window.location.href);
@@ -1795,21 +1811,27 @@ var Loamly = (() => {
1795
1811
  pageview();
1796
1812
  }
1797
1813
  if (!userConfig.disableBehavioral) {
1798
- setupAdvancedBehavioralTracking();
1814
+ setupAdvancedBehavioralTracking(features);
1815
+ }
1816
+ if (features.behavioralML) {
1817
+ behavioralClassifier = new BehavioralClassifier(1e4);
1818
+ behavioralClassifier.setOnClassify(handleBehavioralClassification);
1819
+ setupBehavioralMLTracking();
1820
+ }
1821
+ if (features.focusBlur) {
1822
+ focusBlurAnalyzer = new FocusBlurAnalyzer();
1823
+ focusBlurAnalyzer.initTracking();
1824
+ setTimeout(() => {
1825
+ if (focusBlurAnalyzer) {
1826
+ handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
1827
+ }
1828
+ }, 5e3);
1799
1829
  }
1800
- behavioralClassifier = new BehavioralClassifier(1e4);
1801
- behavioralClassifier.setOnClassify(handleBehavioralClassification);
1802
- setupBehavioralMLTracking();
1803
- focusBlurAnalyzer = new FocusBlurAnalyzer();
1804
- focusBlurAnalyzer.initTracking();
1805
- setTimeout(() => {
1806
- if (focusBlurAnalyzer) {
1807
- handleFocusBlurAnalysis(focusBlurAnalyzer.analyze());
1808
- }
1809
- }, 5e3);
1810
- agenticAnalyzer = new AgenticBrowserAnalyzer();
1811
- agenticAnalyzer.init();
1812
- if (visitorId && sessionId) {
1830
+ if (features.agentic) {
1831
+ agenticAnalyzer = new AgenticBrowserAnalyzer();
1832
+ agenticAnalyzer.init();
1833
+ }
1834
+ if (features.ping && visitorId && sessionId) {
1813
1835
  pingService = new PingService(sessionId, visitorId, VERSION, {
1814
1836
  interval: DEFAULT_CONFIG.pingInterval,
1815
1837
  endpoint: endpoint(DEFAULT_CONFIG.endpoints.ping)
@@ -1821,50 +1843,66 @@ var Loamly = (() => {
1821
1843
  });
1822
1844
  spaRouter.start();
1823
1845
  setupUnloadHandlers();
1846
+ reportHealth("initialized");
1824
1847
  log("Initialization complete");
1825
1848
  }
1826
- function setupAdvancedBehavioralTracking() {
1827
- scrollTracker = new ScrollTracker({
1828
- chunks: [30, 60, 90, 100],
1829
- onChunkReached: (event) => {
1830
- log("Scroll chunk:", event.chunk);
1831
- queueEvent("scroll_depth", {
1832
- depth: event.depth,
1833
- chunk: event.chunk,
1834
- time_to_reach_ms: event.time_to_reach_ms
1835
- });
1836
- }
1837
- });
1838
- scrollTracker.start();
1839
- timeTracker = new TimeTracker({
1840
- updateIntervalMs: 1e4,
1841
- // Report every 10 seconds
1842
- onUpdate: (event) => {
1843
- if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
1844
- queueEvent("time_spent", {
1845
- active_time_ms: event.active_time_ms,
1846
- total_time_ms: event.total_time_ms,
1847
- idle_time_ms: event.idle_time_ms,
1848
- is_engaged: event.is_engaged
1849
+ function setupAdvancedBehavioralTracking(features) {
1850
+ if (features.scroll) {
1851
+ scrollTracker = new ScrollTracker({
1852
+ chunks: [30, 60, 90, 100],
1853
+ onChunkReached: (event) => {
1854
+ log("Scroll chunk:", event.chunk);
1855
+ queueEvent("scroll_depth", {
1856
+ depth: event.depth,
1857
+ chunk: event.chunk,
1858
+ time_to_reach_ms: event.time_to_reach_ms
1849
1859
  });
1850
1860
  }
1851
- }
1852
- });
1853
- timeTracker.start();
1854
- formTracker = new FormTracker({
1855
- onFormEvent: (event) => {
1856
- log("Form event:", event.event_type, event.form_id);
1857
- queueEvent(event.event_type, {
1858
- form_id: event.form_id,
1859
- form_type: event.form_type,
1860
- field_name: event.field_name,
1861
- field_type: event.field_type,
1862
- time_to_submit_ms: event.time_to_submit_ms,
1863
- is_conversion: event.is_conversion
1864
- });
1865
- }
1866
- });
1867
- formTracker.start();
1861
+ });
1862
+ scrollTracker.start();
1863
+ }
1864
+ if (features.time) {
1865
+ timeTracker = new TimeTracker({
1866
+ updateIntervalMs: 1e4,
1867
+ // Report every 10 seconds
1868
+ onUpdate: (event) => {
1869
+ if (event.active_time_ms >= DEFAULT_CONFIG.timeSpentThresholdMs) {
1870
+ queueEvent("time_spent", {
1871
+ active_time_ms: event.active_time_ms,
1872
+ total_time_ms: event.total_time_ms,
1873
+ idle_time_ms: event.idle_time_ms,
1874
+ is_engaged: event.is_engaged
1875
+ });
1876
+ }
1877
+ }
1878
+ });
1879
+ timeTracker.start();
1880
+ }
1881
+ if (features.forms) {
1882
+ formTracker = new FormTracker({
1883
+ onFormEvent: (event) => {
1884
+ log("Form event:", event.event_type, event.form_id);
1885
+ queueEvent(event.event_type, {
1886
+ form_id: event.form_id,
1887
+ form_type: event.form_type,
1888
+ field_name: event.field_name,
1889
+ field_type: event.field_type,
1890
+ time_to_submit_ms: event.time_to_submit_ms,
1891
+ is_conversion: event.is_conversion
1892
+ });
1893
+ }
1894
+ });
1895
+ formTracker.start();
1896
+ }
1897
+ if (features.spa) {
1898
+ spaRouter = new SPARouter({
1899
+ onNavigate: (event) => {
1900
+ log("SPA navigation:", event.navigation_type);
1901
+ pageview(event.to_url);
1902
+ }
1903
+ });
1904
+ spaRouter.start();
1905
+ }
1868
1906
  document.addEventListener("click", (e) => {
1869
1907
  const target = e.target;
1870
1908
  const link = target.closest("a");
@@ -2166,6 +2204,39 @@ var Loamly = (() => {
2166
2204
  function isTrackerInitialized() {
2167
2205
  return initialized;
2168
2206
  }
2207
+ function reportHealth(status, errorMessage) {
2208
+ if (!config.apiKey) return;
2209
+ try {
2210
+ const healthData = {
2211
+ workspace_id: config.apiKey,
2212
+ status,
2213
+ error_message: errorMessage || null,
2214
+ version: VERSION,
2215
+ url: typeof window !== "undefined" ? window.location.href : null,
2216
+ user_agent: typeof navigator !== "undefined" ? navigator.userAgent : null,
2217
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2218
+ features: {
2219
+ scroll_tracker: !!scrollTracker,
2220
+ time_tracker: !!timeTracker,
2221
+ form_tracker: !!formTracker,
2222
+ spa_router: !!spaRouter,
2223
+ behavioral_ml: !!behavioralClassifier,
2224
+ focus_blur: !!focusBlurAnalyzer,
2225
+ agentic: !!agenticAnalyzer,
2226
+ ping_service: !!pingService,
2227
+ event_queue: !!eventQueue
2228
+ }
2229
+ };
2230
+ safeFetch(endpoint(DEFAULT_CONFIG.endpoints.health), {
2231
+ method: "POST",
2232
+ headers: { "Content-Type": "application/json" },
2233
+ body: JSON.stringify(healthData)
2234
+ }).catch(() => {
2235
+ });
2236
+ log("Health reported:", status);
2237
+ } catch {
2238
+ }
2239
+ }
2169
2240
  function reset() {
2170
2241
  log("Resetting tracker");
2171
2242
  pingService?.stop();
@@ -2215,7 +2286,8 @@ var Loamly = (() => {
2215
2286
  getAgentic: getAgenticResult,
2216
2287
  isInitialized: isTrackerInitialized,
2217
2288
  reset,
2218
- debug: setDebug
2289
+ debug: setDebug,
2290
+ reportHealth
2219
2291
  };
2220
2292
 
2221
2293
  // src/browser.ts