@pocketping/widget 0.1.0 → 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 PocketPing Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Embeddable chat widget for PocketPing. Drop-in customer support chat that connec
7
7
  ### Via CDN (Recommended)
8
8
 
9
9
  ```html
10
- <script src="https://cdn.jsdelivr.net/npm/@pocketping/widget/dist/index.global.js"></script>
10
+ <script src="https://cdn.pocketping.io/widget.js"></script>
11
11
  <script>
12
12
  PocketPing.init({
13
13
  endpoint: 'https://yoursite.com/pocketping'
@@ -260,18 +260,96 @@ PocketPing.close();
260
260
  // Toggle the chat
261
261
  PocketPing.toggle();
262
262
 
263
+ // Send a message programmatically
264
+ PocketPing.sendMessage('Hello!');
265
+
263
266
  // Destroy the widget
264
267
  PocketPing.destroy();
265
268
  ```
266
269
 
267
270
  ---
268
271
 
272
+ ## Custom Events
273
+
274
+ PocketPing supports bidirectional custom events between your website and the backend. This enables powerful interactions like triggering alerts when users take specific actions.
275
+
276
+ ### Triggering Events (Widget → Backend)
277
+
278
+ Send events to your backend when users perform actions:
279
+
280
+ ```javascript
281
+ // Notify when user clicks pricing
282
+ PocketPing.trigger('clicked_pricing', { plan: 'pro', source: 'header' });
283
+
284
+ // Track user interactions
285
+ PocketPing.trigger('viewed_demo');
286
+ PocketPing.trigger('downloaded_pdf', { name: 'whitepaper.pdf' });
287
+
288
+ // Report errors
289
+ PocketPing.trigger('error_occurred', { code: 500, page: window.location.pathname });
290
+ ```
291
+
292
+ Events are forwarded to your backend and displayed in Telegram/Discord/Slack with full context.
293
+
294
+ ### Listening for Events (Backend → Widget)
295
+
296
+ Your backend can send events to the widget. Subscribe to handle them:
297
+
298
+ ```javascript
299
+ // Subscribe to an event
300
+ const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
301
+ showPopup(`Special offer: ${data.discount}% off!`);
302
+ });
303
+
304
+ // Unsubscribe when done
305
+ unsubscribe();
306
+
307
+ // Or use offEvent
308
+ PocketPing.onEvent('announcement', handleAnnouncement);
309
+ PocketPing.offEvent('announcement', handleAnnouncement);
310
+ ```
311
+
312
+ ### Event Callback
313
+
314
+ You can also use an `onEvent` callback in the init config:
315
+
316
+ ```javascript
317
+ PocketPing.init({
318
+ endpoint: 'https://yoursite.com/pocketping',
319
+ onEvent: (event) => {
320
+ console.log('Received event:', event.name, event.data);
321
+ }
322
+ });
323
+ ```
324
+
325
+ ### Use Cases
326
+
327
+ | Event | Use Case |
328
+ |-------|----------|
329
+ | `clicked_pricing` | Alert sales team when visitor shows interest |
330
+ | `error_spike` | Get notified of frontend errors |
331
+ | `cart_abandoned` | Trigger follow-up message |
332
+ | `show_offer` | Display personalized offer |
333
+ | `request_demo` | Open demo scheduling modal |
334
+ | `announcement` | Show system-wide notification |
335
+
336
+ ---
337
+
269
338
  ## TypeScript Support
270
339
 
271
340
  Full TypeScript definitions are included:
272
341
 
