krisspy-sdk 0.8.2 → 0.9.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/index.d.mts CHANGED
@@ -760,10 +760,20 @@ declare class KrisspyRealtime {
760
760
  * to the analytics ingest endpoint. Works with SPAs (intercepts pushState).
761
761
  * Browser-only module - safely no-ops in React Native / Node.js.
762
762
  *
763
+ * Supports two backends:
764
+ * - Krisspy internal analytics (default, via /api/v1/analytics/events)
765
+ * - OpenPanel (when openpanelClientId is provided, uses @openpanel/web SDK)
766
+ *
763
767
  * @example
764
768
  * const krisspy = createClient({ backendId: '...', apiKey: '...' })
765
769
  * krisspy.analytics.init({ autoTrackPageViews: true })
766
770
  * krisspy.analytics.track('button_click', { label: 'signup' })
771
+ *
772
+ * // With OpenPanel:
773
+ * krisspy.analytics.init({
774
+ * openpanelClientId: '049c50ff-...',
775
+ * openpanelApiUrl: 'https://api-openpanel.krisspy.ai',
776
+ * })
767
777
  */
768
778
 
769
779
  interface AnalyticsInitOptions {
@@ -775,6 +785,23 @@ interface AnalyticsInitOptions {
775
785
  flushInterval?: number;
776
786
  /** Enable debug logging (default: false) */
777
787
  debug?: boolean;
788
+ /** OpenPanel client ID (UUID). When set, events are sent to OpenPanel instead of Krisspy. */
789
+ openpanelClientId?: string;
790
+ /** OpenPanel API URL for self-hosted instances (default: https://api-openpanel.krisspy.ai) */
791
+ openpanelApiUrl?: string;
792
+ /** Track outgoing links (OpenPanel, default: true) */
793
+ trackOutgoingLinks?: boolean;
794
+ /** Track elements with data-track attributes (OpenPanel, default: true) */
795
+ trackAttributes?: boolean;
796
+ /** Track hash changes in URL (OpenPanel, default: false) */
797
+ trackHashChanges?: boolean;
798
+ /** Disable tracking entirely (OpenPanel, default: false) */
799
+ disabled?: boolean;
800
+ /** Filter function — return false to drop an event before sending */
801
+ filter?: (event: {
802
+ name: string;
803
+ properties?: Record<string, any>;
804
+ }) => boolean;
778
805
  }
779
806
  interface AnalyticsEvent {
780
807
  eventName: string;
@@ -796,6 +823,9 @@ declare class KrisspyAnalytics {
796
823
  private originalPushState;
797
824
  private popstateHandler;
798
825
  private unloadHandler;
826
+ /** OpenPanel SDK instance (loaded dynamically when openpanelClientId is set) */
827
+ private openpanel;
828
+ private useOpenPanel;
799
829
  constructor(http: HttpClient, backendId: string);
800
830
  /**
801
831
  * Initialize analytics tracking
@@ -810,6 +840,51 @@ declare class KrisspyAnalytics {
810
840
  * Identify a user (attach userId + traits to all future events)
811
841
  */
812
842
  identify(userId: string, traits?: Record<string, any>): void;
843
+ /**
844
+ * Set properties that will be sent with every event
845
+ */
846
+ setGlobalProperties(props: Record<string, any>): void;
847
+ /**
848
+ * Increment a numeric property on a user profile
849
+ */
850
+ increment(profileId: string, property: string, value?: number): void;
851
+ /**
852
+ * Decrement a numeric property on a user profile
853
+ */
854
+ decrement(profileId: string, property: string, value?: number): void;
855
+ /**
856
+ * Create or update a group entity (company, team, etc.)
857
+ */
858
+ upsertGroup(group: {
859
+ id: string;
860
+ type: string;
861
+ name: string;
862
+ properties?: Record<string, any>;
863
+ }): void;
864
+ /**
865
+ * Link the current user to a group — tags all future events
866
+ */
867
+ setGroup(groupId: string): void;
868
+ /**
869
+ * Track a revenue event
870
+ */
871
+ revenue(amount: number, properties?: Record<string, any>): Promise<void>;
872
+ /**
873
+ * Queue a pending revenue event (call flushRevenue() to send)
874
+ */
875
+ pendingRevenue(amount: number, properties?: Record<string, any>): void;
876
+ /**
877
+ * Flush all pending revenue events
878
+ */
879
+ flushRevenue(): Promise<void>;
880
+ /**
881
+ * Clear pending revenue
882
+ */
883
+ clearRevenue(): void;
884
+ /**
885
+ * Clear current user data (including groups)
886
+ */
887
+ clear(): void;
813
888
  /**
814
889
  * Flush event queue to the server (async)
815
890
  */
@@ -825,6 +900,12 @@ declare class KrisspyAnalytics {
825
900
  private getOrCreateSessionId;
826
901
  private getIngestUrl;
827
902
  private setupNavigationTracking;
903
+ /**
904
+ * Initialize OpenPanel SDK dynamically.
905
+ * Loads @openpanel/web at runtime (must be installed by the user).
906
+ * Falls back gracefully if not available.
907
+ */
908
+ private initOpenPanel;
828
909
  }
829
910
 
830
911
  /**
package/dist/index.d.ts CHANGED
@@ -760,10 +760,20 @@ declare class KrisspyRealtime {
760
760
  * to the analytics ingest endpoint. Works with SPAs (intercepts pushState).
761
761
  * Browser-only module - safely no-ops in React Native / Node.js.
762
762
  *
763
+ * Supports two backends:
764
+ * - Krisspy internal analytics (default, via /api/v1/analytics/events)
765
+ * - OpenPanel (when openpanelClientId is provided, uses @openpanel/web SDK)
766
+ *
763
767
  * @example
764
768
  * const krisspy = createClient({ backendId: '...', apiKey: '...' })
765
769
  * krisspy.analytics.init({ autoTrackPageViews: true })
766
770
  * krisspy.analytics.track('button_click', { label: 'signup' })
771
+ *
772
+ * // With OpenPanel:
773
+ * krisspy.analytics.init({
774
+ * openpanelClientId: '049c50ff-...',
775
+ * openpanelApiUrl: 'https://api-openpanel.krisspy.ai',
776
+ * })
767
777
  */
768
778
 
769
779
  interface AnalyticsInitOptions {
@@ -775,6 +785,23 @@ interface AnalyticsInitOptions {
775
785
  flushInterval?: number;
776
786
  /** Enable debug logging (default: false) */
777
787
  debug?: boolean;
788
+ /** OpenPanel client ID (UUID). When set, events are sent to OpenPanel instead of Krisspy. */
789
+ openpanelClientId?: string;
790
+ /** OpenPanel API URL for self-hosted instances (default: https://api-openpanel.krisspy.ai) */
791
+ openpanelApiUrl?: string;
792
+ /** Track outgoing links (OpenPanel, default: true) */
793
+ trackOutgoingLinks?: boolean;
794
+ /** Track elements with data-track attributes (OpenPanel, default: true) */
795
+ trackAttributes?: boolean;
796
+ /** Track hash changes in URL (OpenPanel, default: false) */
797
+ trackHashChanges?: boolean;
798
+ /** Disable tracking entirely (OpenPanel, default: false) */
799
+ disabled?: boolean;
800
+ /** Filter function — return false to drop an event before sending */
801
+ filter?: (event: {
802
+ name: string;
803
+ properties?: Record<string, any>;
804
+ }) => boolean;
778
805
  }
779
806
  interface AnalyticsEvent {
780
807
  eventName: string;
@@ -796,6 +823,9 @@ declare class KrisspyAnalytics {
796
823
  private originalPushState;
797
824
  private popstateHandler;
798
825
  private unloadHandler;
826
+ /** OpenPanel SDK instance (loaded dynamically when openpanelClientId is set) */
827
+ private openpanel;
828
+ private useOpenPanel;
799
829
  constructor(http: HttpClient, backendId: string);
800
830
  /**
801
831
  * Initialize analytics tracking
@@ -810,6 +840,51 @@ declare class KrisspyAnalytics {
810
840
  * Identify a user (attach userId + traits to all future events)
811
841
  */
812
842
  identify(userId: string, traits?: Record<string, any>): void;
843
+ /**
844
+ * Set properties that will be sent with every event
845
+ */
846
+ setGlobalProperties(props: Record<string, any>): void;
847
+ /**
848
+ * Increment a numeric property on a user profile
849
+ */
850
+ increment(profileId: string, property: string, value?: number): void;
851
+ /**
852
+ * Decrement a numeric property on a user profile
853
+ */
854
+ decrement(profileId: string, property: string, value?: number): void;
855
+ /**
856
+ * Create or update a group entity (company, team, etc.)
857
+ */
858
+ upsertGroup(group: {
859
+ id: string;
860
+ type: string;
861
+ name: string;
862
+ properties?: Record<string, any>;
863
+ }): void;
864
+ /**
865
+ * Link the current user to a group — tags all future events
866
+ */
867
+ setGroup(groupId: string): void;
868
+ /**
869
+ * Track a revenue event
870
+ */
871
+ revenue(amount: number, properties?: Record<string, any>): Promise<void>;
872
+ /**
873
+ * Queue a pending revenue event (call flushRevenue() to send)
874
+ */
875
+ pendingRevenue(amount: number, properties?: Record<string, any>): void;
876
+ /**
877
+ * Flush all pending revenue events
878
+ */
879
+ flushRevenue(): Promise<void>;
880
+ /**
881
+ * Clear pending revenue
882
+ */
883
+ clearRevenue(): void;
884
+ /**
885
+ * Clear current user data (including groups)
886
+ */
887
+ clear(): void;
813
888
  /**
814
889
  * Flush event queue to the server (async)
815
890
  */
@@ -825,6 +900,12 @@ declare class KrisspyAnalytics {
825
900
  private getOrCreateSessionId;
826
901
  private getIngestUrl;
827
902
  private setupNavigationTracking;
903
+ /**
904
+ * Initialize OpenPanel SDK dynamically.
905
+ * Loads @openpanel/web at runtime (must be installed by the user).
906
+ * Falls back gracefully if not available.
907
+ */
908
+ private initOpenPanel;
828
909
  }
829
910
 
830
911
  /**
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
8
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
11
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
12
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -32,6 +34,14 @@ var __copyProps = (to, from, except, desc) => {
32
34
  }
33
35
  return to;
34
36
  };
37
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
+ // If the importer is in node compatibility mode or this is not an ESM
39
+ // file that has been converted to a CommonJS file using a Babel-
40
+ // compatible transform (i.e. "__esModule" has not been set), then set
41
+ // "default" to the CommonJS "module.exports" for node compatibility.
42
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
+ mod
44
+ ));
35
45
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
46
 
37
47
  // src/index.ts
@@ -1307,6 +1317,9 @@ var KrisspyAnalytics = class {
1307
1317
  this.originalPushState = null;
1308
1318
  this.popstateHandler = null;
1309
1319
  this.unloadHandler = null;
1320
+ /** OpenPanel SDK instance (loaded dynamically when openpanelClientId is set) */
1321
+ this.openpanel = null;
1322
+ this.useOpenPanel = false;
1310
1323
  this.http = http;
1311
1324
  this.backendId = backendId;
1312
1325
  }
@@ -1323,6 +1336,12 @@ var KrisspyAnalytics = class {
1323
1336
  flushInterval: 5e3,
1324
1337
  debug: false
1325
1338
  }, options);
1339
+ if (this.options.openpanelClientId) {
1340
+ this.useOpenPanel = true;
1341
+ this.initialized = true;
1342
+ this.initOpenPanel();
1343
+ return;
1344
+ }
1326
1345
  this.sessionId = this.getOrCreateSessionId();
1327
1346
  this.initialized = true;
1328
1347
  if (this.options.autoTrackPageViews) {
@@ -1339,7 +1358,7 @@ var KrisspyAnalytics = class {
1339
1358
  window.addEventListener("beforeunload", this.unloadHandler);
1340
1359
  this.flushTimer = setInterval(() => this.flush(), this.options.flushInterval);
1341
1360
  if (this.options.debug) {
1342
- console.log("[Krisspy Analytics] Initialized", { backendId: this.backendId, sessionId: this.sessionId });
1361
+ console.log("[Krisspy Analytics] Initialized (internal)", { backendId: this.backendId, sessionId: this.sessionId });
1343
1362
  }
1344
1363
  }
1345
1364
  /**
@@ -1347,6 +1366,13 @@ var KrisspyAnalytics = class {
1347
1366
  */
1348
1367
  track(eventName, properties) {
1349
1368
  if (!this.initialized) return;
1369
+ if (this.useOpenPanel && this.openpanel) {
1370
+ this.openpanel.track(eventName, properties);
1371
+ if (this.options.debug) {
1372
+ console.log("[Krisspy Analytics \u2192 OpenPanel] Tracked:", eventName, properties);
1373
+ }
1374
+ return;
1375
+ }
1350
1376
  const event = {
1351
1377
  eventName,
1352
1378
  sessionId: this.sessionId,
@@ -1365,10 +1391,100 @@ var KrisspyAnalytics = class {
1365
1391
  identify(userId, traits) {
1366
1392
  this.userId = userId;
1367
1393
  this.userTraits = traits || {};
1394
+ if (this.useOpenPanel && this.openpanel) {
1395
+ this.openpanel.identify(__spreadValues({ profileId: userId }, traits));
1396
+ if (this.options.debug) {
1397
+ console.log("[Krisspy Analytics \u2192 OpenPanel] Identified:", userId, traits);
1398
+ }
1399
+ return;
1400
+ }
1368
1401
  if (this.initialized) {
1369
1402
  this.track("identify", __spreadValues({ userId }, traits));
1370
1403
  }
1371
1404
  }
1405
+ // ── OpenPanel-specific methods (no-op when using internal analytics) ──
1406
+ /**
1407
+ * Set properties that will be sent with every event
1408
+ */
1409
+ setGlobalProperties(props) {
1410
+ if (this.useOpenPanel && this.openpanel) {
1411
+ this.openpanel.setGlobalProperties(props);
1412
+ }
1413
+ }
1414
+ /**
1415
+ * Increment a numeric property on a user profile
1416
+ */
1417
+ increment(profileId, property, value) {
1418
+ if (this.useOpenPanel && this.openpanel) {
1419
+ this.openpanel.increment({ profileId, property, value });
1420
+ }
1421
+ }
1422
+ /**
1423
+ * Decrement a numeric property on a user profile
1424
+ */
1425
+ decrement(profileId, property, value) {
1426
+ if (this.useOpenPanel && this.openpanel) {
1427
+ this.openpanel.decrement({ profileId, property, value });
1428
+ }
1429
+ }
1430
+ /**
1431
+ * Create or update a group entity (company, team, etc.)
1432
+ */
1433
+ upsertGroup(group) {
1434
+ if (this.useOpenPanel && this.openpanel) {
1435
+ this.openpanel.upsertGroup(group);
1436
+ }
1437
+ }
1438
+ /**
1439
+ * Link the current user to a group — tags all future events
1440
+ */
1441
+ setGroup(groupId) {
1442
+ if (this.useOpenPanel && this.openpanel) {
1443
+ this.openpanel.setGroup(groupId);
1444
+ }
1445
+ }
1446
+ /**
1447
+ * Track a revenue event
1448
+ */
1449
+ async revenue(amount, properties) {
1450
+ if (this.useOpenPanel && this.openpanel) {
1451
+ await this.openpanel.revenue(amount, properties);
1452
+ }
1453
+ }
1454
+ /**
1455
+ * Queue a pending revenue event (call flushRevenue() to send)
1456
+ */
1457
+ pendingRevenue(amount, properties) {
1458
+ if (this.useOpenPanel && this.openpanel) {
1459
+ this.openpanel.pendingRevenue(amount, properties);
1460
+ }
1461
+ }
1462
+ /**
1463
+ * Flush all pending revenue events
1464
+ */
1465
+ async flushRevenue() {
1466
+ if (this.useOpenPanel && this.openpanel) {
1467
+ await this.openpanel.flushRevenue();
1468
+ }
1469
+ }
1470
+ /**
1471
+ * Clear pending revenue
1472
+ */
1473
+ clearRevenue() {
1474
+ if (this.useOpenPanel && this.openpanel) {
1475
+ this.openpanel.clearRevenue();
1476
+ }
1477
+ }
1478
+ /**
1479
+ * Clear current user data (including groups)
1480
+ */
1481
+ clear() {
1482
+ this.userId = null;
1483
+ this.userTraits = {};
1484
+ if (this.useOpenPanel && this.openpanel) {
1485
+ this.openpanel.clear();
1486
+ }
1487
+ }
1372
1488
  /**
1373
1489
  * Flush event queue to the server (async)
1374
1490
  */
@@ -1470,6 +1586,46 @@ var KrisspyAnalytics = class {
1470
1586
  };
1471
1587
  window.addEventListener("popstate", this.popstateHandler);
1472
1588
  }
1589
+ /**
1590
+ * Initialize OpenPanel SDK dynamically.
1591
+ * Loads @openpanel/web at runtime (must be installed by the user).
1592
+ * Falls back gracefully if not available.
1593
+ */
1594
+ async initOpenPanel() {
1595
+ const clientId = this.options.openpanelClientId;
1596
+ const apiUrl = this.options.openpanelApiUrl || "https://api-openpanel.krisspy.ai";
1597
+ try {
1598
+ const { OpenPanel } = await import("@openpanel/web");
1599
+ this.openpanel = new OpenPanel({
1600
+ clientId,
1601
+ apiUrl,
1602
+ trackScreenViews: this.options.autoTrackPageViews !== false,
1603
+ trackOutgoingLinks: this.options.trackOutgoingLinks !== false,
1604
+ trackAttributes: this.options.trackAttributes !== false,
1605
+ trackHashChanges: this.options.trackHashChanges,
1606
+ disabled: this.options.disabled,
1607
+ filter: this.options.filter
1608
+ });
1609
+ if (this.options.debug) {
1610
+ console.log("[Krisspy Analytics \u2192 OpenPanel] Initialized", { clientId, apiUrl });
1611
+ }
1612
+ } catch (err) {
1613
+ console.warn(
1614
+ "[Krisspy Analytics] @openpanel/web not found. Install it with: npm install @openpanel/web\nFalling back to internal analytics."
1615
+ );
1616
+ this.useOpenPanel = false;
1617
+ this.openpanel = null;
1618
+ this.sessionId = this.getOrCreateSessionId();
1619
+ if (this.options.autoTrackPageViews) {
1620
+ this.track("session_start", {});
1621
+ this.track("page_view", { url: window.location.href, referrer: document.referrer });
1622
+ }
1623
+ if (this.options.autoTrackNavigation) {
1624
+ this.setupNavigationTracking();
1625
+ }
1626
+ this.flushTimer = setInterval(() => this.flush(), this.options.flushInterval);
1627
+ }
1628
+ }
1473
1629
  };
1474
1630
 
1475
1631
  // src/notifications.ts
package/dist/index.mjs CHANGED
@@ -1272,6 +1272,9 @@ var KrisspyAnalytics = class {
1272
1272
  this.originalPushState = null;
1273
1273
  this.popstateHandler = null;
1274
1274
  this.unloadHandler = null;
1275
+ /** OpenPanel SDK instance (loaded dynamically when openpanelClientId is set) */
1276
+ this.openpanel = null;
1277
+ this.useOpenPanel = false;
1275
1278
  this.http = http;
1276
1279
  this.backendId = backendId;
1277
1280
  }
@@ -1288,6 +1291,12 @@ var KrisspyAnalytics = class {
1288
1291
  flushInterval: 5e3,
1289
1292
  debug: false
1290
1293
  }, options);
1294
+ if (this.options.openpanelClientId) {
1295
+ this.useOpenPanel = true;
1296
+ this.initialized = true;
1297
+ this.initOpenPanel();
1298
+ return;
1299
+ }
1291
1300
  this.sessionId = this.getOrCreateSessionId();
1292
1301
  this.initialized = true;
1293
1302
  if (this.options.autoTrackPageViews) {
@@ -1304,7 +1313,7 @@ var KrisspyAnalytics = class {
1304
1313
  window.addEventListener("beforeunload", this.unloadHandler);
1305
1314
  this.flushTimer = setInterval(() => this.flush(), this.options.flushInterval);
1306
1315
  if (this.options.debug) {
1307
- console.log("[Krisspy Analytics] Initialized", { backendId: this.backendId, sessionId: this.sessionId });
1316
+ console.log("[Krisspy Analytics] Initialized (internal)", { backendId: this.backendId, sessionId: this.sessionId });
1308
1317
  }
1309
1318
  }
1310
1319
  /**
@@ -1312,6 +1321,13 @@ var KrisspyAnalytics = class {
1312
1321
  */
1313
1322
  track(eventName, properties) {
1314
1323
  if (!this.initialized) return;
1324
+ if (this.useOpenPanel && this.openpanel) {
1325
+ this.openpanel.track(eventName, properties);
1326
+ if (this.options.debug) {
1327
+ console.log("[Krisspy Analytics \u2192 OpenPanel] Tracked:", eventName, properties);
1328
+ }
1329
+ return;
1330
+ }
1315
1331
  const event = {
1316
1332
  eventName,
1317
1333
  sessionId: this.sessionId,
@@ -1330,10 +1346,100 @@ var KrisspyAnalytics = class {
1330
1346
  identify(userId, traits) {
1331
1347
  this.userId = userId;
1332
1348
  this.userTraits = traits || {};
1349
+ if (this.useOpenPanel && this.openpanel) {
1350
+ this.openpanel.identify(__spreadValues({ profileId: userId }, traits));
1351
+ if (this.options.debug) {
1352
+ console.log("[Krisspy Analytics \u2192 OpenPanel] Identified:", userId, traits);
1353
+ }
1354
+ return;
1355
+ }
1333
1356
  if (this.initialized) {
1334
1357
  this.track("identify", __spreadValues({ userId }, traits));
1335
1358
  }
1336
1359
  }
1360
+ // ── OpenPanel-specific methods (no-op when using internal analytics) ──
1361
+ /**
1362
+ * Set properties that will be sent with every event
1363
+ */
1364
+ setGlobalProperties(props) {
1365
+ if (this.useOpenPanel && this.openpanel) {
1366
+ this.openpanel.setGlobalProperties(props);
1367
+ }
1368
+ }
1369
+ /**
1370
+ * Increment a numeric property on a user profile
1371
+ */
1372
+ increment(profileId, property, value) {
1373
+ if (this.useOpenPanel && this.openpanel) {
1374
+ this.openpanel.increment({ profileId, property, value });
1375
+ }
1376
+ }
1377
+ /**
1378
+ * Decrement a numeric property on a user profile
1379
+ */
1380
+ decrement(profileId, property, value) {
1381
+ if (this.useOpenPanel && this.openpanel) {
1382
+ this.openpanel.decrement({ profileId, property, value });
1383
+ }
1384
+ }
1385
+ /**
1386
+ * Create or update a group entity (company, team, etc.)
1387
+ */
1388
+ upsertGroup(group) {
1389
+ if (this.useOpenPanel && this.openpanel) {
1390
+ this.openpanel.upsertGroup(group);
1391
+ }
1392
+ }
1393
+ /**
1394
+ * Link the current user to a group — tags all future events
1395
+ */
1396
+ setGroup(groupId) {
1397
+ if (this.useOpenPanel && this.openpanel) {
1398
+ this.openpanel.setGroup(groupId);
1399
+ }
1400
+ }
1401
+ /**
1402
+ * Track a revenue event
1403
+ */
1404
+ async revenue(amount, properties) {
1405
+ if (this.useOpenPanel && this.openpanel) {
1406
+ await this.openpanel.revenue(amount, properties);
1407
+ }
1408
+ }
1409
+ /**
1410
+ * Queue a pending revenue event (call flushRevenue() to send)
1411
+ */
1412
+ pendingRevenue(amount, properties) {
1413
+ if (this.useOpenPanel && this.openpanel) {
1414
+ this.openpanel.pendingRevenue(amount, properties);
1415
+ }
1416
+ }
1417
+ /**
1418
+ * Flush all pending revenue events
1419
+ */
1420
+ async flushRevenue() {
1421
+ if (this.useOpenPanel && this.openpanel) {
1422
+ await this.openpanel.flushRevenue();
1423
+ }
1424
+ }
1425
+ /**
1426
+ * Clear pending revenue
1427
+ */
1428
+ clearRevenue() {
1429
+ if (this.useOpenPanel && this.openpanel) {
1430
+ this.openpanel.clearRevenue();
1431
+ }
1432
+ }
1433
+ /**
1434
+ * Clear current user data (including groups)
1435
+ */
1436
+ clear() {
1437
+ this.userId = null;
1438
+ this.userTraits = {};
1439
+ if (this.useOpenPanel && this.openpanel) {
1440
+ this.openpanel.clear();
1441
+ }
1442
+ }
1337
1443
  /**
1338
1444
  * Flush event queue to the server (async)
1339
1445
  */
@@ -1435,6 +1541,46 @@ var KrisspyAnalytics = class {
1435
1541
  };
1436
1542
  window.addEventListener("popstate", this.popstateHandler);
1437
1543
  }
1544
+ /**
1545
+ * Initialize OpenPanel SDK dynamically.
1546
+ * Loads @openpanel/web at runtime (must be installed by the user).
1547
+ * Falls back gracefully if not available.
1548
+ */
1549
+ async initOpenPanel() {
1550
+ const clientId = this.options.openpanelClientId;
1551
+ const apiUrl = this.options.openpanelApiUrl || "https://api-openpanel.krisspy.ai";
1552
+ try {
1553
+ const { OpenPanel } = await import("@openpanel/web");
1554
+ this.openpanel = new OpenPanel({
1555
+ clientId,
1556
+ apiUrl,
1557
+ trackScreenViews: this.options.autoTrackPageViews !== false,
1558
+ trackOutgoingLinks: this.options.trackOutgoingLinks !== false,
1559
+ trackAttributes: this.options.trackAttributes !== false,
1560
+ trackHashChanges: this.options.trackHashChanges,
1561
+ disabled: this.options.disabled,
1562
+ filter: this.options.filter
1563
+ });
1564
+ if (this.options.debug) {
1565
+ console.log("[Krisspy Analytics \u2192 OpenPanel] Initialized", { clientId, apiUrl });
1566
+ }
1567
+ } catch (err) {
1568
+ console.warn(
1569
+ "[Krisspy Analytics] @openpanel/web not found. Install it with: npm install @openpanel/web\nFalling back to internal analytics."
1570
+ );
1571
+ this.useOpenPanel = false;
1572
+ this.openpanel = null;
1573
+ this.sessionId = this.getOrCreateSessionId();
1574
+ if (this.options.autoTrackPageViews) {
1575
+ this.track("session_start", {});
1576
+ this.track("page_view", { url: window.location.href, referrer: document.referrer });
1577
+ }
1578
+ if (this.options.autoTrackNavigation) {
1579
+ this.setupNavigationTracking();
1580
+ }
1581
+ this.flushTimer = setInterval(() => this.flush(), this.options.flushInterval);
1582
+ }
1583
+ }
1438
1584
  };
1439
1585
 
1440
1586
  // src/notifications.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "krisspy-sdk",
3
- "version": "0.8.2",
3
+ "version": "0.9.1",
4
4
  "description": "Krisspy Cloud SDK - Database, Auth, Storage, and Functions for your apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -41,6 +41,9 @@
41
41
  "type": "git",
42
42
  "url": "https://github.com/krisspy/krisspy-sdk"
43
43
  },
44
+ "dependencies": {
45
+ "@openpanel/web": "^1.0.0"
46
+ },
44
47
  "devDependencies": {
45
48
  "@types/node": "^20.0.0",
46
49
  "tsup": "^8.0.0",