unified-analytics-mohit 1.0.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/README.md ADDED
@@ -0,0 +1,662 @@
1
+ # Unified Analytics Library
2
+
3
+ A **pure facade layer** for analytics that provides a single, unified API across multiple analytics providers (Countly, PostHog) on both **React Native** and **Web** (React.js / Next.js).
4
+
5
+ ## Core Philosophy
6
+
7
+ **One API to rule them all.** The app code uses only unified methods - no provider-specific code required. The library internally maps to the appropriate provider implementations with graceful degradation when features aren't supported.
8
+
9
+ ## Key Features
10
+
11
+ - **Pure Facade Pattern**: Single unified API, no provider-specific exposure
12
+ - **Cross-Platform**: Works on React Native and Web (React.js/Next.js)
13
+ - **Graceful Degradation**: Features return null/false when not supported instead of errors
14
+ - **Multi-Provider Support**: Use Countly, PostHog, or both simultaneously
15
+ - **React Hooks**: Easy integration with `useAnalytics()` hook
16
+ - **Zero Configuration**: Auto-detects platform, works with one or both providers
17
+
18
+ ## Installation
19
+
20
+ 1. Copy this library to your project (e.g., `libs/unified-analytics`)
21
+
22
+ 2. Install the provider SDK(s) you want to use:
23
+
24
+ **React Native:**
25
+ ```bash
26
+ # For Countly
27
+ yarn add countly-sdk-react-native-bridge@^24.4.0
28
+
29
+ # For PostHog
30
+ yarn add posthog-react-native@^3.0.0
31
+
32
+ ```
33
+
34
+ **Web (React.js / Next.js):**
35
+ ```bash
36
+ # For Countly
37
+ yarn add countly-sdk-web
38
+
39
+ # For PostHog
40
+ yarn add posthog-js
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ### React Native Setup
46
+
47
+ #### 1. Initialize Analytics
48
+
49
+ ```javascript
50
+ // App.js
51
+ import { analytics, AnalyticsProvider } from './libs/unified-analytics';
52
+
53
+ await analytics.init({
54
+ platform: 'native', // optional, auto-detected
55
+
56
+ countly: {
57
+ serverUrl: 'https://your-countly-server.com',
58
+ appKey: 'your-app-key',
59
+ enableCrashReporting: true,
60
+ },
61
+
62
+ posthog: {
63
+ apiKey: 'phc_xxxxx',
64
+ enableSessionReplay: true,
65
+ captureNativeAppLifecycleEvents: true,
66
+ },
67
+
68
+ debug: __DEV__,
69
+ });
70
+
71
+ // Wrap your app
72
+ export default function App() {
73
+ return (
74
+ <AnalyticsProvider>
75
+ <Navigation />
76
+ </AnalyticsProvider>
77
+ );
78
+ }
79
+ ```
80
+
81
+ #### 2. Setup Navigation Tracking (React Navigation)
82
+
83
+ ```javascript
84
+ import { analytics } from './libs/unified-analytics';
85
+
86
+ function App() {
87
+ const navigationRef = useRef();
88
+
89
+ const { onReady, onStateChange } = analytics.createNavigationHandlers(navigationRef);
90
+
91
+ return (
92
+ <NavigationContainer
93
+ ref={navigationRef}
94
+ onReady={onReady}
95
+ onStateChange={onStateChange}
96
+ >
97
+ <Navigator />
98
+ </NavigationContainer>
99
+ );
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ### Web (Next.js) Setup
106
+
107
+ #### 1. Initialize Analytics
108
+
109
+ ```javascript
110
+ // _app.js or layout.js
111
+ import { analytics, AnalyticsProvider } from 'unified-analytics';
112
+
113
+ await analytics.init({
114
+ platform: 'web',
115
+
116
+ countly: {
117
+ serverUrl: 'https://your-countly-server.com',
118
+ appKey: 'your-web-app-key',
119
+ debug: process.env.NODE_ENV === 'development',
120
+ },
121
+
122
+ posthog: {
123
+ apiKey: 'phc_xxxxx',
124
+ host: 'https://us.i.posthog.com',
125
+ debug: process.env.NODE_ENV === 'development',
126
+ enableSessionReplay: true,
127
+ autocapture: {
128
+ captureClicks: true,
129
+ capturePageviews: false, // We handle this manually
130
+ },
131
+ },
132
+
133
+ debug: process.env.NODE_ENV === 'development',
134
+ });
135
+ ```
136
+
137
+ #### 2. Setup Navigation Tracking
138
+
139
+ **Next.js Pages Router:**
140
+ ```javascript
141
+ import Router from 'next/router';
142
+ import { analytics } from 'unified-analytics';
143
+
144
+ const { onRouteChange } = analytics.createWebNavigationHandlers();
145
+ Router.events.on('routeChangeComplete', onRouteChange);
146
+ ```
147
+
148
+ **Next.js App Router:**
149
+ ```javascript
150
+ 'use client';
151
+ import { usePathname } from 'next/navigation';
152
+ import { analytics } from 'unified-analytics';
153
+ import { useEffect, useRef } from 'react';
154
+
155
+ function NavigationTracker() {
156
+ const pathname = usePathname();
157
+ const handlersRef = useRef(analytics.createWebNavigationHandlers());
158
+
159
+ useEffect(() => {
160
+ handlersRef.current.onRouteChange(pathname);
161
+ }, [pathname]);
162
+
163
+ return null;
164
+ }
165
+ ```
166
+
167
+ **React Router:**
168
+ ```javascript
169
+ import { useLocation } from 'react-router-dom';
170
+ import { analytics } from 'unified-analytics';
171
+ import { useEffect, useRef } from 'react';
172
+
173
+ function NavigationTracker() {
174
+ const location = useLocation();
175
+ const handlersRef = useRef(analytics.createWebNavigationHandlers());
176
+
177
+ useEffect(() => {
178
+ handlersRef.current.onRouteChange(location.pathname);
179
+ }, [location]);
180
+
181
+ return null;
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ### 3. Use in Components (Same on Both Platforms)
188
+
189
+ ```javascript
190
+ import { useAnalytics } from 'unified-analytics';
191
+
192
+ function MyComponent() {
193
+ const {
194
+ trackEvent,
195
+ setGlobalProperties,
196
+ trackError,
197
+ getFeatureFlag,
198
+ } = useAnalytics();
199
+
200
+ const handleLogin = (user) => {
201
+ setGlobalProperties({
202
+ user_id: user.id,
203
+ role: user.role,
204
+ organization: user.org,
205
+ });
206
+
207
+ trackEvent('login', { method: 'email' });
208
+ };
209
+
210
+ const handleButtonClick = () => {
211
+ trackEvent('button_click', {
212
+ button: 'submit',
213
+ screen: 'Profile',
214
+ });
215
+ };
216
+
217
+ const handleError = (error) => {
218
+ trackError(error, {
219
+ screen: 'Profile',
220
+ action: 'update_profile',
221
+ });
222
+ };
223
+
224
+ const checkFeature = () => {
225
+ const isEnabled = getFeatureFlag('new_feature');
226
+ if (isEnabled) {
227
+ // Show new feature
228
+ }
229
+ };
230
+
231
+ return <Button onPress={handleButtonClick} title="Submit" />;
232
+ }
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Platform Configuration
238
+
239
+ ### Platform Detection
240
+
241
+ The library auto-detects the platform, but you can explicitly set it:
242
+
243
+ ```javascript
244
+ analytics.init({
245
+ platform: 'native', // or 'web'
246
+ // ...
247
+ });
248
+ ```
249
+
250
+ Auto-detection logic:
251
+ - **Native**: `navigator.product === 'ReactNative'`
252
+ - **Web**: `typeof window !== 'undefined'` and not React Native
253
+
254
+ ### Platform Utilities
255
+
256
+ ```javascript
257
+ import { setPlatform, getPlatform, isWeb, isNative } from 'unified-analytics';
258
+
259
+ console.log(getPlatform()); // 'web' or 'native'
260
+ console.log(isWeb()); // true/false
261
+ console.log(isNative()); // true/false
262
+ ```
263
+
264
+ ---
265
+
266
+ ## Complete API Reference
267
+
268
+ ### Core Methods
269
+
270
+ #### `trackEvent(name, properties)`
271
+ Track a custom event.
272
+
273
+ ```javascript
274
+ trackEvent('purchase', {
275
+ product_id: '123',
276
+ amount: 99.99,
277
+ currency: 'USD',
278
+ });
279
+ ```
280
+
281
+ **Providers**: Countly, PostHog | **Platforms**: Native, Web
282
+
283
+ ---
284
+
285
+ #### `trackView(viewName, properties)`
286
+ Track a screen/page view.
287
+
288
+ ```javascript
289
+ trackView('Profile', { user_type: 'premium' });
290
+ ```
291
+
292
+ **Providers**: Countly, PostHog | **Platforms**: Native, Web
293
+
294
+ ---
295
+
296
+ #### `identify(userId, properties)`
297
+ Identify a user.
298
+
299
+ ```javascript
300
+ identify('user_123', {
301
+ email: 'user@example.com',
302
+ name: 'John Doe',
303
+ });
304
+ ```
305
+
306
+ **Providers**: Countly, PostHog | **Platforms**: Native, Web
307
+
308
+ ---
309
+
310
+ #### `setUserProperties(properties)`
311
+ Set/update user profile properties.
312
+
313
+ ```javascript
314
+ setUserProperties({
315
+ plan: 'premium',
316
+ signup_date: '2024-01-15',
317
+ });
318
+ ```
319
+
320
+ **Providers**: Countly, PostHog | **Platforms**: Native, Web
321
+
322
+ ---
323
+
324
+ #### `reset()`
325
+ Logout/reset user session.
326
+
327
+ ```javascript
328
+ reset();
329
+ ```
330
+
331
+ **Providers**: Countly, PostHog | **Platforms**: Native, Web
332
+
333
+ ---
334
+
335
+ ### Global Properties (Unified)
336
+
337
+ Properties automatically included in **every** event.
338
+
339
+ #### `setGlobalProperties(properties)`
340
+ ```javascript
341
+ setGlobalProperties({
342
+ user_id: '123',
343
+ role: 'admin',
344
+ app_version: '6.0.0',
345
+ });
346
+ ```
347
+
348
+ **Internal Mapping**:
349
+ - **Countly** -> `userContext` (custom merge on every event)
350
+ - **PostHog** -> `register()` (native super properties)
351
+
352
+ ---
353
+
354
+ #### `getGlobalProperties()`
355
+ ```javascript
356
+ const props = getGlobalProperties();
357
+ ```
358
+
359
+ ---
360
+
361
+ #### `clearGlobalProperties()`
362
+ ```javascript
363
+ clearGlobalProperties();
364
+ ```
365
+
366
+ ---
367
+
368
+ #### `removeGlobalProperty(key)`
369
+ ```javascript
370
+ removeGlobalProperty('user_id');
371
+ ```
372
+
373
+ ---
374
+
375
+ ### Timed Events (Unified)
376
+
377
+ #### `startTimer(eventName)` / `endTimer(eventName, properties)`
378
+ ```javascript
379
+ startTimer('page_load');
380
+ // ... later
381
+ endTimer('page_load', { page: 'dashboard' });
382
+ ```
383
+
384
+ **Providers**: Countly (native), PostHog (graceful no-op)
385
+
386
+ ---
387
+
388
+ ### Error Tracking (Unified)
389
+
390
+ #### `trackError(error, metadata)`
391
+ ```javascript
392
+ try {
393
+ await riskyOperation();
394
+ } catch (error) {
395
+ trackError(error, {
396
+ screen: 'Dashboard',
397
+ action: 'load_data',
398
+ fatal: false,
399
+ });
400
+ }
401
+ ```
402
+
403
+ **Internal Mapping**:
404
+ - **Countly** -> `trackError()` + `addCrashLog()`
405
+ - **PostHog** -> `capture('$exception')`
406
+
407
+ ---
408
+
409
+ ### Session Management
410
+
411
+ Sessions are **automatically managed** by the Countly SDK:
412
+ - **Web**: `Countly.track_sessions()` handles begin/end/update automatically based on page visibility
413
+ - **React Native**: The SDK automatically tracks sessions based on app foreground/background state
414
+
415
+ No manual session management is required. The `startSession()` and `endSession()` methods are deprecated no-ops kept for backward compatibility.
416
+
417
+ ---
418
+
419
+ ### Feature Flags (Unified)
420
+
421
+ #### `getFeatureFlag(key)` / `isFeatureEnabled(key)` / `getAllFeatureFlags()`
422
+ ```javascript
423
+ const flag = getFeatureFlag('new_ui');
424
+ const enabled = isFeatureEnabled('beta_features');
425
+ const allFlags = getAllFeatureFlags();
426
+ ```
427
+
428
+ **Providers**: Countly (returns null/false/{}), PostHog (native)
429
+
430
+ ---
431
+
432
+ ### Navigation Handlers
433
+
434
+ #### `createNavigationHandlers(navigationRef)` - React Native
435
+ ```javascript
436
+ const { onReady, onStateChange } = analytics.createNavigationHandlers(navigationRef);
437
+ ```
438
+
439
+ #### `createWebNavigationHandlers()` - Web
440
+ ```javascript
441
+ const { onRouteChange } = analytics.createWebNavigationHandlers();
442
+ onRouteChange('/dashboard'); // Call on route change
443
+ ```
444
+
445
+ ---
446
+
447
+ ### Screen View Overrides
448
+
449
+ #### `setScreenViewOverride(screenName, customName)`
450
+ ```javascript
451
+ setScreenViewOverride("Login", "Login - Email Entry");
452
+ ```
453
+
454
+ #### `clearScreenViewOverride(screenName)`
455
+ ```javascript
456
+ clearScreenViewOverride("Login");
457
+ ```
458
+
459
+ ---
460
+
461
+ ### Screen View Tracking Control
462
+
463
+ Screen view tracking is enabled by default. You can disable it via config or at runtime.
464
+
465
+ #### Disable via config (at init)
466
+ ```javascript
467
+ analytics.init({
468
+ platform: 'web',
469
+ trackScreenViews: false, // Disables all trackView calls
470
+ countly: { ... },
471
+ posthog: { ... },
472
+ })
473
+ ```
474
+
475
+ #### `setTrackScreenViews(enabled)` - Toggle at runtime
476
+ ```javascript
477
+ // Disable screen view tracking
478
+ analytics.setTrackScreenViews(false)
479
+
480
+ // Re-enable screen view tracking
481
+ analytics.setTrackScreenViews(true)
482
+ ```
483
+
484
+ When disabled, both automatic navigation tracking (`createNavigationHandlers` / `createWebNavigationHandlers`) and manual `trackView()` calls are suppressed. Works on both Native and Web.
485
+
486
+ ---
487
+
488
+ ### Provider-Specific (Web Only)
489
+
490
+ These methods are available when using the Countly web provider:
491
+
492
+ ```javascript
493
+ const { countly } = analytics;
494
+ countly?.trackScrolls(); // Automatic scroll depth tracking
495
+ countly?.trackLinks(); // Automatic link click tracking
496
+ countly?.trackForms(); // Automatic form submission tracking
497
+ ```
498
+
499
+ ---
500
+
501
+ ## Configuration
502
+
503
+ ### Full Configuration Options
504
+
505
+ ```javascript
506
+ analytics.init({
507
+ // Platform ('native' | 'web') - auto-detected if omitted
508
+ platform: 'native',
509
+
510
+ // Countly Configuration
511
+ countly: {
512
+ serverUrl: string, // Required
513
+ appKey: string, // Required
514
+ debug: boolean,
515
+ enableCrashReporting: boolean,
516
+ requiresConsent: boolean, // GDPR
517
+ deviceId: string,
518
+ useTemporaryDeviceId: boolean,
519
+ location: {
520
+ countryCode: string, // ISO 3166-1 alpha-2
521
+ city: string,
522
+ gpsCoordinates: string, // 'latitude,longitude'
523
+ ipAddress: string,
524
+ },
525
+ disableLocation: boolean,
526
+ tamperingProtectionSalt: string,
527
+ },
528
+
529
+ // PostHog Configuration
530
+ posthog: {
531
+ apiKey: string, // Required
532
+ host: string, // Default: https://us.i.posthog.com
533
+ debug: boolean,
534
+ disabled: boolean,
535
+
536
+ // RN-only options
537
+ flushInterval: number, // Seconds, default: 30
538
+ flushAt: number, // Events, default: 20
539
+ captureNativeAppLifecycleEvents: boolean,
540
+ sessionReplay: {
541
+ maskAllTextInputs: boolean,
542
+ maskAllImages: boolean,
543
+ captureLog: boolean, // RN only
544
+ captureNetworkTelemetry: boolean, // RN only
545
+ androidDebouncerDelayMs: number, // RN only
546
+ iOSdebouncerDelayMs: number, // RN only
547
+ },
548
+ autocapture: {
549
+ captureTouches: boolean, // RN only
550
+ captureScreens: boolean, // RN only
551
+ captureClicks: boolean, // Web only
552
+ capturePageviews: boolean, // Web only
553
+ capturePageleave: boolean, // Web only
554
+ },
555
+
556
+ // Common options
557
+ enableSessionReplay: boolean,
558
+ featureFlagsRequestTimeoutMs: number,
559
+ bootstrap: {
560
+ distinctId: string,
561
+ featureFlags: object,
562
+ },
563
+ },
564
+
565
+ // Global
566
+ debug: boolean,
567
+ trackScreenViews: boolean, // Default: true. Set false to disable all screen/page view tracking
568
+ });
569
+ ```
570
+
571
+ ---
572
+
573
+ ## Architecture
574
+
575
+ ### Factory Pattern
576
+
577
+ Each provider uses a factory/proxy pattern:
578
+
579
+ ```
580
+ CountlyProvider.js (factory)
581
+ ├── CountlyProvider.native.js (React Native - uses countly-sdk-react-native-bridge)
582
+ └── CountlyProvider.web.js (Web - uses countly-sdk-web)
583
+
584
+ PostHogProvider.js (factory)
585
+ ├── PostHogProvider.native.js (React Native - uses posthog-react-native)
586
+ └── PostHogProvider.web.js (Web - uses posthog-js)
587
+ ```
588
+
589
+ The factory detects the platform and dynamically imports the correct implementation. The public API is identical across platforms.
590
+
591
+ ### Feature Support Matrix
592
+
593
+ | Feature | Countly | PostHog | Platform |
594
+ |---------|---------|---------|----------|
595
+ | trackEvent | Native | Native | Both |
596
+ | trackView | Native | Native | Both |
597
+ | setGlobalProperties | Custom (userContext) | Native (register) | Both |
598
+ | startTimer/endTimer | Native | No-op | Both |
599
+ | trackError | Native | Native (via $exception) | Both |
600
+ | Feature Flags | Returns null | Native | Both |
601
+ | Session Management | Auto-managed | Auto-managed | Both |
602
+ | Session Recording | N/A | Native | Both |
603
+ | trackScrolls/Links/Forms | Native | N/A | Web only |
604
+
605
+ ---
606
+
607
+ ## Usage Patterns
608
+
609
+ ### On User Login
610
+
611
+ ```javascript
612
+ function handleLogin(user) {
613
+ identify(user.id, { email: user.email, name: user.name });
614
+ setUserProperties({ plan: user.plan });
615
+ setGlobalProperties({ user_id: user.id, role: user.role });
616
+ trackEvent('login', { method: 'email' });
617
+ }
618
+ ```
619
+
620
+ ### On User Logout
621
+
622
+ ```javascript
623
+ function handleLogout() {
624
+ trackEvent('logout');
625
+ clearGlobalProperties();
626
+ reset();
627
+ }
628
+ ```
629
+
630
+ ### Error Handling
631
+
632
+ ```javascript
633
+ async function saveProfile(data) {
634
+ try {
635
+ await api.saveProfile(data);
636
+ trackEvent('profile_saved');
637
+ } catch (error) {
638
+ trackError(error, { screen: 'Profile', action: 'save_profile' });
639
+ }
640
+ }
641
+ ```
642
+
643
+ ---
644
+
645
+ ## Migration Guide
646
+
647
+ If you have existing provider-specific code, replace it with unified methods:
648
+
649
+ ```javascript
650
+ // Before (provider-specific)
651
+ countly.setUserContext({ user_id: '123' });
652
+ posthog.register({ user_id: '123' });
653
+
654
+ // After (unified)
655
+ setGlobalProperties({ user_id: '123' });
656
+ ```
657
+
658
+ ---
659
+
660
+ ## License
661
+
662
+ Internal use only - ANTZ Systems.