flowgrid-sdk 1.0.1 → 1.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.
@@ -12,32 +12,121 @@
12
12
  * await this.init('eventName', { key: 'value' });
13
13
  * ```
14
14
  */
15
+ /**
16
+ * FTRPC - Core transport layer for Flowgrid SDK.
17
+ *
18
+ * @description
19
+ * Provides a secure, validated RPC-style transport layer used by all SDK modules.
20
+ * Handles:
21
+ * - Input validation
22
+ * - Payload size enforcement
23
+ * - Timeout handling
24
+ * - Retry logic (network failures only)
25
+ * - Authorization headers
26
+ *
27
+ * This class is designed to be extended by higher-level modules
28
+ * (e.g., FeatureFlag, Analytics, Experiments).
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const client = new FTRPC("web_123", "api.flowgrid.com", "sk_live_xxx");
33
+ * ```
34
+ */
15
35
  export declare class FTRPC {
16
36
  /**
17
- * Web ID for the specific site or application.
18
- * Used to identify the event source.
37
+ * Unique Web ID identifying the site or application.
38
+ * Used by the backend to associate incoming events.
19
39
  */
20
40
  protected webId: string;
21
41
  /**
22
- * API endpoint for sending events.
23
- * Example: "https://api.flowgrid.com"
42
+ * Base API endpoint.
43
+ * Example values:
44
+ * - "api.flowgrid.com"
45
+ * - "https://api.flowgrid.com"
46
+ *
47
+ * Protocol is normalized automatically.
24
48
  */
25
49
  protected endpoint: string;
26
50
  /**
27
- * API Key for authenticating requests.
51
+ * Private API key used for authenticating requests.
52
+ * Sent as a Bearer token in the Authorization header.
28
53
  */
29
54
  private apiKey;
55
+ /**
56
+ * Maximum allowed payload size (in bytes).
57
+ * Prevents oversized event submissions.
58
+ */
59
+ private static readonly MAX_PAYLOAD_SIZE;
60
+ /**
61
+ * Maximum time (ms) before request is aborted.
62
+ */
63
+ private static readonly TIMEOUT_MS;
64
+ /**
65
+ * Maximum retry attempts for network-level failures.
66
+ * Does NOT retry HTTP 4xx/5xx responses.
67
+ */
68
+ private static readonly MAX_RETRIES;
69
+ /**
70
+ * Creates a new FTRPC transport instance.
71
+ *
72
+ * @param webId - Unique identifier for the web property.
73
+ * @param endpoint - API base endpoint.
74
+ * @param apiKey - Private API key for authentication.
75
+ *
76
+ * @throws {Error} If required parameters are missing.
77
+ */
30
78
  constructor(webId: string, endpoint: string, apiKey: string);
31
79
  /**
32
- * Sends an event to the API.
33
- * Used internally by subclasses to track events.
80
+ * Core RPC transport method.
34
81
  *
35
- * @param eventName - Name of the event to track.
36
- * @param properties - Additional properties to send with the event.
82
+ * @template T Expected JSON response type.
83
+ *
84
+ * @param eventName - Logical event or function name.
85
+ * @param properties - Arbitrary event payload properties.
86
+ * @param method - HTTP method ("GET", "POST", "PATCH").
87
+ *
88
+ * @returns Promise resolving to typed response.
89
+ *
90
+ * @remarks
91
+ * - GET requests are treated as read-only operations.
92
+ * - POST/PATCH requests may mutate backend state.
93
+ * - Retries occur only for network failures or timeouts.
94
+ */
95
+ protected init<T>(eventName: string, properties?: Record<string, any>, method?: "GET" | "POST" | "PATCH"): Promise<T>;
96
+ /**
97
+ * Executes HTTP request with timeout and retry handling.
98
+ *
99
+ * @template T Expected response type.
100
+ *
101
+ * @param url - Fully constructed request URL.
102
+ * @param method - HTTP method.
103
+ * @param body - Optional JSON body (POST/PATCH only).
104
+ *
105
+ * @throws {Error} On timeout, network failure, or non-OK HTTP status.
37
106
  */
38
- protected init<T>(eventName: string, properties?: Record<string, any>, request?: "GET" | "POST" | "PATCH"): Promise<T>;
107
+ private executeRequest;
39
108
  /**
40
- * Validates input parameters for security and correctness.
109
+ * Validates event name and payload.
110
+ *
111
+ * @param eventName - Event identifier.
112
+ * @param properties - Associated event properties.
113
+ *
114
+ * @throws {Error} If validation fails.
41
115
  */
42
116
  private validateInput;
117
+ /**
118
+ * Normalizes endpoint input.
119
+ * Ensures protocol is present and removes trailing slashes.
120
+ *
121
+ * @param endpoint - Raw endpoint string.
122
+ * @returns Normalized endpoint URL.
123
+ */
124
+ private normalizeEndpoint;
125
+ /**
126
+ * Safely reads response text without throwing.
127
+ *
128
+ * @param res - Fetch Response object.
129
+ * @returns Response text or empty string.
130
+ */
131
+ private safeRead;
43
132
  }
