@axyle/expo-sdk 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.
Files changed (43) hide show
  1. package/CONFIG.md +117 -0
  2. package/README.md +534 -0
  3. package/dist/client.d.ts +93 -0
  4. package/dist/client.js +416 -0
  5. package/dist/config.example.d.ts +8 -0
  6. package/dist/config.example.js +13 -0
  7. package/dist/configLoader.d.ts +10 -0
  8. package/dist/configLoader.js +22 -0
  9. package/dist/constants.d.ts +38 -0
  10. package/dist/constants.js +42 -0
  11. package/dist/context.d.ts +36 -0
  12. package/dist/context.js +216 -0
  13. package/dist/core.d.ts +9 -0
  14. package/dist/core.js +45 -0
  15. package/dist/hooks/useFeatureTracking.d.ts +34 -0
  16. package/dist/hooks/useFeatureTracking.js +60 -0
  17. package/dist/hooks/useOnboardingTracking.d.ts +85 -0
  18. package/dist/hooks/useOnboardingTracking.js +172 -0
  19. package/dist/hooks/useScreenTracking.d.ts +23 -0
  20. package/dist/hooks/useScreenTracking.js +52 -0
  21. package/dist/hooks/useScrollTracking.d.ts +39 -0
  22. package/dist/hooks/useScrollTracking.js +146 -0
  23. package/dist/index.d.ts +140 -0
  24. package/dist/index.js +171 -0
  25. package/dist/integrations/expoRouter.d.ts +42 -0
  26. package/dist/integrations/expoRouter.js +66 -0
  27. package/dist/integrations/reactNavigation.d.ts +27 -0
  28. package/dist/integrations/reactNavigation.js +101 -0
  29. package/dist/queue.d.ts +52 -0
  30. package/dist/queue.js +143 -0
  31. package/dist/session.d.ts +44 -0
  32. package/dist/session.js +139 -0
  33. package/dist/sessionAnalytics.d.ts +43 -0
  34. package/dist/sessionAnalytics.js +74 -0
  35. package/dist/storage.d.ts +67 -0
  36. package/dist/storage.js +210 -0
  37. package/dist/transport.d.ts +41 -0
  38. package/dist/transport.js +158 -0
  39. package/dist/types.d.ts +102 -0
  40. package/dist/types.js +5 -0
  41. package/dist/utils.d.ts +39 -0
  42. package/dist/utils.js +116 -0
  43. package/package.json +44 -0
