@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.
- package/CONFIG.md +117 -0
- package/README.md +534 -0
- package/dist/client.d.ts +93 -0
- package/dist/client.js +416 -0
- package/dist/config.example.d.ts +8 -0
- package/dist/config.example.js +13 -0
- package/dist/configLoader.d.ts +10 -0
- package/dist/configLoader.js +22 -0
- package/dist/constants.d.ts +38 -0
- package/dist/constants.js +42 -0
- package/dist/context.d.ts +36 -0
- package/dist/context.js +216 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.js +45 -0
- package/dist/hooks/useFeatureTracking.d.ts +34 -0
- package/dist/hooks/useFeatureTracking.js +60 -0
- package/dist/hooks/useOnboardingTracking.d.ts +85 -0
- package/dist/hooks/useOnboardingTracking.js +172 -0
- package/dist/hooks/useScreenTracking.d.ts +23 -0
- package/dist/hooks/useScreenTracking.js +52 -0
- package/dist/hooks/useScrollTracking.d.ts +39 -0
- package/dist/hooks/useScrollTracking.js +146 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.js +171 -0
- package/dist/integrations/expoRouter.d.ts +42 -0
- package/dist/integrations/expoRouter.js +66 -0
- package/dist/integrations/reactNavigation.d.ts +27 -0
- package/dist/integrations/reactNavigation.js +101 -0
- package/dist/queue.d.ts +52 -0
- package/dist/queue.js +143 -0
- package/dist/session.d.ts +44 -0
- package/dist/session.js +139 -0
- package/dist/sessionAnalytics.d.ts +43 -0
- package/dist/sessionAnalytics.js +74 -0
- package/dist/storage.d.ts +67 -0
- package/dist/storage.js +210 -0
- package/dist/transport.d.ts +41 -0
- package/dist/transport.js +158 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +39 -0
- package/dist/utils.js +116 -0
- 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)
|