@@ -40,114 +40,156 @@
40
40
  import { FTRPC } from "../../client/ftrpc";
41
41
  import { DateRangeFilter, TimeSeriesData } from "../../types";
42
42
  /**
43
- * Base experiment configuration.
43
+ * Configuration for tracking an experiment-related event.
44
+ *
45
+ * Used when sending a generic experiment event with a specific variant
46
+ * and associated properties.
44
47
  */
45
48
  export interface ExperimentConfig {
46
- /** Experiment/event name */
49
+ /** Logical experiment event name */
47
50
  eventName: string;
48
- /** Assigned variant */
51
+ /** Variant identifier associated with this event */
49
52
  variant: string;
50
- /** Event properties */
53
+ /** Additional contextual event data */
51
54
  properties: Record<string, unknown>;
52
55
  }
53
56
  /**
54
- * Experiment definition.
57
+ * Defines the structure and metadata of an experiment.
58
+ *
59
+ * Used when creating or updating an experiment configuration.
55
60
  */
56
61
  export interface ExperimentDefinition {
57
- /** Experiment ID */
62
+ /** Unique identifier for the experiment */
58
63
  experimentId: string;
59
- /** Experiment name */
64
+ /** Human-readable experiment name */
60
65
  name: string;
61
- /** Description */
66
+ /** Optional description of experiment purpose */
62
67
  description?: string;
63
- /** Variants */
68
+ /** Variants participating in the experiment */
64
69
  variants: Array<{
70
+ /** Unique identifier for the variant */
65
71
  variantId: string;
72
+ /** Human-readable variant name */
66
73
  name: string;
74
+ /** Traffic allocation weight (relative distribution) */
67
75
  weight: number;
68
76
  }>;
69
- /** Target audience (optional) */
77
+ /**
78
+ * Optional audience configuration.
79
+ * Allows limiting exposure by percentage and/or filter conditions.
80
+ */
70
81
  audience?: {
82
+ /** Percentage of total traffic eligible (0–100) */
71
83
  percentage: number;
84
+ /** Attribute-based targeting filters */
72
85
  filters?: Record<string, unknown>;
73
86
  };
74
- /** Primary metric */
87
+ /** Primary metric used to evaluate experiment success */
75
88
  primaryMetric: string;
76
- /** Secondary metrics */
89
+ /** Optional secondary metrics */
77
90
  secondaryMetrics?: string[];
78
- /** Start date */
91
+ /** Optional ISO start date */
79
92
  startDate?: string;
80
- /** End date */
93
+ /** Optional ISO end date */
81
94
  endDate?: string;
82
95
  }
83
96
  /**
84
- * Experiment assignment configuration.
97
+ * Configuration for assigning a user to a specific experiment variant.
98
+ *
99
+ * Represents an explicit assignment event.
85
100
  */
86
101
  export interface ExperimentAssignmentConfig {
87
- /** Experiment ID */
102
+ /** Experiment identifier */
88
103
  experimentId: string;
89
- /** User ID */
104
+ /** Unique user identifier */
90
105
  userId: string;
91
- /** Assigned variant ID */
106
+ /** Assigned variant identifier */
92
107
  variantId: string;
93
- /** Assignment source */
108
+ /**
109
+ * Assignment origin:
110
+ * - random: weighted allocation
111
+ * - targeted: rule-based assignment
112
+ * - override: manual or forced assignment
113
+ */
94
114
  source?: 'random' | 'targeted' | 'override';
95
115
  }
96
116
  /**
97
- * Experiment conversion configuration.
117
+ * Configuration for recording a conversion event within an experiment.
118
+ *
119
+ * Used to attribute metric changes to a specific variant.
98
120
  */