package/CONFIG.md ADDED
@@ -0,0 +1,117 @@
1
+ # Configuration Guide
2
+
3
+ This guide explains how to configure the Axyle Analytics SDK with your API key.
4
+
5
+ ## Getting Your API Key
6
+
7
+ 1. Sign up at your analytics platform dashboard
8
+ 2. Create a new project
9
+ 3. Copy your API key from the project settings
10
+ 4. Use it to initialize the SDK
11
+
12
+ ## Configuration
13
+
14
+ The SDK is designed to be simple - you only need to provide your API key:
15
+
16
+ ```typescript
17
+ import { Axyle } from "@axyle/expo-sdk";
18
+
19
+ // Simple: just pass the API key as a string
20
+ Axyle.init("your-api-key-from-platform");
21
+
22
+ // Or as an object (both work the same)
23
+ Axyle.init({ apiKey: "your-api-key-from-platform" });
24
+ ```
25
+
26
+ That's it! The SDK uses sensible defaults for all other settings:
27
+
28
+ - Production server (always)
29
+ - Optimal queue and flush settings
30
+ - Automatic session management
31
+ - App lifecycle tracking
32
+
33
+ ## Setting User ID
34
+
35
+ User ID should be set at runtime using the `identify()` method:
36
+
37
+ ```typescript
38
+ // After user logs in
39
+ Axyle.identify("user-123", {
40
+ email: "user@example.com",
41
+ plan: "premium",
42
+ });
43
+ ```
44
+
45
+ This is the recommended approach as it allows you to track anonymous users before they log in.
46
+
47
+ ## API Key Format
48
+
49
+ Your API key should be in one of these formats:
50
+
51
+ - UUID: `550e8400-e29b-41d4-a716-446655440000`
52
+ - Alphanumeric: At least 32 characters (e.g., `abc123def456ghi789jkl012mno345pqr`)
53
+
54
+ ## Security Best Practices
55
+
56
+ 1. **Never commit API keys to version control**
57
+ - Store API keys in environment variables
58
+ - Use secure storage for API keys in production apps
59
+ - Consider using a secrets management service
60
+
61
+ 2. **Use environment variables for API keys**
62
+
63
+ ```typescript
64
+ Axyle.init(process.env.EXPO_ANALYTICS_API_KEY || "");
65
+ ```
66
+
67
+ 3. **Use different API keys for dev and prod**
68
+ ```typescript
69
+ Axyle.init(__DEV__ ? "dev-api-key" : "prod-api-key");
70
+ ```
71
+
72
+ ## Example: Complete Setup
73
+
74
+ ```typescript
75
+ import { Axyle } from '@axyle/expo-sdk';
76
+ import { useEffect } from 'react';
77
+
78
+ export default function App() {
79
+ useEffect(() => {
80
+ // Initialize SDK - just pass your API key
81
+ Axyle.init('your-api-key-from-platform');
82
+ }, []);
83
+
84
+ // Later, when user logs in
85
+ const handleLogin = async (userId: string, email: string) => {
86
+ await Axyle.identify(userId, {
87
+ email,
88
+ loginMethod: 'email',
89
+ });
90
+ };
91
+
92
+ return (
93
+ // Your app content
94
+ );
95
+ }
96
+ ```
97
+
98
+ ## Troubleshooting
99
+
100
+ ### "API key is required" warning
101
+
102
+ - Make sure you've passed a valid API key string
103
+ - Check that the API key is not empty
104
+
105
+ ### Invalid API key format
106
+
107
+ - Verify your API key matches the expected format (UUID or 32+ character alphanumeric)
108
+ - Check for extra spaces or special characters
109
+ - Use the `isValidApiKeyFormat()` utility if needed:
110
+
111
+ ```typescript
112
+ import { isValidApiKeyFormat } from "@axyle/expo-sdk";
113
+
114
+ if (isValidApiKeyFormat("your-api-key")) {
115
+ Axyle.init("your-api-key");
116
+ }
117
+ ```
package/README.md ADDED
@@ -0,0 +1,534 @@
1
+ # Axyle Analytics SDK
2
+
3
+ A privacy-focused, lightweight analytics SDK for Expo and React Native applications.
4
+
5
+ ## Features
6
+
7
+ - **Simple Integration** - One-line initialization with just an API key
8
+ - **Automatic Tracking** - App lifecycle, sessions, and screen views
9
+ - **Offline Support** - Events are queued and sent when connection is available
10
+ - **Privacy First** - No PII collected by default, opt-out support, GDPR-compliant data deletion
11
+ - **Zero Configuration** - Sensible defaults for all settings
12
+ - **TypeScript Support** - Full type definitions included
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @axyle/expo-sdk
18
+ ```
19
+
20
+ ### Peer Dependencies
21
+
22
+ Install the required peer dependencies:
23
+
24
+ ```bash
25
+ npx expo install expo-application expo-constants expo-device @react-native-async-storage/async-storage
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ### 1. Initialize the SDK
31
+
32
+ Initialize the SDK in your app's entry point (e.g., `App.tsx` or `_layout.tsx`):
33
+
34
+ ```tsx
35
+ import { useEffect } from "react";
36
+ import { Axyle } from "@axyle/expo-sdk";
37
+
38
+ export default function App() {
39
+ useEffect(() => {
40
+ Axyle.init("your-api-key");
41
+ }, []);
42
+
43
+ return <YourApp />;
44
+ }
45
+ ```
46
+
47
+ ### 2. Track Custom Events
48
+
49
+ ```tsx
50
+ import { Axyle } from "@axyle/expo-sdk";
51
+
52
+ // Track a button click
53
+ Axyle.track("Button Clicked", {
54
+ button: "Sign Up",
55
+ screen: "Home",
56
+ });
57
+
58
+ // Track a purchase
59
+ Axyle.track("Purchase Completed", {
60
+ amount: 29.99,
61
+ currency: "USD",
62
+ productId: "premium-plan",
63
+ });
64
+ ```
65
+
66
+ ### 3. Identify Users
67
+
68
+ ```tsx
69
+ // When user logs in
70
+ Axyle.identify("user-123", {
71
+ email: "user@example.com",
72
+ plan: "premium",
73
+ });
74
+
75
+ // When user logs out
76
+ Axyle.reset();
77
+ ```
78
+
79
+ ## API Reference
80
+
81
+ ### Core Methods
82
+
83
+ #### `Axyle.init(apiKey)`
84
+
85
+ Initialize the SDK. Must be called before any other methods.
86
+
87
+ ```tsx
88
+ // Pass API key as a string
89
+ Axyle.init("your-api-key");
90
+
91
+ // Or as an object
92
+ Axyle.init({ apiKey: "your-api-key" });
93
+ ```
94
+
95
+ #### `Axyle.track(eventName, properties?)`
96
+
97
+ Track a custom event with optional properties.
98
+
99
+ ```tsx
100
+ Axyle.track("Video Watched", {
101
+ videoId: "abc123",
102
+ duration: 120,
103
+ quality: "HD",
104
+ });
105
+ ```
106
+
107
+ **Property Types:** Properties must be primitives (string, number, boolean, null).
108
+
109
+ #### `Axyle.identify(userId, traits?)`
110
+
111
+ Associate events with a user ID and optional traits.
112
+
113
+ ```tsx
114
+ Axyle.identify("user-123", {
115
+ email: "user@example.com",
116
+ plan: "premium",
117
+ });
118
+ ```
119
+
120
+ #### `Axyle.reset()`
121
+
122
+ Clear user data and start a new session. Call this on logout.
123
+
124
+ ```tsx
125
+ Axyle.reset();
126
+ ```
127
+
128
+ #### `Axyle.flush()`
129
+
130
+ Manually flush all queued events to the server.
131
+
132
+ ```tsx
133
+ await Axyle.flush();
134
+ ```
135
+
136
+ #### `Axyle.shutdown()`
137
+
138
+ Gracefully shutdown the SDK (flushes events and cleans up resources).
139
+
140
+ ```tsx
141
+ await Axyle.shutdown();
142
+ ```
143
+
144
+ ### Privacy Methods
145
+
146
+ #### `Axyle.optOut()`
147
+
148
+ Opt out of tracking. Stops all event collection.
149
+
150
+ ```tsx
151
+ Axyle.optOut();
152
+ ```
153
+
154
+ #### `Axyle.optIn()`
155
+
156
+ Opt back in to tracking.
157
+
158
+ ```tsx
159
+ Axyle.optIn();
160
+ ```
161
+
162
+ #### `Axyle.deleteUser(userId)`
163
+
164
+ Request deletion of user data (GDPR compliance).
165
+
166
+ ```tsx
167
+ Axyle.deleteUser("user-123");
168
+ ```
169
+
170
+ ### Analytics Methods
171
+
172
+ #### `Axyle.getSessionStats()`
173
+
174
+ Get current session statistics.
175
+
176
+ ```tsx
177
+ const stats = Axyle.getSessionStats();
178
+ // { totalEvents: 15, eventsByType: { 'Button Clicked': 3, ... }, ... }
179
+ ```
180
+
181
+ #### `Axyle.getSessionEvents()`
182
+
183
+ Get all events in the current session.
184
+
185
+ ```tsx
186
+ const events = Axyle.getSessionEvents();
187
+ ```
188
+
189
+ #### `Axyle.getEventsByType(eventName)`
190
+
191
+ Get events filtered by type.
192
+
193
+ ```tsx
194
+ const buttonClicks = Axyle.getEventsByType("Button Clicked");
195
+ ```
196
+
197
+ ## Screen Tracking
198
+
199
+ ### Manual Screen Tracking (Recommended)
200
+
201
+ ```tsx
202
+ import { useEffect } from "react";
203
+ import { trackScreen } from "@axyle/expo-sdk";
204
+
205
+ export default function HomeScreen() {
206
+ useEffect(() => {
207
+ trackScreen("Home");
208
+ }, []);
209
+
210
+ return <View>...</View>;
211
+ }
212
+
213
+ // With additional properties
214
+ export default function ProductScreen({ productId }) {
215
+ useEffect(() => {
216
+ trackScreen("Product", { productId });
217
+ }, [productId]);
218
+
219
+ return <View>...</View>;
220
+ }
221
+ ```
222
+
223
+ ### Using the Screen Tracking Hook
224
+
225
+ ```tsx
226
+ import { useScreenTracking } from "@axyle/expo-sdk";
227
+
228
+ function HomeScreen() {
229
+ useScreenTracking({
230
+ screenName: "Home",
231
+ properties: { section: "main" },
232
+ trackTime: true, // Track time spent on screen
233
+ });
234
+
235
+ return <View>...</View>;
236
+ }
237
+ ```
238
+
239
+ ### React Navigation Integration
240
+
241
+ ```tsx
242
+ import { NavigationContainer } from "@react-navigation/native";
243
+ import { createNavigationTracker } from "@axyle/expo-sdk";
244
+
245
+ const navigationTracker = createNavigationTracker();
246
+
247
+ function App() {
248
+ return (
249
+ <NavigationContainer onStateChange={navigationTracker}>
250
+ {/* Your navigators */}
251
+ </NavigationContainer>
252
+ );
253
+ }
254
+ ```
255
+
256
+ ## Flow Tracking
257
+
258
+ Track multi-step user flows like onboarding, checkout, or tutorials:
259
+
260
+ ```tsx
261
+ import {
262
+ useFlowTracking,
263
+ trackFlowCompleted,
264
+ trackFlowAbandoned,
265
+ } from "@axyle/expo-sdk";
266
+
267
+ // In each step component
268
+ function OnboardingStep1() {
269
+ useFlowTracking({
270
+ flowId: "welcome-onboarding",
271
+ flowType: "onboarding",
272
+ step: 1,
273
+ totalSteps: 4,
274
+ stepName: "Welcome",
275
+ });
276
+
277
+ return <View>...</View>;
278
+ }
279
+
280
+ // When flow completes
281
+ function OnboardingComplete() {
282
+ useEffect(() => {
283
+ trackFlowCompleted("welcome-onboarding", 4, { flowType: "onboarding" });
284
+ }, []);
285
+
286
+ return <View>...</View>;
287
+ }
288
+
289
+ // When user abandons flow (e.g., closes modal)
290
+ const handleClose = () => {
291
+ trackFlowAbandoned("welcome-onboarding", currentStep, 4, {
292
+ flowType: "onboarding",
293
+ stepName: "Current Step Name",
294
+ });
295
+ };
296
+ ```
297
+
298
+ ## Feature Tracking
299
+
300
+ Track feature usage and discovery:
301
+
302
+ ```tsx
303
+ import { trackFeatureUsage, useFeatureViewTracking } from "@axyle/expo-sdk";
304
+
305
+ // Track when a feature is used
306
+ const handleShare = () => {
307
+ trackFeatureUsage("share", { screen: "Article", method: "button" });
308
+ // ... share logic
309
+ };
310
+
311
+ // Track when a feature is viewed/discovered
312
+ function NewFeatureBanner() {
313
+ useFeatureViewTracking("premium-upgrade-banner", { location: "home" });
314
+
315
+ return <View>...</View>;
316
+ }
317
+ ```
318
+
319
+ ## Scroll Tracking
320
+
321
+ Track scroll depth on content screens:
322
+
323
+ ```tsx
324
+ import { useScrollTracking, useWebScrollTracking } from "@axyle/expo-sdk";
325
+
326
+ // React Native
327
+ function ArticleScreen() {
328
+ const scrollViewRef = useScrollTracking({
329
+ screenName: "Article",
330
+ thresholds: [25, 50, 75, 100],
331
+ });
332
+
333
+ return <ScrollView ref={scrollViewRef}>{/* content */}</ScrollView>;
334
+ }
335
+
336
+ // Web
337
+ function WebArticle() {
338
+ useWebScrollTracking({
339
+ screenName: "Article",
340
+ thresholds: [25, 50, 75, 100],
341
+ });
342
+
343
+ return <div>...</div>;
344
+ }
345
+ ```
346
+
347
+ ## Automatically Tracked Events
348
+
349
+ The SDK automatically tracks:
350
+
351
+ | Event | Description |
352
+ | ------------------ | ------------------------------------- |
353
+ | `App Opened` | App launches |
354
+ | `App Backgrounded` | App goes to background |
355
+ | `App Foregrounded` | App returns to foreground |
356
+ | `Session Started` | New session begins |
357
+ | `Session Ended` | Session expires (30 min inactivity) |
358
+ | `Screen Viewed` | Screen navigation (with integrations) |
359
+
360
+ ## Event Schema
361
+
362
+ Each event includes:
363
+
364
+ ```typescript
365
+ {
366
+ id: string; // Unique event ID
367
+ name: string; // Event name
368
+ properties: object; // Custom properties
369
+ timestamp: number; // Unix timestamp (ms)
370
+ userId: string; // User or anonymous ID
371
+ anonymousId: string; // Persistent anonymous ID
372
+ sessionId: string; // Current session ID
373
+ schemaVersion: string; // Schema version
374
+ context: {
375
+ app: { name, version, build, namespace },
376
+ device: { id, manufacturer, model, name, type, brand },
377
+ os: { name, version },
378
+ screen: { width, height, density },
379
+ locale: string,
380
+ timezone: string,
381
+ environment: 'dev' | 'prod'
382
+ }
383
+ }
384
+ ```
385
+
386
+ ## Configuration
387
+
388
+ The SDK uses sensible defaults:
389
+
390
+ | Setting | Default | Description |
391
+ | --------------- | ---------- | ------------------------------- |
392
+ | Queue Size | 100 events | Max events before auto-flush |
393
+ | Flush Interval | 10 seconds | Auto-flush interval |
394
+ | Session Timeout | 30 minutes | Inactivity timeout for sessions |
395
+ | Retry Attempts | 3 | Network retry attempts |
396
+ | Batch Size | 500 KB | Max batch size |
397
+
398
+ These settings are optimized for mobile and cannot be overridden.
399
+
400
+ ## Best Practices
401
+
402
+ ### 1. Initialize Early
403
+
404
+ Initialize in your root component before rendering any screens:
405
+
406
+ ```tsx
407
+ function App() {
408
+ useEffect(() => {
409
+ Axyle.init("your-api-key");
410
+ }, []);
411
+
412
+ return <YourApp />;
413
+ }
414
+ ```
415
+
416
+ ### 2. Use Descriptive Event Names
417
+
418
+ ```tsx
419
+ // Good
420
+ Axyle.track('Checkout Completed', { ... });
421
+ Axyle.track('Profile Photo Updated', { ... });
422
+
423
+ // Avoid
424
+ Axyle.track('click', { ... });
425
+ Axyle.track('event1', { ... });
426
+ ```
427
+
428
+ ### 3. Keep Properties Simple
429
+
430
+ Use primitive types for properties:
431
+
432
+ ```tsx
433
+ // Good
434
+ Axyle.track("Item Added", {
435
+ itemId: "123",
436
+ price: 29.99,
437
+ quantity: 2,
438
+ });
439
+
440
+ // Avoid nested objects
441
+ ```
442
+
443
+ ### 4. Flush Before Critical Actions
444
+
445
+ ```tsx
446
+ async function logout() {
447
+ await Axyle.flush();
448
+ Axyle.reset();
449
+ // ... logout logic
450
+ }
451
+ ```
452
+
453
+ ### 5. Respect User Privacy
454
+
455
+ ```tsx
456
+ function SettingsScreen() {
457
+ const [optedOut, setOptedOut] = useState(false);
458
+
459
+ const handleOptOut = async () => {
460
+ if (optedOut) {
461
+ await Axyle.optIn();
462
+ } else {
463
+ await Axyle.optOut();
464
+ }
465
+ setOptedOut(!optedOut);
466
+ };
467
+
468
+ return (
469
+ <View>
470
+ <Text>Analytics</Text>
471
+ <Switch value={!optedOut} onValueChange={handleOptOut} />
472
+ </View>
473
+ );
474
+ }
475
+ ```
476
+
477
+ ## Troubleshooting
478
+
479
+ ### Events Not Sending
480
+
481
+ 1. Verify your API key is correct
482
+ 2. Check network connectivity
483
+ 3. Call `Axyle.flush()` to force send events
484
+ 4. Check if user has opted out
485
+
486
+ ### TypeScript Errors
487
+
488
+ Ensure peer dependencies are installed:
489
+
490
+ ```bash
491
+ npm install --save-dev @types/react @types/react-native
492
+ ```
493
+
494
+ ### Expo Go Issues
495
+
496
+ 1. Restart Expo Go
497
+ 2. Clear cache: `npx expo start -c`
498
+ 3. Reinstall dependencies
499
+
500
+ ### SDK Not Initializing
501
+
502
+ Ensure you're calling `init()` before any other SDK methods:
503
+
504
+ ```tsx
505
+ // Correct order
506
+ await Axyle.init("api-key");
507
+ Axyle.track("Event", {});
508
+
509
+ // Wrong - track called before init
510
+ Axyle.track("Event", {});
511
+ Axyle.init("api-key");
512
+ ```
513
+
514
+ ## TypeScript
515
+
516
+ The SDK is fully typed. Import types as needed:
517
+
518
+ ```tsx
519
+ import type {
520
+ AnalyticsEvent,
521
+ EventProperties,
522
+ UserTraits,
523
+ SessionAnalyticsStats,
524
+ } from "@axyle/expo-sdk";
525
+ ```
526
+
527
+ ## License
528
+
529
+ MIT
530
+
531
+ ## Support
532
+
533
+ - GitHub Issues: [Report a bug](https://github.com/axyle/expo-sdk/issues)
534
+ - Documentation: [docs.axyle.com](https://docs.axyle.com)