@thisbefine/analytics 0.3.0 → 0.3.2

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/README.md CHANGED
@@ -169,6 +169,38 @@ analytics.log('Cache miss for user preferences', 'debug', {
169
169
  });
170
170
  ```
171
171
 
172
+ ### Lifecycle Events
173
+
174
+ Track key SaaS milestones with built-in methods. These use reserved event names (prefixed with `$`) and typed properties for consistent analytics.
175
+
176
+ ```typescript
177
+ // User lifecycle
178
+ analytics.signup({ method: 'google', plan: 'free' });
179
+ analytics.login({ method: 'passkey', isNewDevice: true });
180
+ analytics.logout({ reason: 'manual' });
181
+ analytics.accountDeleted({ reason: 'not_using', tenure: 45 });
182
+
183
+ // Subscription events
184
+ analytics.subscriptionStarted({ plan: 'pro', interval: 'monthly', mrr: 29 });
185
+ analytics.subscriptionCancelled({ plan: 'pro', reason: 'too_expensive', mrr: 29 });
186
+ analytics.subscriptionRenewed({ plan: 'pro', renewalCount: 12 });
187
+
188
+ // Plan changes
189
+ analytics.planUpgraded({ fromPlan: 'starter', toPlan: 'pro', mrrChange: 20 });
190
+ analytics.planDowngraded({ fromPlan: 'pro', toPlan: 'starter', reason: 'budget' });
191
+
192
+ // Trials
193
+ analytics.trialStarted({ plan: 'pro', trialDays: 14 });
194
+ analytics.trialEnded({ plan: 'pro', converted: true });
195
+
196
+ // Team/collaboration
197
+ analytics.inviteSent({ inviteEmail: 'teammate@company.com', role: 'editor' });
198
+ analytics.inviteAccepted({ invitedBy: 'user_123', role: 'editor' });
199
+
200
+ // Feature adoption
201
+ analytics.featureActivated({ feature: 'dark_mode', isFirstTime: true });
202
+ ```
203
+
172
204
  ### Privacy Controls
173
205
 
174
206
  Because being creepy is bad for business.
@@ -187,6 +219,36 @@ if (analytics.isOptedOut()) {
187
219
  analytics.optIn();
188
220
  ```
189
221
 
222
+ ### Consent Management
223
+
224
+ Granular control over tracking categories for GDPR/CCPA compliance.
225
+
226
+ ```typescript
227
+ // Configure consent categories on init
228
+ const analytics = createAnalytics({
229
+ apiKey: 'tbf_xxx',
230
+ consent: {
231
+ categories: ['analytics', 'marketing', 'functional'],
232
+ defaultConsent: false, // Don't track until explicit consent
233
+ },
234
+ });
235
+
236
+ // Check if a category is enabled
237
+ if (analytics.hasConsent('marketing')) {
238
+ // Show personalized content
239
+ }
240
+
241
+ // Get all consented categories
242
+ const categories = analytics.getConsentedCategories();
243
+
244
+ // Set consent (replaces current consent)
245
+ analytics.setConsent(['analytics', 'functional']);
246
+
247
+ // Grant/revoke individual categories
248
+ analytics.grantConsent('marketing');
249
+ analytics.revokeConsent('marketing');
250
+ ```
251
+
190
252
  ## React Hooks
191
253
 
192
254
  All hooks are available from both `@thisbefine/analytics/react` and `@thisbefine/analytics/next`.