99
121
  export interface ExperimentConversionConfig {
100
- /** Experiment ID */
122
+ /** Experiment identifier */
101
123
  experimentId: string;
102
- /** User ID */
124
+ /** Unique user identifier */
103
125
  userId: string;
104
- /** Variant ID */
126
+ /** Variant associated with the user */
105
127
  variantId: string;
106
- /** Metric name */
128
+ /** Metric name being recorded */
107
129
  metricName: string;
108
- /** Metric value */
130
+ /** Numeric metric value */
109
131
  value: number;
110
132
  }
111
133
  /**
112
- * Experiment tracking response.
134
+ * Standardized response returned from experiment tracking operations.
135
+ *
136
+ * Ensures consistent structure across assignment, exposure,
137
+ * definition, and conversion events.
113
138
  */
114
139
  export interface ExperimentResponse {
140
+ /** Event name associated with the request */
115
141
  eventName: string;
142
+ /** Properties sent with the event */
116
143
  properties: Record<string, unknown>;
144
+ /** Server acknowledgment metadata */
117
145
  response: {
146
+ /** Indicates whether the event was successfully recorded */
118
147
  tracked: boolean;
148
+ /** Optional experiment identifier */
119
149
  experimentId?: string;
150
+ /** Optional variant identifier */
120
151
  variantId?: string;
121
152
  };
153
+ /** ISO timestamp of the recorded event */
122
154
  timestamp: string;
123
155
  }
124
156
  /**
125
- * Experiment results data.
157
+ * Aggregated results for a single experiment.
158
+ *
159
+ * Represents computed performance metrics per variant.
126
160
  */