273
342
  ```typescript
274
- import { init, PocketPingConfig, Message } from '@pocketping/widget';
343
+ import {
344
+ init,
345
+ trigger,
346
+ onEvent,
347
+ offEvent,
348
+ PocketPingConfig,
349
+ Message,
350
+ CustomEvent,
351
+ CustomEventHandler
352
+ } from '@pocketping/widget';
275
353
 
276
354
  const config: PocketPingConfig = {
277
355
  endpoint: 'https://yoursite.com/pocketping',
@@ -281,6 +359,15 @@ const config: PocketPingConfig = {
281
359
  };
282
360
 
283
361
  init(config);
362
+
363
+ // Type-safe events
364
+ trigger('clicked_pricing', { plan: 'pro' });
365
+
366
+ const handler: CustomEventHandler = (data, event: CustomEvent) => {
367
+ console.log(event.name, data);
368
+ };
369
+
370
+ onEvent('show_offer', handler);
284
371
  ```
285
372
 
286
373
  ---
package/dist/index.d.mts CHANGED
@@ -1,6 +1,8 @@
1
1
  interface PocketPingConfig {
2
- /** Your backend endpoint (e.g., "https://yoursite.com/pocketping") */
3
- endpoint: string;
2
+ /** Your backend endpoint for self-hosted (e.g., "https://yoursite.com/pocketping") */
3
+ endpoint?: string;
4
+ /** Project ID for SaaS users (e.g., "proj_xxxxxxxxxxxxx") - from dashboard */
5
+ projectId?: string;
4
6
  /** Company/operator name displayed in header */
5
7
  operatorName?: string;
6
8
  /** Operator/company avatar URL (displayed in header) */
@@ -59,6 +61,8 @@ interface PocketPingConfig {
59
61
  onConnect?: (sessionId: string) => void;
60
62
  /** Called when connection fails */
61
63
  onError?: (error: Error) => void;
64
+ /** Called when a version mismatch is detected */
65
+ onVersionWarning?: (warning: VersionWarning) => void;
62
66
  }
63
67
  type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read';
64
68
  interface Message {
@@ -78,6 +82,8 @@ interface Session {
78
82
  visitorId: string;
79
83
  operatorOnline: boolean;
80
84
  messages: Message[];
85
+ /** User identity if identified via PocketPing.identify() */
86
+ identity?: UserIdentity;
81
87
  }
82
88
  interface PresenceResponse {
83
89
  online: boolean;
@@ -89,6 +95,58 @@ interface PresenceResponse {
89
95
  aiEnabled?: boolean;
90
96
  aiActiveAfter?: number;
91
97
  }
98
+ type VersionWarningSeverity = 'info' | 'warning' | 'error';
99
+ interface VersionWarning {
100
+ /** Severity level of the warning */
101
+ severity: VersionWarningSeverity;
102
+ /** Human-readable warning message */
103
+ message: string;
104
+ /** Current widget version */
105
+ currentVersion: string;
106
+ /** Minimum supported version (if applicable) */
107
+ minVersion?: string;
108
+ /** Latest available version (if applicable) */
109
+ latestVersion?: string;
110
+ /** Whether the widget should still function */
111
+ canContinue: boolean;
112
+ /** URL to upgrade instructions */
113
+ upgradeUrl?: string;
114
+ }
115
+ /** Custom event sent from widget to backend or vice versa */
116
+ interface CustomEvent {
117
+ /** Event name (e.g., 'clicked_pricing', 'show_offer') */
118
+ name: string;
119
+ /** Event payload */
120
+ data?: Record<string, unknown>;
121
+ /** Timestamp of the event */
122
+ timestamp: string;
123
+ }
124
+ /** Handler for custom events */
125
+ type CustomEventHandler = (data: Record<string, unknown> | undefined, event: CustomEvent) => void;
126
+ /**
127
+ * User identity data for identifying visitors
128
+ * @example
129
+ * PocketPing.identify({
130
+ * id: 'user_123',
131
+ * email: 'john@example.com',
132
+ * name: 'John Doe',
133
+ * plan: 'pro',
134
+ * company: 'Acme Inc'
135
+ * })
136
+ */
137
+ interface UserIdentity {
138
+ /** Required unique user identifier */
139
+ id: string;
140
+ /** User's email address */
141
+ email?: string;
142
+ /** User's display name */
143
+ name?: string;
144
+ /** Any custom fields (plan, company, etc.) */
145
+ [key: string]: unknown;
146
+ }
147
+ type ResolvedPocketPingConfig = Omit<PocketPingConfig, 'endpoint'> & {
148
+ endpoint: string;
149
+ };
92
150
 
93
151
  type Listener<T> = (data: T) => void;
94
152
  declare class PocketPingClient {
@@ -97,10 +155,11 @@ declare class PocketPingClient {
97
155
  private ws;
98
156
  private isOpen;
99
157
  private listeners;
158
+ private customEventHandlers;
100
159
  private reconnectAttempts;
101
160
  private maxReconnectAttempts;
102
161
  private reconnectTimeout;
103
- constructor(config: PocketPingConfig);
162
+ constructor(config: ResolvedPocketPingConfig);
104
163
  connect(): Promise<Session>;
105
164
  disconnect(): void;
106
165
  sendMessage(content: string): Promise<Message>;
@@ -108,6 +167,33 @@ declare class PocketPingClient {
108
167
  sendTyping(isTyping?: boolean): Promise<void>;
109
168
  sendReadStatus(messageIds: string[], status: MessageStatus): Promise<void>;
110
169
  getPresence(): Promise<PresenceResponse>;
170
+ /**
171
+ * Identify the current user with metadata
172
+ * Call after user logs in or when user data becomes available
173
+ * @param identity - User identity data with required id field
174
+ * @example
175
+ * PocketPing.identify({
176
+ * id: 'user_123',
177
+ * email: 'john@example.com',
178
+ * name: 'John Doe',
179
+ * plan: 'pro',
180
+ * company: 'Acme Inc'
181
+ * })
182
+ */
183
+ identify(identity: UserIdentity): Promise<void>;
184
+ /**
185
+ * Reset the user identity and optionally start a new session
186
+ * Call on user logout to clear user data
187
+ * @param options - Optional settings: { newSession: boolean }
188
+ */
189
+ reset(options?: {
190
+ newSession?: boolean;
191
+ }): Promise<void>;
192
+ /**
193
+ * Get the current user identity
194
+ * @returns UserIdentity or null if not identified
195
+ */
196
+ getIdentity(): UserIdentity | null;
111
197
  getSession(): Session | null;
112
198
  getMessages(): Message[];
113
199
  isConnected(): boolean;
@@ -116,14 +202,45 @@ declare class PocketPingClient {
116
202
  toggleOpen(): void;
117
203
  on<T>(event: string, listener: Listener<T>): () => void;
118
204
  private emit;
205
+ /**
206
+ * Trigger a custom event to the backend
207
+ * @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
208
+ * @param data - Optional payload to send with the event
209
+ * @example
210
+ * PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
211
+ */
212
+ trigger(eventName: string, data?: Record<string, unknown>): void;
213
+ /**
214
+ * Subscribe to custom events from the backend
215
+ * @param eventName - The name of the event to listen for (e.g., 'show_offer', 'open_chat')
216
+ * @param handler - Callback function when event is received
217
+ * @returns Unsubscribe function
218
+ * @example
219
+ * const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
220
+ * showPopup(data.message)
221
+ * })
222
+ */
223
+ onEvent(eventName: string, handler: CustomEventHandler): () => void;
224
+ /**
225
+ * Unsubscribe from a custom event
226
+ * @param eventName - The name of the event
227
+ * @param handler - The handler to remove
228
+ */
229
+ offEvent(eventName: string, handler: CustomEventHandler): void;
230
+ private emitCustomEvent;
119
231
  private connectWebSocket;
120
232
  private handleWebSocketEvent;
233
+ private handleVersionWarning;
121
234
  private scheduleReconnect;
122
235
  private startPolling;
123
236
  private fetch;
237
+ private checkVersionHeaders;
124
238
  private getOrCreateVisitorId;
125
239
  private getStoredSessionId;
126
240
  private storeSessionId;
241
+ private getStoredIdentity;
242
+ private storeIdentity;
243
+ private clearIdentity;
127
244
  private generateId;
128
245
  }
129
246
 
@@ -133,6 +250,77 @@ declare function open(): void;
133
250
  declare function close(): void;
134
251
  declare function toggle(): void;
135
252
  declare function sendMessage(content: string): Promise<Message>;
253
+ /**
254
+ * Trigger a custom event to the backend
255
+ * @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
256
+ * @param data - Optional payload to send with the event
257
+ * @example
258
+ * PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
259
+ */
260
+ declare function trigger(eventName: string, data?: Record<string, unknown>): void;
261
+ /**
262
+ * Subscribe to custom events from the backend
263
+ * @param eventName - The name of the event to listen for
264
+ * @param handler - Callback function when event is received
265
+ * @returns Unsubscribe function
266
+ * @example
267
+ * const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
268
+ * showPopup(data.message)
269
+ * })
270
+ */
271
+ declare function onEvent(eventName: string, handler: CustomEventHandler): () => void;
272
+ /**
273
+ * Unsubscribe from a custom event
274
+ * @param eventName - The name of the event
275
+ * @param handler - The handler to remove
276
+ */
277
+ declare function offEvent(eventName: string, handler: CustomEventHandler): void;
278
+ /**
279
+ * Identify the current user with metadata
280
+ * Call after user logs in or when user data becomes available
281
+ * @param identity - User identity data with required id field
282
+ * @example
283
+ * PocketPing.identify({
284
+ * id: 'user_123',
285
+ * email: 'john@example.com',
286
+ * name: 'John Doe',
287
+ * plan: 'pro',
288
+ * company: 'Acme Inc'
289
+ * })
290
+ */
291
+ declare function identify(identity: UserIdentity): Promise<void>;
292
+ /**
293
+ * Reset the user identity and optionally start a new session
294
+ * Call on user logout to clear user data
295
+ * @param options - Optional settings: { newSession: boolean }
296
+ * @example
297
+ * // Clear identity but keep session
298
+ * PocketPing.reset()
299
+ *
300
+ * // Clear everything and start fresh
301
+ * PocketPing.reset({ newSession: true })
302
+ */
303
+ declare function reset(options?: {
304
+ newSession?: boolean;
305
+ }): Promise<void>;
306
+ /**
307
+ * Get the current user identity
308
+ * @returns UserIdentity or null if not identified
309
+ */
310
+ declare function getIdentity(): UserIdentity | null;
311
+ /**
312
+ * Subscribe to internal widget events
313
+ * @param eventName - Event name: 'versionWarning', 'message', 'connect', 'typing', etc.
314
+ * @param handler - Callback function
315
+ * @returns Unsubscribe function
316
+ * @example
317
+ * PocketPing.on('versionWarning', (warning) => {
318
+ * if (warning.severity === 'error') {
319
+ * showUpgradeNotice(warning.message);
320
+ * }
321
+ * })
322
+ */
323
+ declare function on<T>(eventName: string, handler: (data: T) => void): () => void;
136
324
  declare const _default: {
137
325
  init: typeof init;
138
326
  destroy: typeof destroy;
@@ -140,6 +328,13 @@ declare const _default: {
140
328
  close: typeof close;
141
329
  toggle: typeof toggle;
142
330
  sendMessage: typeof sendMessage;
331
+ trigger: typeof trigger;
332
+ onEvent: typeof onEvent;
333
+ offEvent: typeof offEvent;
334
+ on: typeof on;
335
+ identify: typeof identify;
336
+ reset: typeof reset;
337
+ getIdentity: typeof getIdentity;
143
338
  };
144
339
 
145
- export { type Message, type PocketPingConfig, close, _default as default, destroy, init, open, sendMessage, toggle };
340
+ export { type CustomEvent, type CustomEventHandler, type Message, type PocketPingConfig, type UserIdentity, type VersionWarning, close, _default as default, destroy, getIdentity, identify, init, offEvent, on, onEvent, open, reset, sendMessage, toggle, trigger };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  interface PocketPingConfig {
2
- /** Your backend endpoint (e.g., "https://yoursite.com/pocketping") */
3
- endpoint: string;
2
+ /** Your backend endpoint for self-hosted (e.g., "https://yoursite.com/pocketping") */
3
+ endpoint?: string;
4
+ /** Project ID for SaaS users (e.g., "proj_xxxxxxxxxxxxx") - from dashboard */
5
+ projectId?: string;
4
6
  /** Company/operator name displayed in header */
5
7
  operatorName?: string;
6
8
  /** Operator/company avatar URL (displayed in header) */
@@ -59,6 +61,8 @@ interface PocketPingConfig {
59
61
  onConnect?: (sessionId: string) => void;
60
62
  /** Called when connection fails */
61
63
  onError?: (error: Error) => void;
64
+ /** Called when a version mismatch is detected */
65
+ onVersionWarning?: (warning: VersionWarning) => void;
62
66
  }
63
67
  type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read';
64
68
  interface Message {
@@ -78,6 +82,8 @@ interface Session {
78
82
  visitorId: string;
79
83
  operatorOnline: boolean;
80
84
  messages: Message[];
85
+ /** User identity if identified via PocketPing.identify() */
86
+ identity?: UserIdentity;
81
87
  }
82
88
  interface PresenceResponse {
83
89
  online: boolean;
@@ -89,6 +95,58 @@ interface PresenceResponse {
89
95
  aiEnabled?: boolean;
90
96
  aiActiveAfter?: number;
91
97
  }
98
+ type VersionWarningSeverity = 'info' | 'warning' | 'error';
99
+ interface VersionWarning {
100
+ /** Severity level of the warning */
101
+ severity: VersionWarningSeverity;
102
+ /** Human-readable warning message */
103
+ message: string;
104
+ /** Current widget version */
105
+ currentVersion: string;
106
+ /** Minimum supported version (if applicable) */
107
+ minVersion?: string;
108
+ /** Latest available version (if applicable) */
109
+ latestVersion?: string;
110
+ /** Whether the widget should still function */
111
+ canContinue: boolean;
112
+ /** URL to upgrade instructions */
113
+ upgradeUrl?: string;
114
+ }
115
+ /** Custom event sent from widget to backend or vice versa */
116
+ interface CustomEvent {
117
+ /** Event name (e.g., 'clicked_pricing', 'show_offer') */
118
+ name: string;
119
+ /** Event payload */
120
+ data?: Record<string, unknown>;
121
+ /** Timestamp of the event */
122
+ timestamp: string;
123
+ }
124
+ /** Handler for custom events */
125
+ type CustomEventHandler = (data: Record<string, unknown> | undefined, event: CustomEvent) => void;
126
+ /**
127
+ * User identity data for identifying visitors
128
+ * @example
129
+ * PocketPing.identify({
130
+ * id: 'user_123',
131
+ * email: 'john@example.com',
132
+ * name: 'John Doe',
133
+ * plan: 'pro',
134
+ * company: 'Acme Inc'
135
+ * })
136
+ */
137
+ interface UserIdentity {
138
+ /** Required unique user identifier */
139
+ id: string;
140
+ /** User's email address */
141
+ email?: string;
142
+ /** User's display name */
143
+ name?: string;
144
+ /** Any custom fields (plan, company, etc.) */
145
+ [key: string]: unknown;
146
+ }
147
+ type ResolvedPocketPingConfig = Omit<PocketPingConfig, 'endpoint'> & {
148
+ endpoint: string;
149
+ };
92
150
 
93
151
  type Listener<T> = (data: T) => void;
94
152
  declare class PocketPingClient {
@@ -97,10 +155,11 @@ declare class PocketPingClient {
97
155
  private ws;
98
156
  private isOpen;
99
157
  private listeners;
158
+ private customEventHandlers;
100
159
  private reconnectAttempts;
101
160
  private maxReconnectAttempts;
102
161
  private reconnectTimeout;
103
- constructor(config: PocketPingConfig);
162
+ constructor(config: ResolvedPocketPingConfig);
104
163
  connect(): Promise<Session>;
105
164
  disconnect(): void;
106
165
  sendMessage(content: string): Promise<Message>;
@@ -108,6 +167,33 @@ declare class PocketPingClient {
108
167
  sendTyping(isTyping?: boolean): Promise<void>;
109
168
  sendReadStatus(messageIds: string[], status: MessageStatus): Promise<void>;
110
169
  getPresence(): Promise<PresenceResponse>;
170
+ /**
171
+ * Identify the current user with metadata
172
+ * Call after user logs in or when user data becomes available
173
+ * @param identity - User identity data with required id field
174
+ * @example
175
+ * PocketPing.identify({
176
+ * id: 'user_123',
177
+ * email: 'john@example.com',
178
+ * name: 'John Doe',
179
+ * plan: 'pro',
180
+ * company: 'Acme Inc'
181
+ * })
182
+ */
183
+ identify(identity: UserIdentity): Promise<void>;
184
+ /**
185
+ * Reset the user identity and optionally start a new session
186
+ * Call on user logout to clear user data
187
+ * @param options - Optional settings: { newSession: boolean }
188
+ */
189
+ reset(options?: {
190
+ newSession?: boolean;
191
+ }): Promise<void>;
192
+ /**
193
+ * Get the current user identity
194
+ * @returns UserIdentity or null if not identified
195
+ */
196
+ getIdentity(): UserIdentity | null;
111
197
  getSession(): Session | null;
112
198
  getMessages(): Message[];
113
199
  isConnected(): boolean;
@@ -116,14 +202,45 @@ declare class PocketPingClient {
116
202
  toggleOpen(): void;
117
203
  on<T>(event: string, listener: Listener<T>): () => void;
118
204
  private emit;
205
+ /**
206
+ * Trigger a custom event to the backend
207
+ * @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
208
+ * @param data - Optional payload to send with the event
209
+ * @example
210
+ * PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
211
+ */
212
+ trigger(eventName: string, data?: Record<string, unknown>): void;
213
+ /**
214
+ * Subscribe to custom events from the backend
215
+ * @param eventName - The name of the event to listen for (e.g., 'show_offer', 'open_chat')
216
+ * @param handler - Callback function when event is received
217
+ * @returns Unsubscribe function
218
+ * @example
219
+ * const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
220
+ * showPopup(data.message)
221
+ * })
222
+ */
223
+ onEvent(eventName: string, handler: CustomEventHandler): () => void;
224
+ /**
225
+ * Unsubscribe from a custom event
226
+ * @param eventName - The name of the event
227
+ * @param handler - The handler to remove
228
+ */
229
+ offEvent(eventName: string, handler: CustomEventHandler): void;
230
+ private emitCustomEvent;
119
231
  private connectWebSocket;
120
232
  private handleWebSocketEvent;
233
+ private handleVersionWarning;
121
234
  private scheduleReconnect;
122
235
  private startPolling;
123
236
  private fetch;
237
+ private checkVersionHeaders;
124
238
  private getOrCreateVisitorId;
125
239
  private getStoredSessionId;
126
240
  private storeSessionId;
241
+ private getStoredIdentity;
242
+ private storeIdentity;
243
+ private clearIdentity;
127
244
  private generateId;
128
245
  }
129
246
 
@@ -133,6 +250,77 @@ declare function open(): void;
133
250
  declare function close(): void;
134
251
  declare function toggle(): void;
135
252
  declare function sendMessage(content: string): Promise<Message>;
253
+ /**
254
+ * Trigger a custom event to the backend
255
+ * @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
256
+ * @param data - Optional payload to send with the event
257
+ * @example
258
+ * PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
259
+ */
260
+ declare function trigger(eventName: string, data?: Record<string, unknown>): void;
261
+ /**
262
+ * Subscribe to custom events from the backend
263
+ * @param eventName - The name of the event to listen for
264
+ * @param handler - Callback function when event is received
265
+ * @returns Unsubscribe function
266
+ * @example
267
+ * const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
268
+ * showPopup(data.message)
269
+ * })
270
+ */
271
+ declare function onEvent(eventName: string, handler: CustomEventHandler): () => void;
272
+ /**
273
+ * Unsubscribe from a custom event
274
+ * @param eventName - The name of the event
275
+ * @param handler - The handler to remove
276
+ */
277
+ declare function offEvent(eventName: string, handler: CustomEventHandler): void;
278
+ /**
279
+ * Identify the current user with metadata
280
+ * Call after user logs in or when user data becomes available
281
+ * @param identity - User identity data with required id field
282
+ * @example
283
+ * PocketPing.identify({
284
+ * id: 'user_123',
285
+ * email: 'john@example.com',
286
+ * name: 'John Doe',
287
+ * plan: 'pro',
288
+ * company: 'Acme Inc'
289
+ * })
290
+ */
291
+ declare function identify(identity: UserIdentity): Promise<void>;
292
+ /**
293
+ * Reset the user identity and optionally start a new session
294
+ * Call on user logout to clear user data
295
+ * @param options - Optional settings: { newSession: boolean }
296
+ * @example
297
+ * // Clear identity but keep session
298
+ * PocketPing.reset()
299
+ *
300
+ * // Clear everything and start fresh
301
+ * PocketPing.reset({ newSession: true })
302
+ */
303
+ declare function reset(options?: {
304
+ newSession?: boolean;
305
+ }): Promise<void>;
306
+ /**
307
+ * Get the current user identity
308
+ * @returns UserIdentity or null if not identified
309
+ */
310
+ declare function getIdentity(): UserIdentity | null;
311
+ /**
312
+ * Subscribe to internal widget events
313
+ * @param eventName - Event name: 'versionWarning', 'message', 'connect', 'typing', etc.
314
+ * @param handler - Callback function
315
+ * @returns Unsubscribe function
316
+ * @example
317
+ * PocketPing.on('versionWarning', (warning) => {
318
+ * if (warning.severity === 'error') {
319
+ * showUpgradeNotice(warning.message);
320
+ * }
321
+ * })
322
+ */
323
+ declare function on<T>(eventName: string, handler: (data: T) => void): () => void;
136
324
  declare const _default: {
137
325
  init: typeof init;
138
326
  destroy: typeof destroy;
@@ -140,6 +328,13 @@ declare const _default: {
140
328
  close: typeof close;
141
329
  toggle: typeof toggle;
142
330
  sendMessage: typeof sendMessage;
331
+ trigger: typeof trigger;
332
+ onEvent: typeof onEvent;
333
+ offEvent: typeof offEvent;
334
+ on: typeof on;
335
+ identify: typeof identify;
336
+ reset: typeof reset;
337
+ getIdentity: typeof getIdentity;
143
338
  };
144
339
 
145
- export { type Message, type PocketPingConfig, close, _default as default, destroy, init, open, sendMessage, toggle };
340
+ export { type CustomEvent, type CustomEventHandler, type Message, type PocketPingConfig, type UserIdentity, type VersionWarning, close, _default as default, destroy, getIdentity, identify, init, offEvent, on, onEvent, open, reset, sendMessage, toggle, trigger };