@@ -289,9 +351,10 @@ const analytics = createAnalytics({
289
351
  // Required
290
352
  apiKey: 'tbf_xxx',
291
353
 
292
- // Optional
354
+ // Optional - Basic
293
355
  host: 'https://thisbefine.com', // API endpoint
294
356
  debug: false, // Console logging
357
+ structuredLogging: false, // Output debug logs as JSON
295
358
  flushAt: 20, // Batch size before sending
296
359
  flushInterval: 10000, // Ms between flushes
297
360
  sessionTimeout: 1800000, // 30 min session timeout
@@ -299,12 +362,46 @@ const analytics = createAnalytics({
299
362
  respectDNT: true, // Honor Do Not Track
300
363
  maxRetries: 3, // Retry failed requests
301
364
 
302
- // Error tracking config
365
+ // Error tracking
303
366
  errors: {
304
367
  enabled: true,
305
368
  captureUnhandled: true,
306
369
  captureConsoleErrors: true,
307
370
  },
371
+
372
+ // Lifecycle hooks
373
+ onFlushError: (error, failedEvents) => {
374
+ console.error('Failed to send events:', error);
375
+ // Log to your error tracking service
376
+ },
377
+ beforeSend: (event) => {
378
+ // Scrub PII from event properties
379
+ if (event.type === 'track' && event.properties?.email) {
380
+ const { email, ...rest } = event.properties;
381
+ return { ...event, properties: rest };
382
+ }
383
+ // Return null to discard the event
384
+ return event;
385
+ },
386
+
387
+ // Queue persistence (crash recovery)
388
+ persistQueue: true, // Save queue to localStorage
389
+ maxPersistedEvents: 1000, // Max events to persist
390
+
391
+ // Privacy & consent
392
+ anonymousIdMaxAge: 2592000000, // Rotate anonymous ID every 30 days
393
+ consent: {
394
+ categories: ['analytics', 'marketing', 'functional'],
395
+ defaultConsent: true, // Track by default (respects DNT)
396
+ },
397
+
398
+ // Rate limiting & sampling
399
+ maxEventsPerSecond: 100, // Drop events exceeding this rate
400
+ sampleRate: 1, // 1 = 100%, 0.5 = 50% of events
401
+
402
+ // Circuit breaker (stops hammering failed servers)
403
+ circuitBreakerThreshold: 5, // Open after N consecutive failures
404
+ circuitBreakerResetTimeout: 30000, // Try again after 30s
308
405
  });
309
406
  ```
310
407
 
@@ -334,12 +431,44 @@ const analytics = createAnalytics({
334
431
  | `page(name?, properties?)` | Track a page view |
335
432
  | `group(accountId, traits?)` | Associate user with account |
336
433
  | `reset()` | Clear user data (call on logout) |
337
- | `flush()` | Force send queued events |
434
+ | `flush()` | Force send queued events (returns `FlushResult`) |
435
+ | `destroy()` | Clean up resources, flush remaining events |
338
436
  | `optOut()` | Disable tracking |
339
437
  | `optIn()` | Re-enable tracking |
340
438
  | `isOptedOut()` | Check opt-out status |
341
439
  | `getUser()` | Get current user state |
342
440
 
441
+ ### Consent Methods
442
+
443
+ | Method | Description |
444
+ |--------|-------------|
445
+ | `hasConsent(category)` | Check if a category is enabled |
446
+ | `getConsentedCategories()` | Get all consented categories |
447
+ | `setConsent(categories)` | Set consent (replaces current) |
448
+ | `grantConsent(category)` | Enable a category |
449
+ | `revokeConsent(category)` | Disable a category |
450
+
451
+ Categories: `analytics` | `marketing` | `functional`
452
+
453
+ ### Lifecycle Methods
454
+
455
+ | Method | Description |
456
+ |--------|-------------|
457
+ | `signup(props?)` | Track user signup |
458
+ | `login(props?)` | Track user login |
459
+ | `logout(props?)` | Track user logout |
460
+ | `accountDeleted(props?)` | Track account deletion |
461
+ | `subscriptionStarted(props)` | Track subscription start |
462
+ | `subscriptionCancelled(props)` | Track subscription cancellation |
463
+ | `subscriptionRenewed(props)` | Track subscription renewal |
464
+ | `planUpgraded(props)` | Track plan upgrade |
465
+ | `planDowngraded(props)` | Track plan downgrade |
466
+ | `trialStarted(props)` | Track trial start |
467
+ | `trialEnded(props)` | Track trial end |
468
+ | `inviteSent(props?)` | Track invite sent |
469
+ | `inviteAccepted(props?)` | Track invite accepted |
470
+ | `featureActivated(props)` | Track feature activation |
471
+
343
472
  ### Error Tracking Methods
344
473
 
345
474
  | Method | Description |
@@ -376,11 +505,40 @@ Full type definitions included:
376
505
 
377
506
  ```typescript
378
507
  import type {
508
+ // Core types
379
509
  Analytics,
380
510
  AnalyticsConfig,
381
511
  UserState,
382
512
  UserTraits,
383
513
  AccountTraits,
514
+ FlushResult,
515
+
516
+ // Event types
517
+ AnalyticsEvent,
518
+ TrackEvent,
519
+ IdentifyEvent,
520
+ PageEvent,
521
+ GroupEvent,
522
+
523
+ // Hooks
524
+ BeforeSend,
525
+ OnFlushError,
526
+
527
+ // Lifecycle event props
528
+ SignupProps,
529
+ LoginProps,
530
+ LogoutProps,
531
+ AccountDeletedProps,
532
+ SubscriptionStartedProps,
533
+ SubscriptionCancelledProps,
534
+ SubscriptionRenewedProps,
535
+ PlanUpgradedProps,
536
+ PlanDowngradedProps,
537
+ TrialStartedProps,
538
+ TrialEndedProps,
539
+ InviteSentProps,
540
+ InviteAcceptedProps,
541
+ FeatureActivatedProps,
384
542
  } from '@thisbefine/analytics';
385
543
  ```
386
544
 
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.3.0";
1
+ export declare const VERSION = "0.3.2";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Auto-generated by scripts/generate-version.js
2
2
  // Do not edit manually
3
- export const VERSION = "0.3.0";
3
+ export const VERSION = "0.3.2";
4
4
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@thisbefine/analytics",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Track events, catch errors, and pretend everything's fine. Lightweight analytics for indie SaaS.",
5
5
  "author": "Thisbefine <hello@thisbefine.com>",
6
6
  "license": "MIT",
7
- "homepage": "https://thisbefine.com",
7
+ "homepage": "https://thisbefine.com/docs",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/thisbefine/analytics.git"