@datalyr/react-native 1.1.1 → 1.2.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 (42) hide show
  1. package/CHANGELOG.md +24 -141
  2. package/LICENSE +21 -0
  3. package/README.md +405 -217
  4. package/datalyr-react-native.podspec +31 -0
  5. package/ios/DatalyrNative.m +70 -0
  6. package/ios/DatalyrNative.swift +275 -0
  7. package/ios/DatalyrSKAdNetwork.m +26 -0
  8. package/lib/datalyr-sdk.d.ts +64 -3
  9. package/lib/datalyr-sdk.js +322 -3
  10. package/lib/index.d.ts +1 -0
  11. package/lib/index.js +4 -2
  12. package/lib/integrations/index.d.ts +6 -0
  13. package/lib/integrations/index.js +6 -0
  14. package/lib/integrations/meta-integration.d.ts +76 -0
  15. package/lib/integrations/meta-integration.js +218 -0
  16. package/lib/integrations/tiktok-integration.d.ts +82 -0
  17. package/lib/integrations/tiktok-integration.js +356 -0
  18. package/lib/native/DatalyrNativeBridge.d.ts +31 -0
  19. package/lib/native/DatalyrNativeBridge.js +168 -0
  20. package/lib/native/index.d.ts +5 -0
  21. package/lib/native/index.js +5 -0
  22. package/lib/types.d.ts +29 -0
  23. package/package.json +10 -5
  24. package/src/datalyr-sdk-expo.ts +957 -0
  25. package/src/datalyr-sdk.ts +419 -19
  26. package/src/expo.ts +38 -18
  27. package/src/index.ts +5 -2
  28. package/src/integrations/index.ts +7 -0
  29. package/src/integrations/meta-integration.ts +238 -0
  30. package/src/integrations/tiktok-integration.ts +360 -0
  31. package/src/native/DatalyrNativeBridge.ts +271 -0
  32. package/src/native/index.ts +11 -0
  33. package/src/types.ts +39 -0
  34. package/src/utils-expo.ts +25 -3
  35. package/src/utils-interface.ts +38 -0
  36. package/EXPO_INSTALL.md +0 -297
  37. package/INSTALL.md +0 -402
  38. package/examples/attribution-example.tsx +0 -377
  39. package/examples/auto-events-example.tsx +0 -403
  40. package/examples/example.tsx +0 -250
  41. package/examples/skadnetwork-example.tsx +0 -380
  42. package/examples/test-implementation.tsx +0 -163
