@getforty/widget 0.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.
Potentially problematic release.
This version of @getforty/widget might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +276 -0
- package/dist/index.cjs +456 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +359 -0
- package/dist/index.d.ts +359 -0
- package/dist/index.global.js +456 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +456 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget Configuration Types
|
|
3
|
+
* These types are exported publicly for developers using the widget
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Primary configuration object passed to widget initialization
|
|
7
|
+
*/
|
|
8
|
+
interface WidgetConfig {
|
|
9
|
+
/** Workspace tracking ID (required) - format: gf_xxxxxxxxxxxx */
|
|
10
|
+
trackingId: string;
|
|
11
|
+
/** Display language (default: auto-detect from browser) */
|
|
12
|
+
locale?: "en" | "pt-BR" | string;
|
|
13
|
+
/** Custom translations to override built-in strings */
|
|
14
|
+
translations?: Partial<TranslationStrings>;
|
|
15
|
+
/** Visual customization options for forms */
|
|
16
|
+
theme?: WidgetTheme;
|
|
17
|
+
/** Rendering mode for forms */
|
|
18
|
+
mode?: "inline" | "modal";
|
|
19
|
+
/** Target element for inline mode (CSS selector or HTMLElement) */
|
|
20
|
+
container?: string | HTMLElement;
|
|
21
|
+
/** Show/hide GetForty branding */
|
|
22
|
+
showBranding?: boolean;
|
|
23
|
+
/** Automatically track page views */
|
|
24
|
+
autoTrackPageViews?: boolean;
|
|
25
|
+
/** Automatically display forms based on server-side conditions (default: true) */
|
|
26
|
+
autoDisplay?: boolean;
|
|
27
|
+
/** API base URL (default: https://getforty.club) */
|
|
28
|
+
apiBaseUrl?: string;
|
|
29
|
+
/** Enable debug logging */
|
|
30
|
+
debug?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Observe parent window's dataLayer (Google Tag Manager) and automatically
|
|
33
|
+
* send events through GetForty tracking pipeline (opt-in)
|
|
34
|
+
*
|
|
35
|
+
* When enabled, watches for events pushed to window.dataLayer and forwards
|
|
36
|
+
* them to GetForty's backend, allowing you to leverage existing GTM integrations.
|
|
37
|
+
*
|
|
38
|
+
* Note: Only works in same-origin scenarios (cross-origin iframes not supported)
|
|
39
|
+
*/
|
|
40
|
+
observeDataLayer?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Prefix added to dataLayer event names when sent to GetForty
|
|
43
|
+
* (default: "gtm_")
|
|
44
|
+
*
|
|
45
|
+
* Example: dataLayer event "purchase" becomes "gtm_purchase" in GetForty
|
|
46
|
+
*/
|
|
47
|
+
dataLayerEventPrefix?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Filter which dataLayer events to send (optional)
|
|
50
|
+
* Can be a RegExp to test event names or a function that returns boolean
|
|
51
|
+
*
|
|
52
|
+
* Examples:
|
|
53
|
+
* - /^custom_/ (only events starting with "custom_")
|
|
54
|
+
* - (name) => name !== "gtm.js" (exclude GTM internal events)
|
|
55
|
+
*/
|
|
56
|
+
dataLayerEventFilter?: RegExp | ((eventName: string) => boolean);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Visual customization options for form UI
|
|
60
|
+
*/
|
|
61
|
+
interface WidgetTheme {
|
|
62
|
+
/** Primary color for buttons and accents (CSS color) */
|
|
63
|
+
primaryColor?: string;
|
|
64
|
+
/** Background color for widget container (CSS color) */
|
|
65
|
+
backgroundColor?: string;
|
|
66
|
+
/** Text color (CSS color) */
|
|
67
|
+
textColor?: string;
|
|
68
|
+
/** Font family (CSS font-family) */
|
|
69
|
+
fontFamily?: string;
|
|
70
|
+
/** Border radius for containers and inputs (CSS value) */
|
|
71
|
+
borderRadius?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Options for tracking a custom event
|
|
75
|
+
*/
|
|
76
|
+
interface TrackEventOptions {
|
|
77
|
+
/** Custom properties to attach to the event */
|
|
78
|
+
properties?: Record<string, string | number | boolean | null>;
|
|
79
|
+
/** Override the auto-generated session ID */
|
|
80
|
+
sessionId?: string;
|
|
81
|
+
/** Override the identified user ID */
|
|
82
|
+
userId?: string;
|
|
83
|
+
/** Timestamp override (default: now) */
|
|
84
|
+
timestamp?: Date;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Options for identifying a user
|
|
88
|
+
*/
|
|
89
|
+
interface IdentifyOptions {
|
|
90
|
+
/** User traits/properties */
|
|
91
|
+
traits?: Record<string, string | number | boolean | null>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Internal representation of a tracked event
|
|
95
|
+
*/
|
|
96
|
+
interface TrackedEvent {
|
|
97
|
+
/** Event name (e.g., 'page_view', 'purchase', 'signup') */
|
|
98
|
+
eventName: string;
|
|
99
|
+
/** Custom event properties */
|
|
100
|
+
properties?: Record<string, unknown>;
|
|
101
|
+
/** Session identifier (auto-generated or provided) */
|
|
102
|
+
sessionId: string;
|
|
103
|
+
/** User identifier (from identify() call) */
|
|
104
|
+
userId?: string;
|
|
105
|
+
/** Event timestamp */
|
|
106
|
+
timestamp: string;
|
|
107
|
+
/** Retry count for failed sends */
|
|
108
|
+
_retryCount?: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Localizable UI strings
|
|
112
|
+
*/
|
|
113
|
+
interface TranslationStrings {
|
|
114
|
+
submit: string;
|
|
115
|
+
submitting: string;
|
|
116
|
+
next: string;
|
|
117
|
+
previous: string;
|
|
118
|
+
skip: string;
|
|
119
|
+
required: string;
|
|
120
|
+
invalidEmail: string;
|
|
121
|
+
invalidNumber: string;
|
|
122
|
+
minLength: string;
|
|
123
|
+
maxLength: string;
|
|
124
|
+
loading: string;
|
|
125
|
+
success: string;
|
|
126
|
+
successMessage: string;
|
|
127
|
+
error: string;
|
|
128
|
+
networkError: string;
|
|
129
|
+
rateLimited: string;
|
|
130
|
+
tryAgain: string;
|
|
131
|
+
npsNotLikely: string;
|
|
132
|
+
npsVeryLikely: string;
|
|
133
|
+
closeModal: string;
|
|
134
|
+
formLabel: string;
|
|
135
|
+
questionOf: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Form configuration received from API
|
|
139
|
+
*/
|
|
140
|
+
interface FormConfig {
|
|
141
|
+
id: string;
|
|
142
|
+
title: string;
|
|
143
|
+
type: "NPS" | "CSAT" | "PMF" | "CUSTOM";
|
|
144
|
+
questions: Question[];
|
|
145
|
+
branding?: {
|
|
146
|
+
logoUrl?: string;
|
|
147
|
+
thankYouMessage?: string;
|
|
148
|
+
colors?: {
|
|
149
|
+
primary?: string;
|
|
150
|
+
background?: string;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Question definition within a form
|
|
156
|
+
*/
|
|
157
|
+
interface Question {
|
|
158
|
+
id: string;
|
|
159
|
+
type: "rating" | "nps" | "text" | "textarea" | "select" | "multiselect" | "scale";
|
|
160
|
+
label: string;
|
|
161
|
+
description?: string;
|
|
162
|
+
required: boolean;
|
|
163
|
+
options?: QuestionOption[];
|
|
164
|
+
validation?: {
|
|
165
|
+
minLength?: number;
|
|
166
|
+
maxLength?: number;
|
|
167
|
+
pattern?: string;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Option for select/multiselect questions
|
|
172
|
+
*/
|
|
173
|
+
interface QuestionOption {
|
|
174
|
+
value: string;
|
|
175
|
+
label: string;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Answer submitted for a question
|
|
179
|
+
*/
|
|
180
|
+
interface Answer {
|
|
181
|
+
questionId: string;
|
|
182
|
+
value: string | string[] | number;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Events emitted by widget for developer integration
|
|
186
|
+
*/
|
|
187
|
+
interface WidgetEventMap {
|
|
188
|
+
/** Widget started loading form configuration */
|
|
189
|
+
"load:start": {
|
|
190
|
+
formId: string;
|
|
191
|
+
};
|
|
192
|
+
/** Form configuration loaded successfully */
|
|
193
|
+
"load:success": {
|
|
194
|
+
form: FormConfig;
|
|
195
|
+
};
|
|
196
|
+
/** Form loading failed */
|
|
197
|
+
"load:error": {
|
|
198
|
+
error: string;
|
|
199
|
+
retryable: boolean;
|
|
200
|
+
};
|
|
201
|
+
/** Widget became visible (modal opened or inline rendered) */
|
|
202
|
+
open: {
|
|
203
|
+
mode: "inline" | "modal";
|
|
204
|
+
};
|
|
205
|
+
/** Widget hidden (modal closed) */
|
|
206
|
+
close: {
|
|
207
|
+
reason: "user" | "submitted" | "programmatic";
|
|
208
|
+
};
|
|
209
|
+
/** Form submission started */
|
|
210
|
+
"submit:start": {
|
|
211
|
+
answers: Answer[];
|
|
212
|
+
};
|
|
213
|
+
/** Form submission successful */
|
|
214
|
+
"submit:success": {
|
|
215
|
+
responseId: string;
|
|
216
|
+
};
|
|
217
|
+
/** Form submission failed */
|
|
218
|
+
"submit:error": {
|
|
219
|
+
error: string;
|
|
220
|
+
retryable: boolean;
|
|
221
|
+
};
|
|
222
|
+
/** Any error occurred */
|
|
223
|
+
error: {
|
|
224
|
+
type: "load" | "submit" | "network";
|
|
225
|
+
message: string;
|
|
226
|
+
};
|
|
227
|
+
/** Field received focus */
|
|
228
|
+
"field:focus": {
|
|
229
|
+
questionId: string;
|
|
230
|
+
questionLabel: string;
|
|
231
|
+
};
|
|
232
|
+
/** Field lost focus */
|
|
233
|
+
"field:blur": {
|
|
234
|
+
questionId: string;
|
|
235
|
+
questionLabel: string;
|
|
236
|
+
};
|
|
237
|
+
/** Field value changed */
|
|
238
|
+
"field:change": {
|
|
239
|
+
questionId: string;
|
|
240
|
+
questionLabel: string;
|
|
241
|
+
};
|
|
242
|
+
/** Field validation error */
|
|
243
|
+
"field:validation": {
|
|
244
|
+
questionId: string;
|
|
245
|
+
questionLabel: string;
|
|
246
|
+
error: string;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Public interface for the GetForty widget instance
|
|
251
|
+
*/
|
|
252
|
+
interface GetFortyWidgetInstance {
|
|
253
|
+
/**
|
|
254
|
+
* Track a custom event
|
|
255
|
+
* @param eventName - Name of the event (e.g., 'page_view', 'purchase')
|
|
256
|
+
* @param properties - Optional custom properties
|
|
257
|
+
*/
|
|
258
|
+
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
259
|
+
/**
|
|
260
|
+
* Identify the current user
|
|
261
|
+
* Sends user data to backend and links events/respondents
|
|
262
|
+
* @param userId - Unique user identifier
|
|
263
|
+
* @param traits - Optional user traits (email, name, plan, etc.)
|
|
264
|
+
*/
|
|
265
|
+
identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
|
|
266
|
+
/**
|
|
267
|
+
* Show a feedback form
|
|
268
|
+
* @param formId - The form ID to display
|
|
269
|
+
*/
|
|
270
|
+
showForm(formId: string): void;
|
|
271
|
+
/**
|
|
272
|
+
* Hide the currently displayed form
|
|
273
|
+
*/
|
|
274
|
+
hideForm(): void;
|
|
275
|
+
/**
|
|
276
|
+
* Subscribe to widget lifecycle events
|
|
277
|
+
* @param event - Event name
|
|
278
|
+
* @param callback - Event handler
|
|
279
|
+
*/
|
|
280
|
+
on<K extends keyof WidgetEventMap>(event: K, callback: (data: WidgetEventMap[K]) => void): void;
|
|
281
|
+
/**
|
|
282
|
+
* Unsubscribe from widget lifecycle events
|
|
283
|
+
*/
|
|
284
|
+
off<K extends keyof WidgetEventMap>(event: K, callback: (data: WidgetEventMap[K]) => void): void;
|
|
285
|
+
/**
|
|
286
|
+
* Flush any queued events immediately
|
|
287
|
+
*/
|
|
288
|
+
flush(): Promise<void>;
|
|
289
|
+
/**
|
|
290
|
+
* Get the current session ID
|
|
291
|
+
*/
|
|
292
|
+
getSessionId(): string;
|
|
293
|
+
/**
|
|
294
|
+
* Destroy the widget and clean up resources
|
|
295
|
+
* Stops polling, clears timers, and removes DOM elements
|
|
296
|
+
*/
|
|
297
|
+
destroy(): void;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Widget constants
|
|
302
|
+
*/
|
|
303
|
+
declare const VERSION = "0.1.0";
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @getforty/widget
|
|
307
|
+
* Embeddable feedback widget and event tracking SDK for GetForty
|
|
308
|
+
*
|
|
309
|
+
* Usage:
|
|
310
|
+
* ```typescript
|
|
311
|
+
* import { GetForty } from '@getforty/widget'
|
|
312
|
+
*
|
|
313
|
+
* const widget = await GetForty.init({
|
|
314
|
+
* trackingId: 'gf_xxxxxxxxxxxx',
|
|
315
|
+
* })
|
|
316
|
+
*
|
|
317
|
+
* // Track events
|
|
318
|
+
* widget.track('page_view', { page: '/pricing' })
|
|
319
|
+
*
|
|
320
|
+
* // Identify users
|
|
321
|
+
* widget.identify('user_123', { email: 'user@example.com' })
|
|
322
|
+
*
|
|
323
|
+
* // Show forms programmatically
|
|
324
|
+
* widget.showForm('form-id')
|
|
325
|
+
*
|
|
326
|
+
* // Listen to events
|
|
327
|
+
* widget.on('submit:success', (data) => {
|
|
328
|
+
* console.log('Feedback submitted!', data.responseId)
|
|
329
|
+
* })
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* GetForty namespace
|
|
335
|
+
* Main entry point for the widget SDK
|
|
336
|
+
*/
|
|
337
|
+
declare const GetForty: {
|
|
338
|
+
/**
|
|
339
|
+
* Initialize the GetForty widget
|
|
340
|
+
* @param config - Widget configuration
|
|
341
|
+
* @returns Promise that resolves to a widget instance
|
|
342
|
+
* @throws Error if trackingId is missing or invalid
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* const widget = await GetForty.init({
|
|
347
|
+
* trackingId: 'gf_xxxxxxxxxxxx',
|
|
348
|
+
* debug: true, // Enable debug logging
|
|
349
|
+
* })
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
init(config: WidgetConfig): Promise<GetFortyWidgetInstance>;
|
|
353
|
+
/**
|
|
354
|
+
* Current SDK version
|
|
355
|
+
*/
|
|
356
|
+
version: string;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export { type Answer, type FormConfig, GetForty, type GetFortyWidgetInstance, type IdentifyOptions, type Question, type TrackEventOptions, type TrackedEvent, type TranslationStrings, VERSION, type WidgetConfig, type WidgetEventMap, type WidgetTheme, GetForty as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widget Configuration Types
|
|
3
|
+
* These types are exported publicly for developers using the widget
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Primary configuration object passed to widget initialization
|
|
7
|
+
*/
|
|
8
|
+
interface WidgetConfig {
|
|
9
|
+
/** Workspace tracking ID (required) - format: gf_xxxxxxxxxxxx */
|
|
10
|
+
trackingId: string;
|
|
11
|
+
/** Display language (default: auto-detect from browser) */
|
|
12
|
+
locale?: "en" | "pt-BR" | string;
|
|
13
|
+
/** Custom translations to override built-in strings */
|
|
14
|
+
translations?: Partial<TranslationStrings>;
|
|
15
|
+
/** Visual customization options for forms */
|
|
16
|
+
theme?: WidgetTheme;
|
|
17
|
+
/** Rendering mode for forms */
|
|
18
|
+
mode?: "inline" | "modal";
|
|
19
|
+
/** Target element for inline mode (CSS selector or HTMLElement) */
|
|
20
|
+
container?: string | HTMLElement;
|
|
21
|
+
/** Show/hide GetForty branding */
|
|
22
|
+
showBranding?: boolean;
|
|
23
|
+
/** Automatically track page views */
|
|
24
|
+
autoTrackPageViews?: boolean;
|
|
25
|
+
/** Automatically display forms based on server-side conditions (default: true) */
|
|
26
|
+
autoDisplay?: boolean;
|
|
27
|
+
/** API base URL (default: https://getforty.club) */
|
|
28
|
+
apiBaseUrl?: string;
|
|
29
|
+
/** Enable debug logging */
|
|
30
|
+
debug?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Observe parent window's dataLayer (Google Tag Manager) and automatically
|
|
33
|
+
* send events through GetForty tracking pipeline (opt-in)
|
|
34
|
+
*
|
|
35
|
+
* When enabled, watches for events pushed to window.dataLayer and forwards
|
|
36
|
+
* them to GetForty's backend, allowing you to leverage existing GTM integrations.
|
|
37
|
+
*
|
|
38
|
+
* Note: Only works in same-origin scenarios (cross-origin iframes not supported)
|
|
39
|
+
*/
|
|
40
|
+
observeDataLayer?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Prefix added to dataLayer event names when sent to GetForty
|
|
43
|
+
* (default: "gtm_")
|
|
44
|
+
*
|
|
45
|
+
* Example: dataLayer event "purchase" becomes "gtm_purchase" in GetForty
|
|
46
|
+
*/
|
|
47
|
+
dataLayerEventPrefix?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Filter which dataLayer events to send (optional)
|
|
50
|
+
* Can be a RegExp to test event names or a function that returns boolean
|
|
51
|
+
*
|
|
52
|
+
* Examples:
|
|
53
|
+
* - /^custom_/ (only events starting with "custom_")
|
|
54
|
+
* - (name) => name !== "gtm.js" (exclude GTM internal events)
|
|
55
|
+
*/
|
|
56
|
+
dataLayerEventFilter?: RegExp | ((eventName: string) => boolean);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Visual customization options for form UI
|
|
60
|
+
*/
|
|
61
|
+
interface WidgetTheme {
|
|
62
|
+
/** Primary color for buttons and accents (CSS color) */
|
|
63
|
+
primaryColor?: string;
|
|
64
|
+
/** Background color for widget container (CSS color) */
|
|
65
|
+
backgroundColor?: string;
|
|
66
|
+
/** Text color (CSS color) */
|
|
67
|
+
textColor?: string;
|
|
68
|
+
/** Font family (CSS font-family) */
|
|
69
|
+
fontFamily?: string;
|
|
70
|
+
/** Border radius for containers and inputs (CSS value) */
|
|
71
|
+
borderRadius?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Options for tracking a custom event
|
|
75
|
+
*/
|
|
76
|
+
interface TrackEventOptions {
|
|
77
|
+
/** Custom properties to attach to the event */
|
|
78
|
+
properties?: Record<string, string | number | boolean | null>;
|
|
79
|
+
/** Override the auto-generated session ID */
|
|
80
|
+
sessionId?: string;
|
|
81
|
+
/** Override the identified user ID */
|
|
82
|
+
userId?: string;
|
|
83
|
+
/** Timestamp override (default: now) */
|
|
84
|
+
timestamp?: Date;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Options for identifying a user
|
|
88
|
+
*/
|
|
89
|
+
interface IdentifyOptions {
|
|
90
|
+
/** User traits/properties */
|
|
91
|
+
traits?: Record<string, string | number | boolean | null>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Internal representation of a tracked event
|
|
95
|
+
*/
|
|
96
|
+
interface TrackedEvent {
|
|
97
|
+
/** Event name (e.g., 'page_view', 'purchase', 'signup') */
|
|
98
|
+
eventName: string;
|
|
99
|
+
/** Custom event properties */
|
|
100
|
+
properties?: Record<string, unknown>;
|
|
101
|
+
/** Session identifier (auto-generated or provided) */
|
|
102
|
+
sessionId: string;
|
|
103
|
+
/** User identifier (from identify() call) */
|
|
104
|
+
userId?: string;
|
|
105
|
+
/** Event timestamp */
|
|
106
|
+
timestamp: string;
|
|
107
|
+
/** Retry count for failed sends */
|
|
108
|
+
_retryCount?: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Localizable UI strings
|
|
112
|
+
*/
|
|
113
|
+
interface TranslationStrings {
|
|
114
|
+
submit: string;
|
|
115
|
+
submitting: string;
|
|
116
|
+
next: string;
|
|
117
|
+
previous: string;
|
|
118
|
+
skip: string;
|
|
119
|
+
required: string;
|
|
120
|
+
invalidEmail: string;
|
|
121
|
+
invalidNumber: string;
|
|
122
|
+
minLength: string;
|
|
123
|
+
maxLength: string;
|
|
124
|
+
loading: string;
|
|
125
|
+
success: string;
|
|
126
|
+
successMessage: string;
|
|
127
|
+
error: string;
|
|
128
|
+
networkError: string;
|
|
129
|
+
rateLimited: string;
|
|
130
|
+
tryAgain: string;
|
|
131
|
+
npsNotLikely: string;
|
|
132
|
+
npsVeryLikely: string;
|
|
133
|
+
closeModal: string;
|
|
134
|
+
formLabel: string;
|
|
135
|
+
questionOf: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Form configuration received from API
|
|
139
|
+
*/
|
|
140
|
+
interface FormConfig {
|
|
141
|
+
id: string;
|
|
142
|
+
title: string;
|
|
143
|
+
type: "NPS" | "CSAT" | "PMF" | "CUSTOM";
|
|
144
|
+
questions: Question[];
|
|
145
|
+
branding?: {
|
|
146
|
+
logoUrl?: string;
|
|
147
|
+
thankYouMessage?: string;
|
|
148
|
+
colors?: {
|
|
149
|
+
primary?: string;
|
|
150
|
+
background?: string;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Question definition within a form
|
|
156
|
+
*/
|
|
157
|
+
interface Question {
|
|
158
|
+
id: string;
|
|
159
|
+
type: "rating" | "nps" | "text" | "textarea" | "select" | "multiselect" | "scale";
|
|
160
|
+
label: string;
|
|
161
|
+
description?: string;
|
|
162
|
+
required: boolean;
|
|
163
|
+
options?: QuestionOption[];
|
|
164
|
+
validation?: {
|
|
165
|
+
minLength?: number;
|
|
166
|
+
maxLength?: number;
|
|
167
|
+
pattern?: string;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Option for select/multiselect questions
|
|
172
|
+
*/
|
|
173
|
+
interface QuestionOption {
|
|
174
|
+
value: string;
|
|
175
|
+
label: string;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Answer submitted for a question
|
|
179
|
+
*/
|
|
180
|
+
interface Answer {
|
|
181
|
+
questionId: string;
|
|
182
|
+
value: string | string[] | number;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Events emitted by widget for developer integration
|
|
186
|
+
*/
|
|
187
|
+
interface WidgetEventMap {
|
|
188
|
+
/** Widget started loading form configuration */
|
|
189
|
+
"load:start": {
|
|
190
|
+
formId: string;
|
|
191
|
+
};
|
|
192
|
+
/** Form configuration loaded successfully */
|
|
193
|
+
"load:success": {
|
|
194
|
+
form: FormConfig;
|
|
195
|
+
};
|
|
196
|
+
/** Form loading failed */
|
|
197
|
+
"load:error": {
|
|
198
|
+
error: string;
|
|
199
|
+
retryable: boolean;
|
|
200
|
+
};
|
|
201
|
+
/** Widget became visible (modal opened or inline rendered) */
|
|
202
|
+
open: {
|
|
203
|
+
mode: "inline" | "modal";
|
|
204
|
+
};
|
|
205
|
+
/** Widget hidden (modal closed) */
|
|
206
|
+
close: {
|
|
207
|
+
reason: "user" | "submitted" | "programmatic";
|
|
208
|
+
};
|
|
209
|
+
/** Form submission started */
|
|
210
|
+
"submit:start": {
|
|
211
|
+
answers: Answer[];
|
|
212
|
+
};
|
|
213
|
+
/** Form submission successful */
|
|
214
|
+
"submit:success": {
|
|
215
|
+
responseId: string;
|
|
216
|
+
};
|
|
217
|
+
/** Form submission failed */
|
|
218
|
+
"submit:error": {
|
|
219
|
+
error: string;
|
|
220
|
+
retryable: boolean;
|
|
221
|
+
};
|
|
222
|
+
/** Any error occurred */
|
|
223
|
+
error: {
|
|
224
|
+
type: "load" | "submit" | "network";
|
|
225
|
+
message: string;
|
|
226
|
+
};
|
|
227
|
+
/** Field received focus */
|
|
228
|
+
"field:focus": {
|
|
229
|
+
questionId: string;
|
|
230
|
+
questionLabel: string;
|
|
231
|
+
};
|
|
232
|
+
/** Field lost focus */
|
|
233
|
+
"field:blur": {
|
|
234
|
+
questionId: string;
|
|
235
|
+
questionLabel: string;
|
|
236
|
+
};
|
|
237
|
+
/** Field value changed */
|
|
238
|
+
"field:change": {
|
|
239
|
+
questionId: string;
|
|
240
|
+
questionLabel: string;
|
|
241
|
+
};
|
|
242
|
+
/** Field validation error */
|
|
243
|
+
"field:validation": {
|
|
244
|
+
questionId: string;
|
|
245
|
+
questionLabel: string;
|
|
246
|
+
error: string;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Public interface for the GetForty widget instance
|
|
251
|
+
*/
|
|
252
|
+
interface GetFortyWidgetInstance {
|
|
253
|
+
/**
|
|
254
|
+
* Track a custom event
|
|
255
|
+
* @param eventName - Name of the event (e.g., 'page_view', 'purchase')
|
|
256
|
+
* @param properties - Optional custom properties
|
|
257
|
+
*/
|
|
258
|
+
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
259
|
+
/**
|
|
260
|
+
* Identify the current user
|
|
261
|
+
* Sends user data to backend and links events/respondents
|
|
262
|
+
* @param userId - Unique user identifier
|
|
263
|
+
* @param traits - Optional user traits (email, name, plan, etc.)
|
|
264
|
+
*/
|
|
265
|
+
identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
|
|
266
|
+
/**
|
|
267
|
+
* Show a feedback form
|
|
268
|
+
* @param formId - The form ID to display
|
|
269
|
+
*/
|
|
270
|
+
showForm(formId: string): void;
|
|
271
|
+
/**
|
|
272
|
+
* Hide the currently displayed form
|
|
273
|
+
*/
|
|
274
|
+
hideForm(): void;
|
|
275
|
+
/**
|
|
276
|
+
* Subscribe to widget lifecycle events
|
|
277
|
+
* @param event - Event name
|
|
278
|
+
* @param callback - Event handler
|
|
279
|
+
*/
|
|
280
|
+
on<K extends keyof WidgetEventMap>(event: K, callback: (data: WidgetEventMap[K]) => void): void;
|
|
281
|
+
/**
|
|
282
|
+
* Unsubscribe from widget lifecycle events
|
|
283
|
+
*/
|
|
284
|
+
off<K extends keyof WidgetEventMap>(event: K, callback: (data: WidgetEventMap[K]) => void): void;
|
|
285
|
+
/**
|
|
286
|
+
* Flush any queued events immediately
|
|
287
|
+
*/
|
|
288
|
+
flush(): Promise<void>;
|
|
289
|
+
/**
|
|
290
|
+
* Get the current session ID
|
|
291
|
+
*/
|
|
292
|
+
getSessionId(): string;
|
|
293
|
+
/**
|
|
294
|
+
* Destroy the widget and clean up resources
|
|
295
|
+
* Stops polling, clears timers, and removes DOM elements
|
|
296
|
+
*/
|
|
297
|
+
destroy(): void;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Widget constants
|
|
302
|
+
*/
|
|
303
|
+
declare const VERSION = "0.1.0";
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @getforty/widget
|
|
307
|
+
* Embeddable feedback widget and event tracking SDK for GetForty
|
|
308
|
+
*
|
|
309
|
+
* Usage:
|
|
310
|
+
* ```typescript
|
|
311
|
+
* import { GetForty } from '@getforty/widget'
|
|
312
|
+
*
|
|
313
|
+
* const widget = await GetForty.init({
|
|
314
|
+
* trackingId: 'gf_xxxxxxxxxxxx',
|
|
315
|
+
* })
|
|
316
|
+
*
|
|
317
|
+
* // Track events
|
|
318
|
+
* widget.track('page_view', { page: '/pricing' })
|
|
319
|
+
*
|
|
320
|
+
* // Identify users
|
|
321
|
+
* widget.identify('user_123', { email: 'user@example.com' })
|
|
322
|
+
*
|
|
323
|
+
* // Show forms programmatically
|
|
324
|
+
* widget.showForm('form-id')
|
|
325
|
+
*
|
|
326
|
+
* // Listen to events
|
|
327
|
+
* widget.on('submit:success', (data) => {
|
|
328
|
+
* console.log('Feedback submitted!', data.responseId)
|
|
329
|
+
* })
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* GetForty namespace
|
|
335
|
+
* Main entry point for the widget SDK
|
|
336
|
+
*/
|
|
337
|
+
declare const GetForty: {
|
|
338
|
+
/**
|
|
339
|
+
* Initialize the GetForty widget
|
|
340
|
+
* @param config - Widget configuration
|
|
341
|
+
* @returns Promise that resolves to a widget instance
|
|
342
|
+
* @throws Error if trackingId is missing or invalid
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```typescript
|
|
346
|
+
* const widget = await GetForty.init({
|
|
347
|
+
* trackingId: 'gf_xxxxxxxxxxxx',
|
|
348
|
+
* debug: true, // Enable debug logging
|
|
349
|
+
* })
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
init(config: WidgetConfig): Promise<GetFortyWidgetInstance>;
|
|
353
|
+
/**
|
|
354
|
+
* Current SDK version
|
|
355
|
+
*/
|
|
356
|
+
version: string;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export { type Answer, type FormConfig, GetForty, type GetFortyWidgetInstance, type IdentifyOptions, type Question, type TrackEventOptions, type TrackedEvent, type TranslationStrings, VERSION, type WidgetConfig, type WidgetEventMap, type WidgetTheme, GetForty as default };
|