127
161
  export interface ExperimentResultsData {
128
- /** Experiment info */
162
+ /** Experiment metadata */
129
163
  experiment: {
130
164
  experimentId: string;
131
165
  name: string;
132
166
  status: 'running' | 'paused' | 'completed';
133
167
  startDate: string;
168
+ /** Duration in days */
134
169
  duration: number;
135
170
  };
136
- /** Results by variant */
171
+ /** Variant-level performance metrics */
137
172
  variants: Array<{
138
173
  variantId: string;
139
174
  name: string;
175
+ /** Total participants assigned */
140
176
  participants: number;
177
+ /** Total recorded conversions */
141
178
  conversions: number;
179
+ /** conversions / participants */
142
180
  conversionRate: number;
181
+ /** Relative improvement compared to baseline */
143
182
  improvement: number;
183
+ /** Statistical confidence level (0–1 or percentage depending on backend) */
144
184
  confidence: number;
185
+ /** Indicates highest performing variant */
145
186
  isWinner: boolean;
187
+ /** Indicates whether statistical threshold is met */
146
188
  isStatisticallySignificant: boolean;
147
189
  }>;
148
- /** Metric trends */
190
+ /** Time-series metric trends per metric name */
149
191
  trends: Record<string, TimeSeriesData>;
150
- /** Recommendation */
192
+ /** System-generated recommendation */
151
193
  recommendation: {
152
194
  action: 'ship_winner' | 'continue' | 'stop' | 'needs_more_data';
153
195
  winningVariant?: string;
@@ -156,10 +198,12 @@ export interface ExperimentResultsData {
156
198
  };
157
199
  }
158
200
  /**
159
- * All experiments analytics.
201
+ * Aggregated analytics across all experiments.
202
+ *
203
+ * Provides high-level performance and activity overview.
160
204
  */
161
205
  export interface ExperimentAnalyticsData {
162
- /** Summary */
206
+ /** Platform-wide experiment summary */
163
207
  summary: {
164
208
  totalExperiments: number;
165
209
  activeExperiments: number;
@@ -167,7 +211,7 @@ export interface ExperimentAnalyticsData {
167
211
  avgExperimentDuration: number;
168
212
  winRate: number;
169
213
  };
170
- /** Active experiments */
214
+ /** Currently active experiments */
171
215
  active: Array<{
172
216
  experimentId: string;
173
217
  name: string;
@@ -176,7 +220,7 @@ export interface ExperimentAnalyticsData {
176
220
  leadingVariant: string;
177
221
  confidence: number;
178
222
  }>;
179
- /** Recent results */
223
+ /** Recently completed experiments */
180
224
  recentResults: Array<{
181
225
  experimentId: string;
182
226
  name: string;
@@ -185,24 +229,57 @@ export interface ExperimentAnalyticsData {
185
229
  completedDate: string;
186
230
  }>;
187
231
  }
232
+ export interface VariantResponse {
233
+ experimentId: string;
234
+ userId?: string;
235
+ variantId: string;
236
+ assignedAt: string;
237
+ }
188
238
  /**
189
- * Experiment - Track A/B tests and experiments.
239
+ * Experiment - A/B Testing & Experimentation SDK
190
240
  *
191
241
  * @extends FTRPC
192
242
  *
193
243
  * @description
194
- * Provides experiment tracking including:
244
+ * Provides structured experiment lifecycle management including:
195
245
  * - Experiment definition
196
- * - Variant assignment
246
+ * - Deterministic or server-based variant assignment
247
+ * - Exposure tracking
197
248
  * - Conversion tracking
198
- * - Results analysis
199
- * - Statistical significance
249
+ * - Statistical results & analysis
250
+ *
251
+ * This class enforces correct HTTP semantics:
252
+ *
253
+ * Exposure and conversion events are strictly POST to preserve:
254
+ * - Statistical validity
255
+ * - Unique participant counting
256
+ * - Accurate conversion attribution
257
+ * - Idempotent replay safety
258
+ *
259
+ * @lifecycle
260
+ * 1. Define experiment
261
+ * 2. Assign user to variant
262
+ * 3. Track exposure (when user actually sees variant)
263
+ * 4. Track conversions (primary/secondary metrics)
264
+ * 5. Query results & statistical analysis
265
+ *
266
+ * @statistical_model
267
+ * - Variant-level sample sizes tracked independently
268
+ * - Conversion rates calculated per variant
269
+ * - Confidence intervals computed server-side
270
+ * - Statistical significance evaluated against control
271
+ *
272
+ * @guarantees
273
+ * - Assignment is explicitly recorded
274
+ * - Exposure tracking is immutable
275
+ * - Conversion events are attributable to assigned variant
276
+ * - Results queries never mutate experiment state
200
277
  *
201
278
  * @example
202
279
  * ```typescript
203
280
  * const experiment = new Experiment(webId, endpoint, apiKey);
204
281
  *
205
- * // Define experiment
282
+ * // 1. Define experiment
206
283
  * await experiment.define({
207
284
  * experimentId: 'checkout_v2',
208
285
  * name: 'Simplified Checkout',
@@ -213,14 +290,17 @@ export interface ExperimentAnalyticsData {
213
290
  * primaryMetric: 'checkout_completed'
214
291
  * });
215
292
  *
216
- * // Assign user to variant
293
+ * // 2. Assign user
217
294
  * await experiment.assign({
218
295
  * experimentId: 'checkout_v2',
219
296
  * userId: 'user_123',
220
297
  * variantId: 'treatment'
221
298
  * });
222
299
  *
223
- * // Track conversion
300
+ * // 3. Track exposure
301
+ * await experiment.trackExposure('checkout_v2', 'user_123', 'treatment');
302
+ *
303
+ * // 4. Track conversion
224
304
  * await experiment.trackConversion({
225
305
  * experimentId: 'checkout_v2',
226
306
  * userId: 'user_123',
@@ -228,6 +308,9 @@ export interface ExperimentAnalyticsData {
228
308
  * metricName: 'checkout_completed',
229
309
  * value: 1
230
310
  * });
311
+ *
312
+ * // 5. Fetch results
313
+ * const results = await experiment.getResults('checkout_v2');
231
314
  * ```
232
315
  */
233
316
  export declare class Experiment extends FTRPC {
@@ -246,34 +329,68 @@ export declare class Experiment extends FTRPC {
246
329
  */
247
330
  define(definition: ExperimentDefinition): Promise<ExperimentResponse>;
248
331
  /**
249
- * Assigns a user to an experiment variant.
250
- *
251
- * @param config - Assignment configuration
252
- * @returns Promise resolving to experiment response
253
- */
332
+ * Assigns a user to a variant.
333
+ *
334
+ * This operation records assignment.
335
+ * Assignment should occur before exposure tracking.
336
+ *
337
+ * @param config - Assignment configuration
338
+ * @returns Promise resolving to ExperimentResponse
339
+ *
340
+ * @notes
341
+ * - Assignment does not imply exposure.
342
+ * - Exposure must be tracked separately when the variant is rendered.
343
+ */
254
344
  assign(config: ExperimentAssignmentConfig): Promise<ExperimentResponse>;
255
345
  /**
256
- * Tracks a conversion for an experiment.
346
+ * Records a conversion event for an experiment.
347
+ *
348
+ * Conversion events are attributed to the user's assigned variant.
349
+ * Supports primary and secondary metrics.
257
350
  *
258
351
  * @param config - Conversion configuration
259
- * @returns Promise resolving to experiment response
260
- */
352
+ * @returns Promise resolving to ExperimentResponse
353
+ *
354
+ * @statistical_impact
355
+ * Conversion data directly affects:
356
+ * - Conversion rate calculations
357
+ * - Variant improvement %
358
+ * - Confidence intervals
359
+ * - Statistical significance evaluation
360
+ */
261
361
  trackConversion(config: ExperimentConversionConfig): Promise<ExperimentResponse>;
262
362
  /**
263
- * Tracks user exposure to an experiment.
363
+ * Records that a user was exposed to a variant.
264
364
  *
265
- * @param experimentId - Experiment ID
266
- * @param userId - User ID
267
- * @param variantId - Variant ID
268
- * @returns Promise resolving to experiment response
269
- */
365
+ * Exposure tracking is required for valid experiment analysis.
366
+ * This ensures participants are counted correctly.
367
+ *
368
+ * @param experimentId - Experiment identifier
369
+ * @param userId - Unique user identifier
370
+ * @param variantId - Assigned variant identifier
371
+ * @returns Promise resolving to ExperimentResponse
372
+ *
373
+ * @important
374
+ * Exposure must only be tracked once per user per experiment.
375
+ * Duplicate exposures may inflate participant counts.
376
+ */
270
377
  trackExposure(experimentId: string, userId: string, variantId: string): Promise<ExperimentResponse>;
271
378
  /**
272
- * Gets results for a specific experiment.
379
+ * Retrieves statistical results for an experiment.
273
380
  *
274
- * @param experimentId - Experiment ID
275
- * @returns Promise resolving to experiment results
276
- */
381
+ * No experiment state is modified.
382
+ *
383
+ * @param experimentId - Experiment identifier
384
+ * @returns Promise resolving to ExperimentResultsData
385
+ *
386
+ * @returns_data
387
+ * - Variant performance metrics
388
+ * - Conversion rates
389
+ * - Improvement vs control
390
+ * - Statistical significance flags
391
+ * - Confidence levels
392
+ * - Recommendation engine output
393
+ */
277
394
  getResults(experimentId: string): Promise<ExperimentResultsData>;
278
395
  /**
279
396
  * Gets experiment analytics overview.
@@ -282,5 +399,13 @@ export declare class Experiment extends FTRPC {
282
399
  * @returns Promise resolving to experiment analytics
283
400
  */
284
401
  getAnalytics(filter?: DateRangeFilter): Promise<ExperimentAnalyticsData>;
402
+ /**
403
+ * Retrieves the variant assigned to a user for a specific experiment.
404
+ *
405
+ * @param experimentId - Experiment identifier
406
+ * @param userId - Unique user identifier
407
+ * @returns Promise resolving to VariantResponse, or null if no variant is assigned
408
+ */
409
+ getVariant(experimentId: string, userId: string): Promise<VariantResponse | null>;
285
410
  }
286
411
  export default Experiment;
@@ -37,7 +37,7 @@
37
37
  * ```
38
38
  */
39
39
  import { FTRPC } from "../../client/ftrpc";
40
- import { DateRangeFilter, TimeSeriesData } from "../../types";
40
+ import { TimeSeriesData } from "../../types";
41
41
  /**
42
42
  * Base feature flag configuration.
43
43
  */
@@ -245,20 +245,5 @@ export declare class FeatureFlag extends FTRPC {
245
245
  * @returns Promise resolving to flag response
246
246
  */
247
247
  trackRolloutChange(flagKey: string, previousPercentage: number, newPercentage: number, changedBy?: string): Promise<FlagResponse>;
248
- /**
249
- * Gets analytics for a specific flag.
250
- *
251
- * @param flagKey - Flag key
252
- * @param filter - Date range filter
253
- * @returns Promise resolving to flag analytics
254
- */
255
- getFlagAnalytics(flagKey: string, filter?: DateRangeFilter): Promise<FlagAnalyticsData>;
256
- /**
257
- * Gets analytics for all flags.
258
- *
259
- * @param filter - Date range filter
260
- * @returns Promise resolving to all flags analytics
261
- */
262
- getAnalytics(filter?: DateRangeFilter): Promise<AllFlagsAnalyticsData>;
263
248
  }
264
249
  export default FeatureFlag;
@@ -31,21 +31,30 @@
31
31
  * const trackFeature = new TrackFeature(webId, endpoint, apiKey);
32
32
  *
33
33
  * await trackFeature.create({
34
- * eventName: 'export_report',
35
- * properties: { format: 'csv', rowCount: 1000 }
34
+ * userId: 'user_123',
35
+ * action: 'export_report',
36
+ * properties: { featureName: 'export_report', featureId: 'export_report_001' }
36
37
  * });
37
38
  * ```
38
39
  */
39
40
  import { FTRPC } from "../../client/ftrpc";
40
41
  import { DateRangeFilter, TimeSeriesData } from "../../types";
42
+ type FeatureConfigProperties = {
43
+ featureId?: string;
44
+ featureName: string;
45
+ metadata?: Record<string, unknown>;
46
+ };
41
47
  /**
42
48
  * Base configuration for feature tracking.
43
49
  */
44
50
  export interface FeatureConfig {
45
- /** Event/feature name */
46
- eventName: string;
51
+ /** Feature tracking properties */
52
+ action: string;
53
+ /** Feature category */
54
+ category?: string;
55
+ userId: string;
47
56
  /** Event properties */
48
- properties: Record<string, unknown>;
57
+ properties: FeatureConfigProperties;
49
58
  }
50
59
  /**
51
60
  * Detailed feature usage configuration.
@@ -77,7 +86,7 @@ export interface FeatureDiscoveryConfig {
77
86
  /** User ID */
78
87
  userId: string;
79
88
  /** How feature was discovered */
80
- discoveryMethod: 'organic' | 'tooltip' | 'announcement' | 'search' | 'onboarding' | 'recommendation';
89
+ discoveryMethod: 'organic' | 'tooltip' | 'announcement' | 'search' | 'onboarding' | 'recommendation' | string;
81
90
  /** Whether user engaged with feature */
82
91
  engaged: boolean;
83
92
  }
@@ -143,8 +152,6 @@ export interface FeatureAnalyticsData {
143
152
  * - Generic feature events
144
153
  * - Detailed usage tracking
145
154
  * - Feature discovery tracking
146
- * - Adoption analytics
147
- * - Engagement metrics
148
155
  *
149
156
  * @example
150
157
  * ```typescript
@@ -152,8 +159,9 @@ export interface FeatureAnalyticsData {
152
159
  *
153
160
  * // Simple feature tracking
154
161
  * await trackFeature.create({
155
- * eventName: 'dark_mode_enabled',
156
- * properties: { userId: 'user_123' }
162
+ * userId: 'user_123',
163
+ * action: 'dark_mode_enabled',
164
+ * properties: { featureName: 'dark_mode' }
157
165
  * });
158
166
  *
159
167
  * // Detailed feature usage
@@ -183,32 +191,6 @@ export declare class TrackFeature extends FTRPC {
183
191
  * @returns Promise resolving to feature response
184
192
  */
185
193
  trackUsage(config: FeatureUsageConfig): Promise<FeatureResponse>;
186
- /**
187
- * Tracks feature discovery.
188
- *
189
- * @param config - Feature discovery configuration
190
- * @returns Promise resolving to feature response
191
- */
192
- trackDiscovery(config: FeatureDiscoveryConfig): Promise<FeatureResponse>;
193
- /**
194
- * Tracks feature adoption (first-time use).
195
- *
196
- * @param featureId - Feature identifier
197
- * @param userId - User ID
198
- * @param source - How user found feature
199
- * @returns Promise resolving to feature response
200
- */
201
- trackAdoption(featureId: string, userId: string, source?: string): Promise<FeatureResponse>;
202
- /**
203
- * Tracks feature abandonment.
204
- *
205
- * @param featureId - Feature identifier
206
- * @param userId - User ID
207
- * @param reason - Abandonment reason
208
- * @param timeSpent - Time spent before abandoning (ms)
209
- * @returns Promise resolving to feature response
210
- */
211
- trackAbandonment(featureId: string, userId: string, reason?: string, timeSpent?: number): Promise<FeatureResponse>;
212
194
  /**
213
195
  * Gets feature analytics for dashboards.
214
196
  *
@@ -266,7 +266,7 @@ export declare class Checkout extends FTRPC {
266
266
  * cart: shoppingCart,
267
267
  * payment: {
268
268
  * method: 'credit_card',
269
- * provider: 'Stripe',
269
+ * provider: 'stripe',
270
270
  * cardBrand: 'Mastercard',
271
271
  * cardLast4: '4242'
272
272
  * }