@@ -1,403 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import {
3
- View,
4
- Text,
5
- TouchableOpacity,
6
- ScrollView,
7
- Alert,
8
- StyleSheet,
9
- AppState,
10
- SafeAreaView,
11
- } from 'react-native';
12
- import { datalyr } from '@datalyr/react-native';
13
-
14
- // This example demonstrates all automatic events (like Mixpanel)
15
- export default function AutoEventsExample() {
16
- const [sdkStatus, setSdkStatus] = useState<any>(null);
17
- const [sessionInfo, setSessionInfo] = useState<any>(null);
18
- const [autoEvents, setAutoEvents] = useState<string[]>([]);
19
-
20
- useEffect(() => {
21
- initializeSDK();
22
-
23
- // Monitor app state changes
24
- const subscription = AppState.addEventListener('change', handleAppStateChange);
25
-
26
- return () => subscription?.remove();
27
- }, []);
28
-
29
- const initializeSDK = async () => {
30
- try {
31
- console.log('🚀 Initializing Datalyr SDK with auto-events...');
32
-
33
- await datalyr.initialize({
34
- workspaceId: 'your-workspace-id',
35
- apiKey: 'dk_your_api_key', // Required for authentication
36
- debug: true,
37
- enableAttribution: true, // ✅ Deep link attribution tracking
38
- autoEvents: {
39
- trackSessions: true, // ✅ Automatic session tracking
40
- trackScreenViews: true, // ✅ Automatic screen tracking
41
- trackAppUpdates: true, // ✅ App version changes
42
- trackPerformance: true, // ✅ App launch time, performance
43
- sessionTimeoutMs: 30 * 60 * 1000, // 30 minutes
44
- },
45
- });
46
-
47
- // Get SDK status
48
- const status = datalyr.getStatus();
49
- setSdkStatus(status);
50
-
51
- // Get session info
52
- const session = datalyr.getCurrentSession();
53
- setSessionInfo(session);
54
-
55
- console.log('✅ SDK initialized with auto-events');
56
- addAutoEvent('✅ SDK Initialized (automatic)');
57
- addAutoEvent('📱 App Install Detected (automatic)');
58
- addAutoEvent('⏱️ Session Started (automatic)');
59
- addAutoEvent('🚀 App Launch Performance Tracked (automatic)');
60
-
61
- } catch (error) {
62
- console.error('❌ Failed to initialize SDK:', error);
63
- Alert.alert('Error', 'Failed to initialize SDK');
64
- }
65
- };
66
-
67
- const addAutoEvent = (event: string) => {
68
- setAutoEvents(prev => [...prev, `${new Date().toLocaleTimeString()}: ${event}`]);
69
- };
70
-
71
- const handleAppStateChange = (nextAppState: string) => {
72
- console.log('📱 App state changed to:', nextAppState);
73
-
74
- if (nextAppState === 'active') {
75
- addAutoEvent('🔆 App Foreground (automatic)');
76
- // Session might be resumed or new session started automatically
77
- updateSessionInfo();
78
- } else if (nextAppState === 'background') {
79
- addAutoEvent('🌙 App Background (automatic)');
80
- }
81
- };
82
-
83
- const updateSessionInfo = () => {
84
- const session = datalyr.getCurrentSession();
85
- setSessionInfo(session);
86
- };
87
-
88
- // Simulate automatic screen tracking
89
- const navigateToScreen = async (screenName: string) => {
90
- console.log(`📺 Navigating to ${screenName}`);
91
-
92
- // This will trigger automatic screen tracking
93
- await datalyr.screen(screenName, {
94
- screen_category: 'demo',
95
- navigation_method: 'button_press',
96
- });
97
-
98
- addAutoEvent(`📺 Pageview: ${screenName} (automatic)`);
99
- updateSessionInfo();
100
- };
101
-
102
- // Simulate automatic revenue tracking
103
- const simulatePurchase = async () => {
104
- console.log('💰 Simulating purchase...');
105
-
106
- // This will trigger automatic revenue event tracking
107
- await datalyr.trackRevenue('purchase', {
108
- product_id: 'premium_plan',
109
- price: 9.99,
110
- currency: 'USD',
111
- payment_method: 'apple_pay',
112
- });
113
-
114
- addAutoEvent('💰 Revenue Event: Purchase (automatic)');
115
- };
116
-
117
- // Simulate app update
118
- const simulateAppUpdate = async () => {
119
- console.log('📱 Simulating app update...');
120
-
121
- await datalyr.trackAppUpdate('1.0.0', '1.1.0');
122
- addAutoEvent('📱 App Update: 1.0.0 → 1.1.0 (automatic)');
123
- };
124
-
125
- // Force end session to test session management
126
- const endCurrentSession = async () => {
127
- console.log('🔚 Ending current session...');
128
-
129
- await datalyr.endSession();
130
- addAutoEvent('🔚 Session Ended (manual)');
131
-
132
- // Update session info after ending
133
- setTimeout(updateSessionInfo, 1000);
134
- };
135
-
136
- // Custom event (for comparison with automatic events)
137
- const trackCustomEvent = async () => {
138
- console.log('🎯 Tracking custom event...');
139
-
140
- await datalyr.track('button_clicked', {
141
- button_name: 'custom_event_button',
142
- screen_name: 'auto_events_demo',
143
- user_intent: 'testing',
144
- });
145
-
146
- addAutoEvent('🎯 Custom Event: button_clicked (manual)');
147
- };
148
-
149
- return (
150
- <SafeAreaView style={styles.container}>
151
- <ScrollView style={styles.content}>
152
- <Text style={styles.title}>📊 Datalyr Auto-Events Demo</Text>
153
- <Text style={styles.subtitle}>Like Mixpanel's Automatic Events</Text>
154
-
155
- {/* SDK Status */}
156
- <View style={styles.section}>
157
- <Text style={styles.sectionTitle}>📱 SDK Status</Text>
158
- <View style={styles.infoCard}>
159
- <Text style={styles.infoText}>
160
- Initialized: {sdkStatus?.initialized ? '✅' : '❌'}
161
- </Text>
162
- <Text style={styles.infoText}>
163
- Visitor ID: {sdkStatus?.visitorId || 'Not set'}
164
- </Text>
165
- <Text style={styles.infoText}>
166
- Workspace: {sdkStatus?.workspaceId || 'Not set'}
167
- </Text>
168
- </View>
169
- </View>
170
-
171
- {/* Session Info */}
172
- <View style={styles.section}>
173
- <Text style={styles.sectionTitle}>⏱️ Current Session</Text>
174
- <View style={styles.infoCard}>
175
- {sessionInfo ? (
176
- <>
177
- <Text style={styles.infoText}>
178
- Session ID: {sessionInfo.sessionId}
179
- </Text>
180
- <Text style={styles.infoText}>
181
- Duration: {Math.round((Date.now() - sessionInfo.startTime) / 1000)}s
182
- </Text>
183
- <Text style={styles.infoText}>
184
- Pageviews: {sessionInfo.screenViews}
185
- </Text>
186
- <Text style={styles.infoText}>
187
- Events: {sessionInfo.events}
188
- </Text>
189
- </>
190
- ) : (
191
- <Text style={styles.infoText}>No active session</Text>
192
- )}
193
- </View>
194
- </View>
195
-
196
- {/* Action Buttons */}
197
- <View style={styles.section}>
198
- <Text style={styles.sectionTitle}>🎮 Test Automatic Events</Text>
199
-
200
- <TouchableOpacity
201
- style={styles.button}
202
- onPress={() => navigateToScreen('Home')}
203
- >
204
- <Text style={styles.buttonText}>📺 Navigate to Home</Text>
205
- </TouchableOpacity>
206
-
207
- <TouchableOpacity
208
- style={styles.button}
209
- onPress={() => navigateToScreen('Profile')}
210
- >
211
- <Text style={styles.buttonText}>📺 Navigate to Profile</Text>
212
- </TouchableOpacity>
213
-
214
- <TouchableOpacity
215
- style={styles.button}
216
- onPress={() => navigateToScreen('Settings')}
217
- >
218
- <Text style={styles.buttonText}>📺 Navigate to Settings</Text>
219
- </TouchableOpacity>
220
-
221
- <TouchableOpacity
222
- style={[styles.button, styles.revenueButton]}
223
- onPress={simulatePurchase}
224
- >
225
- <Text style={styles.buttonText}>💰 Simulate Purchase</Text>
226
- </TouchableOpacity>
227
-
228
- <TouchableOpacity
229
- style={[styles.button, styles.updateButton]}
230
- onPress={simulateAppUpdate}
231
- >
232
- <Text style={styles.buttonText}>📱 Simulate App Update</Text>
233
- </TouchableOpacity>
234
-
235
- <TouchableOpacity
236
- style={[styles.button, styles.sessionButton]}
237
- onPress={endCurrentSession}
238
- >
239
- <Text style={styles.buttonText}>🔚 End Session</Text>
240
- </TouchableOpacity>
241
-
242
- <TouchableOpacity
243
- style={[styles.button, styles.customButton]}
244
- onPress={trackCustomEvent}
245
- >
246
- <Text style={styles.buttonText}>🎯 Track Custom Event</Text>
247
- </TouchableOpacity>
248
- </View>
249
-
250
- {/* Event Log */}
251
- <View style={styles.section}>
252
- <Text style={styles.sectionTitle}>📝 Automatic Events Log</Text>
253
- <View style={styles.eventLog}>
254
- {autoEvents.length === 0 ? (
255
- <Text style={styles.noEvents}>No events yet...</Text>
256
- ) : (
257
- autoEvents.map((event, index) => (
258
- <Text key={index} style={styles.eventItem}>
259
- {event}
260
- </Text>
261
- ))
262
- )}
263
- </View>
264
- </View>
265
-
266
- {/* Auto-Events Features */}
267
- <View style={styles.section}>
268
- <Text style={styles.sectionTitle}>✨ Included Automatic Events</Text>
269
- <View style={styles.featureList}>
270
- <Text style={styles.featureItem}>✅ Session Start/End</Text>
271
- <Text style={styles.featureItem}>✅ App Foreground/Background</Text>
272
- <Text style={styles.featureItem}>✅ Pageviews</Text>
273
- <Text style={styles.featureItem}>✅ App Install Detection</Text>
274
- <Text style={styles.featureItem}>✅ App Updates</Text>
275
- <Text style={styles.featureItem}>✅ App Launch Performance</Text>
276
- <Text style={styles.featureItem}>✅ Revenue Events</Text>
277
- <Text style={styles.featureItem}>✅ SDK Initialization</Text>
278
- <Text style={styles.featureItem}>✅ Attribution Tracking</Text>
279
- </View>
280
- </View>
281
-
282
- <View style={styles.footer}>
283
- <Text style={styles.footerText}>
284
- 🎉 All events are automatically captured and sent to your dashboard!
285
- </Text>
286
- </View>
287
- </ScrollView>
288
- </SafeAreaView>
289
- );
290
- }
291
-
292
- const styles = StyleSheet.create({
293
- container: {
294
- flex: 1,
295
- backgroundColor: '#f5f5f5',
296
- },
297
- content: {
298
- flex: 1,
299
- padding: 20,
300
- },
301
- title: {
302
- fontSize: 24,
303
- fontWeight: 'bold',
304
- textAlign: 'center',
305
- marginBottom: 8,
306
- color: '#333',
307
- },
308
- subtitle: {
309
- fontSize: 16,
310
- textAlign: 'center',
311
- marginBottom: 30,
312
- color: '#666',
313
- },
314
- section: {
315
- marginBottom: 25,
316
- },
317
- sectionTitle: {
318
- fontSize: 18,
319
- fontWeight: '600',
320
- marginBottom: 12,
321
- color: '#333',
322
- },
323
- infoCard: {
324
- backgroundColor: 'white',
325
- padding: 15,
326
- borderRadius: 8,
327
- borderLeftWidth: 4,
328
- borderLeftColor: '#007AFF',
329
- },
330
- infoText: {
331
- fontSize: 14,
332
- marginBottom: 6,
333
- color: '#444',
334
- fontFamily: 'Monaco',
335
- },
336
- button: {
337
- backgroundColor: '#007AFF',
338
- padding: 15,
339
- borderRadius: 8,
340
- marginBottom: 10,
341
- alignItems: 'center',
342
- },
343
- revenueButton: {
344
- backgroundColor: '#34C759',
345
- },
346
- updateButton: {
347
- backgroundColor: '#FF9500',
348
- },
349
- sessionButton: {
350
- backgroundColor: '#FF3B30',
351
- },
352
- customButton: {
353
- backgroundColor: '#5856D6',
354
- },
355
- buttonText: {
356
- color: 'white',
357
- fontSize: 16,
358
- fontWeight: '600',
359
- },
360
- eventLog: {
361
- backgroundColor: 'white',
362
- padding: 15,
363
- borderRadius: 8,
364
- maxHeight: 200,
365
- },
366
- noEvents: {
367
- textAlign: 'center',
368
- color: '#999',
369
- fontStyle: 'italic',
370
- },
371
- eventItem: {
372
- fontSize: 12,
373
- marginBottom: 6,
374
- color: '#333',
375
- fontFamily: 'Monaco',
376
- borderBottomWidth: 1,
377
- borderBottomColor: '#eee',
378
- paddingBottom: 4,
379
- },
380
- featureList: {
381
- backgroundColor: 'white',
382
- padding: 15,
383
- borderRadius: 8,
384
- },
385
- featureItem: {
386
- fontSize: 14,
387
- marginBottom: 8,
388
- color: '#333',
389
- },
390
- footer: {
391
- marginTop: 20,
392
- padding: 20,
393
- backgroundColor: 'white',
394
- borderRadius: 8,
395
- alignItems: 'center',
396
- },
397
- footerText: {
398
- fontSize: 16,
399
- color: '#34C759',
400
- fontWeight: '600',
401
- textAlign: 'center',
402
- },
403
- });
@@ -1,250 +0,0 @@
1
- /**
2
- * Datalyr React Native SDK Example
3
- *
4
- * This example shows how to integrate the Datalyr SDK into a React Native app
5
- * for mobile attribution and event tracking.
6
- */
7
-
8
- import React, { useEffect, useState } from 'react';
9
- import {
10
- View,
11
- Text,
12
- Button,
13
- StyleSheet,
14
- Alert,
15
- ScrollView,
16
- StatusBar,
17
- } from 'react-native';
18
- import { datalyr } from '@datalyr/react-native';
19
-
20
- const App: React.FC = () => {
21
- const [sdkStatus, setSdkStatus] = useState<any>(null);
22
- const [isInitialized, setIsInitialized] = useState(false);
23
-
24
- useEffect(() => {
25
- initializeDatalyr();
26
- }, []);
27
-
28
- const initializeDatalyr = async () => {
29
- try {
30
- // Initialize with your workspace ID and API key
31
- await datalyr.initialize({
32
- workspaceId: 'ozLZblQ8hN', // Replace with your actual workspace ID
33
- apiKey: 'dk_your_api_key', // Required for authentication
34
- debug: true, // Enable debug logging
35
- enableAttribution: true, // ✅ Deep link attribution tracking
36
- });
37
-
38
- setIsInitialized(true);
39
- updateStatus();
40
-
41
- // Track app launch
42
- await datalyr.track('app_launch', {
43
- app_version: '1.0.0',
44
- platform: 'ios', // or 'android'
45
- });
46
-
47
- console.log('Datalyr SDK initialized successfully!');
48
- } catch (error) {
49
- console.error('Failed to initialize Datalyr SDK:', error);
50
- Alert.alert('Error', 'Failed to initialize Datalyr SDK');
51
- }
52
- };
53
-
54
- const updateStatus = () => {
55
- const status = datalyr.getStatus();
56
- setSdkStatus(status);
57
- };
58
-
59
- const trackPurchase = async () => {
60
- try {
61
- await datalyr.track('purchase', {
62
- value: 29.99,
63
- currency: 'USD',
64
- item_id: 'product_123',
65
- item_name: 'Premium Subscription',
66
- category: 'subscription',
67
- });
68
-
69
- Alert.alert('Success', 'Purchase event tracked!');
70
- updateStatus();
71
- } catch (error) {
72
- console.error('Error tracking purchase:', error);
73
- Alert.alert('Error', 'Failed to track purchase');
74
- }
75
- };
76
-
77
- const trackScreenView = async () => {
78
- try {
79
- await datalyr.screen('home_screen', {
80
- section: 'main',
81
- user_type: 'premium',
82
- });
83
-
84
- Alert.alert('Success', 'Pageview tracked!');
85
- updateStatus();
86
- } catch (error) {
87
- console.error('Error tracking pageview:', error);
88
- Alert.alert('Error', 'Failed to track pageview');
89
- }
90
- };
91
-
92
- const identifyUser = async () => {
93
- try {
94
- await datalyr.identify('user_12345', {
95
- email: 'user@example.com',
96
- name: 'John Doe',
97
- plan: 'premium',
98
- signup_date: new Date().toISOString(),
99
- });
100
-
101
- Alert.alert('Success', 'User identified!');
102
- updateStatus();
103
- } catch (error) {
104
- console.error('Error identifying user:', error);
105
- Alert.alert('Error', 'Failed to identify user');
106
- }
107
- };
108
-
109
- const flushEvents = async () => {
110
- try {
111
- await datalyr.flush();
112
- Alert.alert('Success', 'Events flushed!');
113
- updateStatus();
114
- } catch (error) {
115
- console.error('Error flushing events:', error);
116
- Alert.alert('Error', 'Failed to flush events');
117
- }
118
- };
119
-
120
- const resetUser = async () => {
121
- try {
122
- await datalyr.reset();
123
- Alert.alert('Success', 'User data reset!');
124
- updateStatus();
125
- } catch (error) {
126
- console.error('Error resetting user:', error);
127
- Alert.alert('Error', 'Failed to reset user');
128
- }
129
- };
130
-
131
- return (
132
- <View style={styles.container}>
133
- <StatusBar barStyle="dark-content" />
134
- <ScrollView style={styles.scrollView} contentContainerStyle={styles.content}>
135
- <Text style={styles.title}>Datalyr SDK Example</Text>
136
-
137
- <View style={styles.statusContainer}>
138
- <Text style={styles.statusTitle}>SDK Status:</Text>
139
- <Text style={styles.statusText}>
140
- Initialized: {isInitialized ? '✅' : '❌'}
141
- </Text>
142
- {sdkStatus && (
143
- <>
144
- <Text style={styles.statusText}>
145
- Workspace: {sdkStatus.workspaceId}
146
- </Text>
147
- <Text style={styles.statusText}>
148
- Visitor ID: {sdkStatus.visitorId.substring(0, 8)}...
149
- </Text>
150
- <Text style={styles.statusText}>
151
- Session ID: {sdkStatus.sessionId.substring(0, 12)}...
152
- </Text>
153
- <Text style={styles.statusText}>
154
- User ID: {sdkStatus.currentUserId || 'Not set'}
155
- </Text>
156
- <Text style={styles.statusText}>
157
- Queue Size: {sdkStatus.queueStats?.queueSize || 0}
158
- </Text>
159
- </>
160
- )}
161
- </View>
162
-
163
- <View style={styles.buttonContainer}>
164
- <Button
165
- title="Track Purchase Event"
166
- onPress={trackPurchase}
167
- disabled={!isInitialized}
168
- />
169
-
170
- <Button
171
- title="Track Pageview"
172
- onPress={trackScreenView}
173
- disabled={!isInitialized}
174
- />
175
-
176
- <Button
177
- title="Identify User"
178
- onPress={identifyUser}
179
- disabled={!isInitialized}
180
- />
181
-
182
- <Button
183
- title="Flush Events"
184
- onPress={flushEvents}
185
- disabled={!isInitialized}
186
- />
187
-
188
- <Button
189
- title="Reset User Data"
190
- onPress={resetUser}
191
- disabled={!isInitialized}
192
- />
193
-
194
- <Button
195
- title="Refresh Status"
196
- onPress={updateStatus}
197
- disabled={!isInitialized}
198
- />
199
- </View>
200
- </ScrollView>
201
- </View>
202
- );
203
- };
204
-
205
- const styles = StyleSheet.create({
206
- container: {
207
- flex: 1,
208
- backgroundColor: '#f5f5f5',
209
- },
210
- scrollView: {
211
- flex: 1,
212
- },
213
- content: {
214
- padding: 20,
215
- },
216
- title: {
217
- fontSize: 24,
218
- fontWeight: 'bold',
219
- textAlign: 'center',
220
- marginBottom: 30,
221
- color: '#333',
222
- },
223
- statusContainer: {
224
- backgroundColor: '#fff',
225
- padding: 15,
226
- borderRadius: 8,
227
- marginBottom: 20,
228
- elevation: 2,
229
- shadowOffset: { width: 0, height: 2 },
230
- shadowOpacity: 0.1,
231
- shadowRadius: 4,
232
- },
233
- statusTitle: {
234
- fontSize: 18,
235
- fontWeight: 'bold',
236
- marginBottom: 10,
237
- color: '#333',
238
- },
239
- statusText: {
240
- fontSize: 14,
241
- marginBottom: 5,
242
- color: '#666',
243
- fontFamily: 'monospace',
244
- },
245
- buttonContainer: {
246
- gap: 10,
247
- },
248
- });
249
-
250
- export default App;