@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,380 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
- import { View, Text, Button, StyleSheet, ScrollView, Alert } from 'react-native';
3
- import { Datalyr } from '../src/index';
4
-
5
- /**
6
- * 🚀 SKAdNetwork Example - React Native
7
- *
8
- * This example demonstrates how to use Datalyr's automatic SKAdNetwork conversion value encoding
9
- * to compete with AppsFlyer/Adjust at 90% cost savings.
10
- *
11
- * Features demonstrated:
12
- * - Industry template initialization (E-commerce, Gaming, Subscription)
13
- * - Automatic conversion value encoding for iOS 14+ attribution
14
- * - Revenue tier optimization (8 tiers: $0-1, $1-5, $5-10, $10-25, $25-50, $50-100, $100-250, $250+)
15
- * - Event tracking with automatic SKAdNetwork.updateConversionValue() calls
16
- * - Testing and debugging conversion values
17
- */
18
-
19
- interface TestResult {
20
- event: string;
21
- conversionValue: number | null;
22
- properties?: any;
23
- }
24
-
25
- export default function SKAdNetworkExample() {
26
- const [initialized, setInitialized] = useState(false);
27
- const [currentTemplate, setCurrentTemplate] = useState<'ecommerce' | 'gaming' | 'subscription'>('ecommerce');
28
- const [testResults, setTestResults] = useState<TestResult[]>([]);
29
-
30
- useEffect(() => {
31
- initializeDatalyr();
32
- }, []);
33
-
34
- // Initialize with E-commerce template
35
- const initializeDatalyr = async () => {
36
- try {
37
- await Datalyr.initialize({
38
- workspaceId: 'your-workspace-id',
39
- apiKey: 'dk_your_api_key',
40
- skadTemplate: 'ecommerce', // Industry template for automatic optimization
41
- debug: true, // Enable detailed SKAdNetwork logging
42
- enableAttribution: true,
43
- autoEvents: {
44
- trackSessions: true,
45
- trackScreenViews: true,
46
- },
47
- });
48
-
49
- setInitialized(true);
50
- console.log('✅ Datalyr initialized with SKAdNetwork E-commerce template');
51
-
52
- } catch (error) {
53
- console.error('❌ Failed to initialize Datalyr:', error);
54
- Alert.alert('Error', 'Failed to initialize SDK');
55
- }
56
- };
57
-
58
- // Switch between different industry templates
59
- const switchTemplate = async (template: 'ecommerce' | 'gaming' | 'subscription') => {
60
- try {
61
- await Datalyr.initialize({
62
- workspaceId: 'your-workspace-id',
63
- apiKey: 'dk_your_api_key',
64
- skadTemplate: template,
65
- debug: true,
66
- });
67
- setCurrentTemplate(template);
68
- setTestResults([]);
69
- console.log(`✅ Switched to ${template} template`);
70
- } catch (error) {
71
- console.error(`❌ Failed to switch to ${template} template:`, error);
72
- }
73
- };
74
-
75
- // Test conversion value encoding without sending to Apple
76
- const testConversionValue = (event: string, properties?: any) => {
77
- const conversionValue = Datalyr.getConversionValue(event, properties);
78
- const result: TestResult = { event, conversionValue, properties };
79
- setTestResults(prev => [...prev, result]);
80
-
81
- console.log(`🧪 Test - Event: ${event}, Conversion Value: ${conversionValue}`, properties);
82
- return conversionValue;
83
- };
84
-
85
- // E-commerce Examples
86
- const trackEcommerceEvents = async () => {
87
- console.log('🛒 Tracking E-commerce Events');
88
-
89
- // Track purchase with automatic revenue encoding
90
- await Datalyr.trackPurchase(29.99, 'USD', 'premium_plan');
91
- testConversionValue('purchase', { revenue: 29.99, currency: 'USD' });
92
-
93
- // Track funnel events
94
- await Datalyr.trackWithSKAdNetwork('view_item', { product_id: 'shirt_001' });
95
- testConversionValue('view_item', { product_id: 'shirt_001' });
96
-
97
- await Datalyr.trackWithSKAdNetwork('add_to_cart', { product_id: 'shirt_001', value: 25.99 });
98
- testConversionValue('add_to_cart', { product_id: 'shirt_001' });
99
-
100
- await Datalyr.trackWithSKAdNetwork('begin_checkout', { cart_value: 89.97 });
101
- testConversionValue('begin_checkout', { cart_value: 89.97 });
102
-
103
- await Datalyr.trackWithSKAdNetwork('signup', { source: 'homepage' });
104
- testConversionValue('signup', { source: 'homepage' });
105
-
106
- Alert.alert('E-commerce Events', 'Tracked purchase, cart events, and signup with automatic SKAdNetwork encoding');
107
- };
108
-
109
- // Gaming Examples
110
- const trackGamingEvents = async () => {
111
- console.log('🎮 Tracking Gaming Events');
112
-
113
- // Track game progression
114
- await Datalyr.trackWithSKAdNetwork('tutorial_complete', { level: 1 });
115
- testConversionValue('tutorial_complete', { level: 1 });
116
-
117
- await Datalyr.trackWithSKAdNetwork('level_complete', { level: 5, score: 1250 });
118
- testConversionValue('level_complete', { level: 5, score: 1250 });
119
-
120
- await Datalyr.trackWithSKAdNetwork('achievement_unlocked', { achievement: 'first_win' });
121
- testConversionValue('achievement_unlocked', { achievement: 'first_win' });
122
-
123
- // Track in-app purchase
124
- await Datalyr.trackPurchase(4.99, 'USD', 'extra_lives');
125
- testConversionValue('purchase', { revenue: 4.99, currency: 'USD' });
126
-
127
- await Datalyr.trackWithSKAdNetwork('ad_watched', { ad_type: 'rewarded_video' });
128
- testConversionValue('ad_watched', { ad_type: 'rewarded_video' });
129
-
130
- Alert.alert('Gaming Events', 'Tracked game progression and IAP with automatic SKAdNetwork encoding');
131
- };
132
-
133
- // Subscription Examples
134
- const trackSubscriptionEvents = async () => {
135
- console.log('📱 Tracking Subscription Events');
136
-
137
- // Track subscription funnel
138
- await Datalyr.trackWithSKAdNetwork('trial_start', { plan: 'premium' });
139
- testConversionValue('trial_start', { plan: 'premium' });
140
-
141
- await Datalyr.trackSubscription(9.99, 'USD', 'monthly');
142
- testConversionValue('subscribe', { revenue: 9.99, currency: 'USD' });
143
-
144
- await Datalyr.trackWithSKAdNetwork('upgrade', {
145
- revenue: 19.99,
146
- from_plan: 'basic',
147
- to_plan: 'premium'
148
- });
149
- testConversionValue('upgrade', { revenue: 19.99 });
150
-
151
- await Datalyr.trackWithSKAdNetwork('payment_method_added', { method: 'credit_card' });
152
- testConversionValue('payment_method_added', { method: 'credit_card' });
153
-
154
- Alert.alert('Subscription Events', 'Tracked subscription funnel with automatic SKAdNetwork encoding');
155
- };
156
-
157
- // Test different revenue tiers
158
- const testRevenueTiers = () => {
159
- console.log('💰 Testing Revenue Tiers');
160
-
161
- const testAmounts = [0.5, 2.99, 7.99, 15.99, 35.99, 75.99, 150.99, 299.99];
162
- testAmounts.forEach(amount => {
163
- testConversionValue('purchase', { revenue: amount });
164
- });
165
-
166
- Alert.alert('Revenue Tiers', 'Tested all 8 revenue tiers (check console for values)');
167
- };
168
-
169
- const clearResults = () => {
170
- setTestResults([]);
171
- };
172
-
173
- if (!initialized) {
174
- return (
175
- <View style={styles.container}>
176
- <Text style={styles.title}>Initializing SKAdNetwork...</Text>
177
- </View>
178
- );
179
- }
180
-
181
- return (
182
- <ScrollView style={styles.container}>
183
- <Text style={styles.title}>🚀 SKAdNetwork Example</Text>
184
- <Text style={styles.subtitle}>Compete with AppsFlyer/Adjust at 90% cost savings</Text>
185
-
186
- {/* Template Selector */}
187
- <View style={styles.section}>
188
- <Text style={styles.sectionTitle}>Industry Templates</Text>
189
- <View style={styles.buttonRow}>
190
- {(['ecommerce', 'gaming', 'subscription'] as const).map(template => (
191
- <Button
192
- key={template}
193
- title={template.charAt(0).toUpperCase() + template.slice(1)}
194
- onPress={() => switchTemplate(template)}
195
- color={currentTemplate === template ? '#007AFF' : '#999'}
196
- />
197
- ))}
198
- </View>
199
- <Text style={styles.currentTemplate}>Current: {currentTemplate}</Text>
200
- </View>
201
-
202
- {/* Action Buttons */}
203
- <View style={styles.section}>
204
- <Text style={styles.sectionTitle}>Track Events ({currentTemplate})</Text>
205
-
206
- {currentTemplate === 'ecommerce' && (
207
- <Button title="🛒 Track E-commerce Events" onPress={trackEcommerceEvents} />
208
- )}
209
-
210
- {currentTemplate === 'gaming' && (
211
- <Button title="🎮 Track Gaming Events" onPress={trackGamingEvents} />
212
- )}
213
-
214
- {currentTemplate === 'subscription' && (
215
- <Button title="📱 Track Subscription Events" onPress={trackSubscriptionEvents} />
216
- )}
217
-
218
- <View style={styles.buttonSpacing} />
219
- <Button title="💰 Test Revenue Tiers" onPress={testRevenueTiers} />
220
- </View>
221
-
222
- {/* Test Results */}
223
- <View style={styles.section}>
224
- <View style={styles.resultHeader}>
225
- <Text style={styles.sectionTitle}>Conversion Values (Test Mode)</Text>
226
- <Button title="Clear" onPress={clearResults} />
227
- </View>
228
-
229
- {testResults.length === 0 ? (
230
- <Text style={styles.noResults}>No test results yet. Track some events!</Text>
231
- ) : (
232
- testResults.map((result, index) => (
233
- <View key={index} style={styles.resultItem}>
234
- <Text style={styles.resultEvent}>{result.event}</Text>
235
- <Text style={styles.resultValue}>Value: {result.conversionValue || 0}</Text>
236
- {result.properties && (
237
- <Text style={styles.resultProperties}>
238
- {JSON.stringify(result.properties, null, 2).slice(0, 100)}...
239
- </Text>
240
- )}
241
- </View>
242
- ))
243
- )}
244
- </View>
245
-
246
- {/* Revenue Tier Reference */}
247
- <View style={styles.section}>
248
- <Text style={styles.sectionTitle}>Revenue Tier Reference</Text>
249
- <View style={styles.tierTable}>
250
- {[
251
- ['$0-1', 'Tier 0'],
252
- ['$1-5', 'Tier 1'],
253
- ['$5-10', 'Tier 2'],
254
- ['$10-25', 'Tier 3'],
255
- ['$25-50', 'Tier 4'],
256
- ['$50-100', 'Tier 5'],
257
- ['$100-250', 'Tier 6'],
258
- ['$250+', 'Tier 7'],
259
- ].map(([range, tier], index) => (
260
- <View key={index} style={styles.tierRow}>
261
- <Text style={styles.tierRange}>{range}</Text>
262
- <Text style={styles.tierValue}>{tier}</Text>
263
- </View>
264
- ))}
265
- </View>
266
- </View>
267
-
268
- <View style={styles.footer}>
269
- <Text style={styles.footerText}>
270
- 🎯 Same functionality as AppsFlyer/Adjust{'\n'}
271
- 💰 90% cost savings{'\n'}
272
- 📊 Unified web + mobile dashboard
273
- </Text>
274
- </View>
275
- </ScrollView>
276
- );
277
- }
278
-
279
- const styles = StyleSheet.create({
280
- container: {
281
- flex: 1,
282
- padding: 20,
283
- backgroundColor: '#f5f5f5',
284
- },
285
- title: {
286
- fontSize: 24,
287
- fontWeight: 'bold',
288
- textAlign: 'center',
289
- marginBottom: 5,
290
- },
291
- subtitle: {
292
- fontSize: 16,
293
- textAlign: 'center',
294
- color: '#666',
295
- marginBottom: 20,
296
- },
297
- section: {
298
- backgroundColor: 'white',
299
- padding: 15,
300
- marginBottom: 15,
301
- borderRadius: 10,
302
- },
303
- sectionTitle: {
304
- fontSize: 18,
305
- fontWeight: 'bold',
306
- marginBottom: 10,
307
- },
308
- buttonRow: {
309
- flexDirection: 'row',
310
- justifyContent: 'space-around',
311
- marginBottom: 10,
312
- },
313
- currentTemplate: {
314
- textAlign: 'center',
315
- fontStyle: 'italic',
316
- color: '#666',
317
- },
318
- buttonSpacing: {
319
- height: 10,
320
- },
321
- resultHeader: {
322
- flexDirection: 'row',
323
- justifyContent: 'space-between',
324
- alignItems: 'center',
325
- marginBottom: 10,
326
- },
327
- noResults: {
328
- textAlign: 'center',
329
- color: '#999',
330
- fontStyle: 'italic',
331
- },
332
- resultItem: {
333
- padding: 10,
334
- backgroundColor: '#f8f8f8',
335
- marginBottom: 5,
336
- borderRadius: 5,
337
- },
338
- resultEvent: {
339
- fontWeight: 'bold',
340
- fontSize: 16,
341
- },
342
- resultValue: {
343
- color: '#007AFF',
344
- fontSize: 14,
345
- },
346
- resultProperties: {
347
- color: '#666',
348
- fontSize: 12,
349
- marginTop: 5,
350
- },
351
- tierTable: {
352
- borderWidth: 1,
353
- borderColor: '#ddd',
354
- borderRadius: 5,
355
- },
356
- tierRow: {
357
- flexDirection: 'row',
358
- justifyContent: 'space-between',
359
- padding: 10,
360
- borderBottomWidth: 1,
361
- borderBottomColor: '#eee',
362
- },
363
- tierRange: {
364
- fontWeight: 'bold',
365
- },
366
- tierValue: {
367
- color: '#666',
368
- },
369
- footer: {
370
- padding: 15,
371
- backgroundColor: '#e8f4f8',
372
- borderRadius: 10,
373
- marginBottom: 20,
374
- },
375
- footerText: {
376
- textAlign: 'center',
377
- color: '#666',
378
- lineHeight: 20,
379
- },
380
- });
@@ -1,163 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import { Button, View, Text, StyleSheet } from 'react-native';
3
- import { Datalyr } from '@datalyr/react-native';
4
-
5
- // Initialize SDK with server-side API
6
- const initializeSDK = async () => {
7
- await Datalyr.initialize({
8
- apiKey: 'dk_your_api_key_here', // Required for v1.0.0
9
- // workspaceId is now optional
10
- useServerTracking: true, // Default: true (uses https://api.datalyr.com)
11
- debug: true,
12
- enableAutoEvents: true,
13
- enableAttribution: true,
14
- skadTemplate: 'ecommerce', // For SKAdNetwork support
15
- });
16
-
17
- console.log('Datalyr SDK initialized with server-side tracking');
18
- };
19
-
20
- export default function TestApp() {
21
- useEffect(() => {
22
- initializeSDK();
23
-
24
- // Track app open event
25
- Datalyr.track('App Opened', {
26
- version: '1.0.0',
27
- source: 'test_implementation',
28
- });
29
- }, []);
30
-
31
- const testUserIdentification = async () => {
32
- await Datalyr.identify('test_user_123', {
33
- email: 'user@example.com',
34
- name: 'Test User',
35
- plan: 'premium',
36
- company: 'Test Company',
37
- });
38
- console.log('User identified');
39
- };
40
-
41
- const testEventTracking = async () => {
42
- // Standard event tracking
43
- await Datalyr.track('Button Clicked', {
44
- button_name: 'test_button',
45
- screen: 'test_screen',
46
- });
47
-
48
- console.log('Event tracked');
49
- };
50
-
51
- const testPurchaseTracking = async () => {
52
- // Track purchase with automatic SKAdNetwork conversion
53
- await Datalyr.trackPurchase(99.99, 'USD', 'premium_subscription');
54
- console.log('Purchase tracked with SKAdNetwork');
55
- };
56
-
57
- const testScreenTracking = async () => {
58
- await Datalyr.screen('Test Screen', {
59
- previous_screen: 'Home',
60
- user_action: 'navigation',
61
- });
62
- console.log('Screen view tracked');
63
- };
64
-
65
- const testAttributionData = async () => {
66
- // Set custom attribution data
67
- await Datalyr.setAttributionData({
68
- campaign: 'summer_sale',
69
- source: 'facebook',
70
- medium: 'social',
71
- fbclid: 'test_fbclid_123',
72
- });
73
-
74
- // Get current attribution
75
- const attribution = Datalyr.getAttributionData();
76
- console.log('Attribution data:', attribution);
77
- };
78
-
79
- const testSessionManagement = async () => {
80
- // Get current session
81
- const session = Datalyr.getCurrentSession();
82
- console.log('Current session:', session);
83
-
84
- // End session manually if needed
85
- await Datalyr.endSession();
86
- console.log('Session ended');
87
- };
88
-
89
- const testRevenue = async () => {
90
- // Track subscription
91
- await Datalyr.trackSubscription(49.99, 'USD', 'monthly_pro');
92
-
93
- // Track custom revenue event
94
- await Datalyr.trackRevenue('In-App Purchase', {
95
- product_id: 'coins_1000',
96
- amount: 4.99,
97
- currency: 'USD',
98
- quantity: 1,
99
- });
100
-
101
- console.log('Revenue events tracked');
102
- };
103
-
104
- const testFlush = async () => {
105
- // Force flush all queued events
106
- await Datalyr.flush();
107
- console.log('Events flushed');
108
- };
109
-
110
- const testReset = async () => {
111
- // Reset user session (logout)
112
- await Datalyr.reset();
113
- console.log('User session reset');
114
- };
115
-
116
- const getStatus = () => {
117
- const status = Datalyr.getStatus();
118
- console.log('SDK Status:', status);
119
- };
120
-
121
- return (
122
- <View style={styles.container}>
123
- <Text style={styles.title}>Datalyr SDK v1.0.0 Test</Text>
124
- <Text style={styles.subtitle}>Server-Side Tracking API</Text>
125
-
126
- <View style={styles.buttonContainer}>
127
- <Button title="Identify User" onPress={testUserIdentification} />
128
- <Button title="Track Event" onPress={testEventTracking} />
129
- <Button title="Track Purchase" onPress={testPurchaseTracking} />
130
- <Button title="Track Screen" onPress={testScreenTracking} />
131
- <Button title="Test Attribution" onPress={testAttributionData} />
132
- <Button title="Test Session" onPress={testSessionManagement} />
133
- <Button title="Track Revenue" onPress={testRevenue} />
134
- <Button title="Flush Events" onPress={testFlush} />
135
- <Button title="Reset Session" onPress={testReset} />
136
- <Button title="Get Status" onPress={getStatus} />
137
- </View>
138
- </View>
139
- );
140
- }
141
-
142
- const styles = StyleSheet.create({
143
- container: {
144
- flex: 1,
145
- padding: 20,
146
- justifyContent: 'center',
147
- },
148
- title: {
149
- fontSize: 24,
150
- fontWeight: 'bold',
151
- textAlign: 'center',
152
- marginBottom: 10,
153
- },
154
- subtitle: {
155
- fontSize: 16,
156
- textAlign: 'center',
157
- marginBottom: 30,
158
- color: '#666',
159
- },
160
- buttonContainer: {
161
- gap: 10,
162
- },
163
- });