@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.
- package/CHANGELOG.md +24 -141
- package/LICENSE +21 -0
- package/README.md +405 -217
- package/datalyr-react-native.podspec +31 -0
- package/ios/DatalyrNative.m +70 -0
- package/ios/DatalyrNative.swift +275 -0
- package/ios/DatalyrSKAdNetwork.m +26 -0
- package/lib/datalyr-sdk.d.ts +64 -3
- package/lib/datalyr-sdk.js +322 -3
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -2
- package/lib/integrations/index.d.ts +6 -0
- package/lib/integrations/index.js +6 -0
- package/lib/integrations/meta-integration.d.ts +76 -0
- package/lib/integrations/meta-integration.js +218 -0
- package/lib/integrations/tiktok-integration.d.ts +82 -0
- package/lib/integrations/tiktok-integration.js +356 -0
- package/lib/native/DatalyrNativeBridge.d.ts +31 -0
- package/lib/native/DatalyrNativeBridge.js +168 -0
- package/lib/native/index.d.ts +5 -0
- package/lib/native/index.js +5 -0
- package/lib/types.d.ts +29 -0
- package/package.json +10 -5
- package/src/datalyr-sdk-expo.ts +957 -0
- package/src/datalyr-sdk.ts +419 -19
- package/src/expo.ts +38 -18
- package/src/index.ts +5 -2
- package/src/integrations/index.ts +7 -0
- package/src/integrations/meta-integration.ts +238 -0
- package/src/integrations/tiktok-integration.ts +360 -0
- package/src/native/DatalyrNativeBridge.ts +271 -0
- package/src/native/index.ts +11 -0
- package/src/types.ts +39 -0
- package/src/utils-expo.ts +25 -3
- package/src/utils-interface.ts +38 -0
- package/EXPO_INSTALL.md +0 -297
- package/INSTALL.md +0 -402
- package/examples/attribution-example.tsx +0 -377
- package/examples/auto-events-example.tsx +0 -403
- package/examples/example.tsx +0 -250
- package/examples/skadnetwork-example.tsx +0 -380
- package/examples/test-implementation.tsx +0 -163
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Datalyr Attribution Example
|
|
3
|
-
*
|
|
4
|
-
* This example shows how to implement and test deep link attribution
|
|
5
|
-
* for Facebook, TikTok, Google Ads, and other ad platforms.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import React, { useEffect, useState } from 'react';
|
|
9
|
-
import {
|
|
10
|
-
View,
|
|
11
|
-
Text,
|
|
12
|
-
Button,
|
|
13
|
-
StyleSheet,
|
|
14
|
-
Alert,
|
|
15
|
-
ScrollView,
|
|
16
|
-
TextInput,
|
|
17
|
-
Linking,
|
|
18
|
-
} from 'react-native';
|
|
19
|
-
import { datalyr } from '@datalyr/react-native';
|
|
20
|
-
|
|
21
|
-
const AttributionExample: React.FC = () => {
|
|
22
|
-
const [attributionData, setAttributionData] = useState<any>(null);
|
|
23
|
-
const [testUrl, setTestUrl] = useState('');
|
|
24
|
-
const [isInitialized, setIsInitialized] = useState(false);
|
|
25
|
-
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
initializeSDK();
|
|
28
|
-
}, []);
|
|
29
|
-
|
|
30
|
-
const initializeSDK = async () => {
|
|
31
|
-
try {
|
|
32
|
-
await datalyr.initialize({
|
|
33
|
-
workspaceId: 'ozLZblQ8hN',
|
|
34
|
-
apiKey: 'dk_your_api_key', // Required for authentication
|
|
35
|
-
debug: true,
|
|
36
|
-
enableAttribution: true, // ✅ Enable deep link attribution tracking
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
setIsInitialized(true);
|
|
40
|
-
refreshAttributionData();
|
|
41
|
-
|
|
42
|
-
console.log('Datalyr SDK initialized with attribution tracking!');
|
|
43
|
-
} catch (error) {
|
|
44
|
-
console.error('Failed to initialize SDK:', error);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const refreshAttributionData = () => {
|
|
49
|
-
if (isInitialized) {
|
|
50
|
-
const data = datalyr.getAttributionData();
|
|
51
|
-
const status = datalyr.getStatus();
|
|
52
|
-
setAttributionData({
|
|
53
|
-
...data,
|
|
54
|
-
summary: status.attribution,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const testDeepLink = async (url: string) => {
|
|
60
|
-
try {
|
|
61
|
-
console.log('Testing deep link:', url);
|
|
62
|
-
|
|
63
|
-
// Simulate opening the app with a deep link
|
|
64
|
-
// In a real app, this would happen automatically when the app is opened
|
|
65
|
-
await Linking.openURL(url);
|
|
66
|
-
|
|
67
|
-
// Refresh attribution data to see if parameters were captured
|
|
68
|
-
setTimeout(() => {
|
|
69
|
-
refreshAttributionData();
|
|
70
|
-
Alert.alert('Deep Link Tested', 'Check attribution data for captured parameters');
|
|
71
|
-
}, 1000);
|
|
72
|
-
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.error('Error testing deep link:', error);
|
|
75
|
-
Alert.alert('Error', 'Failed to test deep link');
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const simulateInstall = async () => {
|
|
80
|
-
try {
|
|
81
|
-
// Clear existing attribution data to simulate fresh install
|
|
82
|
-
await datalyr.setAttributionData({});
|
|
83
|
-
|
|
84
|
-
Alert.alert(
|
|
85
|
-
'Install Simulation',
|
|
86
|
-
'Attribution data cleared. The next app launch will be treated as an install.',
|
|
87
|
-
[
|
|
88
|
-
{ text: 'OK', onPress: refreshAttributionData }
|
|
89
|
-
]
|
|
90
|
-
);
|
|
91
|
-
} catch (error) {
|
|
92
|
-
console.error('Error simulating install:', error);
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const setCustomAttribution = async () => {
|
|
97
|
-
try {
|
|
98
|
-
await datalyr.setAttributionData({
|
|
99
|
-
campaign_source: 'facebook',
|
|
100
|
-
campaign_medium: 'paid_social',
|
|
101
|
-
campaign_name: 'summer_sale_2024',
|
|
102
|
-
fbclid: 'test_fbclid_123456',
|
|
103
|
-
custom_param: 'test_value',
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
refreshAttributionData();
|
|
107
|
-
Alert.alert('Success', 'Custom attribution data set');
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error('Error setting custom attribution:', error);
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// Sample test URLs for different platforms
|
|
114
|
-
const testUrls = {
|
|
115
|
-
// Datalyr LYR System (YOUR MAIN TRACKING!)
|
|
116
|
-
lyr_campaign: 'myapp://open?lyr=summer_sale_mobile&utm_source=facebook&utm_medium=paid_social&utm_campaign=summer_sale&fbclid=IwAR123abc',
|
|
117
|
-
|
|
118
|
-
// Facebook Attribution
|
|
119
|
-
facebook: 'myapp://open?utm_source=facebook&utm_medium=paid_social&utm_campaign=summer_sale&fbclid=IwAR123abc&lyr=fb_summer_2024',
|
|
120
|
-
|
|
121
|
-
// TikTok Attribution
|
|
122
|
-
tiktok: 'myapp://open?utm_source=tiktok&utm_medium=video&utm_campaign=viral_video&ttclid=tiktok123xyz&lyr=tt_viral_campaign',
|
|
123
|
-
|
|
124
|
-
// Google Attribution
|
|
125
|
-
google: 'myapp://open?utm_source=google&utm_medium=search&utm_campaign=brand_search&gclid=google456def&lyr=google_brand_search',
|
|
126
|
-
|
|
127
|
-
// Partner/Affiliate
|
|
128
|
-
partner: 'myapp://open?utm_source=partner&partner_id=partner123&affiliate_id=aff456&lyr=partner_campaign_q4',
|
|
129
|
-
|
|
130
|
-
// Complete attribution example
|
|
131
|
-
comprehensive: 'myapp://open?lyr=comprehensive_test&utm_source=facebook&utm_medium=paid_social&utm_campaign=q4_sale&utm_term=mobile_app&utm_content=video_ad&fbclid=IwAR123abc&campaign_id=camp123&ad_id=ad456&creative_id=cr789&placement_id=pl001',
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<View style={styles.container}>
|
|
136
|
-
<ScrollView style={styles.scrollView} contentContainerStyle={styles.content}>
|
|
137
|
-
<Text style={styles.title}>Attribution Testing</Text>
|
|
138
|
-
|
|
139
|
-
{/* Attribution Status */}
|
|
140
|
-
<View style={styles.section}>
|
|
141
|
-
<Text style={styles.sectionTitle}>Attribution Status</Text>
|
|
142
|
-
{attributionData ? (
|
|
143
|
-
<View style={styles.dataContainer}>
|
|
144
|
-
<Text style={styles.dataLabel}>Install Status:</Text>
|
|
145
|
-
<Text style={styles.dataValue}>
|
|
146
|
-
{attributionData.summary?.isInstall ? '🆕 First Install' : '🔄 Returning User'}
|
|
147
|
-
</Text>
|
|
148
|
-
|
|
149
|
-
<Text style={styles.dataLabel}>Attribution Source:</Text>
|
|
150
|
-
<Text style={styles.dataValue}>
|
|
151
|
-
{attributionData.campaign_source || 'Unknown'}
|
|
152
|
-
</Text>
|
|
153
|
-
|
|
154
|
-
<Text style={styles.dataLabel}>Campaign:</Text>
|
|
155
|
-
<Text style={styles.dataValue}>
|
|
156
|
-
{attributionData.campaign_name || 'Unknown'}
|
|
157
|
-
</Text>
|
|
158
|
-
|
|
159
|
-
<Text style={styles.dataLabel}>LYR Tag:</Text>
|
|
160
|
-
<Text style={styles.dataValue}>
|
|
161
|
-
{attributionData.lyr || 'Not set'}
|
|
162
|
-
</Text>
|
|
163
|
-
|
|
164
|
-
<Text style={styles.dataLabel}>Click IDs:</Text>
|
|
165
|
-
{attributionData.fbclid && (
|
|
166
|
-
<Text style={styles.dataValue}>Facebook: {attributionData.fbclid}</Text>
|
|
167
|
-
)}
|
|
168
|
-
{attributionData.ttclid && (
|
|
169
|
-
<Text style={styles.dataValue}>TikTok: {attributionData.ttclid}</Text>
|
|
170
|
-
)}
|
|
171
|
-
{attributionData.gclid && (
|
|
172
|
-
<Text style={styles.dataValue}>Google: {attributionData.gclid}</Text>
|
|
173
|
-
)}
|
|
174
|
-
|
|
175
|
-
<Text style={styles.dataLabel}>Install Time:</Text>
|
|
176
|
-
<Text style={styles.dataValue}>
|
|
177
|
-
{attributionData.install_time ?
|
|
178
|
-
new Date(attributionData.install_time).toLocaleString() :
|
|
179
|
-
'Not set'
|
|
180
|
-
}
|
|
181
|
-
</Text>
|
|
182
|
-
</View>
|
|
183
|
-
) : (
|
|
184
|
-
<Text style={styles.noData}>No attribution data available</Text>
|
|
185
|
-
)}
|
|
186
|
-
</View>
|
|
187
|
-
|
|
188
|
-
{/* Test Deep Links */}
|
|
189
|
-
<View style={styles.section}>
|
|
190
|
-
<Text style={styles.sectionTitle}>Test Attribution Links</Text>
|
|
191
|
-
|
|
192
|
-
<Button
|
|
193
|
-
title="Test Facebook Attribution"
|
|
194
|
-
onPress={() => testDeepLink(testUrls.facebook)}
|
|
195
|
-
disabled={!isInitialized}
|
|
196
|
-
/>
|
|
197
|
-
|
|
198
|
-
<Button
|
|
199
|
-
title="Test TikTok Attribution"
|
|
200
|
-
onPress={() => testDeepLink(testUrls.tiktok)}
|
|
201
|
-
disabled={!isInitialized}
|
|
202
|
-
/>
|
|
203
|
-
|
|
204
|
-
<Button
|
|
205
|
-
title="Test Google Attribution"
|
|
206
|
-
onPress={() => testDeepLink(testUrls.google)}
|
|
207
|
-
disabled={!isInitialized}
|
|
208
|
-
/>
|
|
209
|
-
|
|
210
|
-
<Button
|
|
211
|
-
title="Test LYR Campaign"
|
|
212
|
-
onPress={() => testDeepLink(testUrls.lyr_campaign)}
|
|
213
|
-
disabled={!isInitialized}
|
|
214
|
-
/>
|
|
215
|
-
|
|
216
|
-
<Button
|
|
217
|
-
title="Test Partner Attribution"
|
|
218
|
-
onPress={() => testDeepLink(testUrls.partner)}
|
|
219
|
-
disabled={!isInitialized}
|
|
220
|
-
/>
|
|
221
|
-
|
|
222
|
-
<Button
|
|
223
|
-
title="Test Comprehensive Attribution"
|
|
224
|
-
onPress={() => testDeepLink(testUrls.comprehensive)}
|
|
225
|
-
disabled={!isInitialized}
|
|
226
|
-
/>
|
|
227
|
-
</View>
|
|
228
|
-
|
|
229
|
-
{/* Custom URL Testing */}
|
|
230
|
-
<View style={styles.section}>
|
|
231
|
-
<Text style={styles.sectionTitle}>Test Custom URL</Text>
|
|
232
|
-
<TextInput
|
|
233
|
-
style={styles.input}
|
|
234
|
-
placeholder="Enter deep link URL to test..."
|
|
235
|
-
value={testUrl}
|
|
236
|
-
onChangeText={setTestUrl}
|
|
237
|
-
multiline
|
|
238
|
-
/>
|
|
239
|
-
<Button
|
|
240
|
-
title="Test Custom URL"
|
|
241
|
-
onPress={() => testDeepLink(testUrl)}
|
|
242
|
-
disabled={!isInitialized || !testUrl}
|
|
243
|
-
/>
|
|
244
|
-
</View>
|
|
245
|
-
|
|
246
|
-
{/* Controls */}
|
|
247
|
-
<View style={styles.section}>
|
|
248
|
-
<Text style={styles.sectionTitle}>Controls</Text>
|
|
249
|
-
|
|
250
|
-
<Button
|
|
251
|
-
title="Refresh Attribution Data"
|
|
252
|
-
onPress={refreshAttributionData}
|
|
253
|
-
disabled={!isInitialized}
|
|
254
|
-
/>
|
|
255
|
-
|
|
256
|
-
<Button
|
|
257
|
-
title="Set Custom Attribution"
|
|
258
|
-
onPress={setCustomAttribution}
|
|
259
|
-
disabled={!isInitialized}
|
|
260
|
-
/>
|
|
261
|
-
|
|
262
|
-
<Button
|
|
263
|
-
title="Simulate Fresh Install"
|
|
264
|
-
onPress={simulateInstall}
|
|
265
|
-
disabled={!isInitialized}
|
|
266
|
-
/>
|
|
267
|
-
</View>
|
|
268
|
-
|
|
269
|
-
{/* Attribution Flow Explanation */}
|
|
270
|
-
<View style={styles.section}>
|
|
271
|
-
<Text style={styles.sectionTitle}>How It Works</Text>
|
|
272
|
-
<Text style={styles.explanation}>
|
|
273
|
-
1. User clicks ad with attribution parameters (fbclid, ttclid, etc.)
|
|
274
|
-
{'\n'}2. App store opens with deep link containing parameters
|
|
275
|
-
{'\n'}3. User downloads and opens app
|
|
276
|
-
{'\n'}4. SDK captures parameters from deep link
|
|
277
|
-
{'\n'}5. Install event is tracked with attribution data
|
|
278
|
-
{'\n'}6. Future events include attribution for postbacks
|
|
279
|
-
</Text>
|
|
280
|
-
</View>
|
|
281
|
-
|
|
282
|
-
{/* Debug Info */}
|
|
283
|
-
{__DEV__ && attributionData && (
|
|
284
|
-
<View style={styles.section}>
|
|
285
|
-
<Text style={styles.sectionTitle}>Debug Info</Text>
|
|
286
|
-
<Text style={styles.debugText}>
|
|
287
|
-
{JSON.stringify(attributionData, null, 2)}
|
|
288
|
-
</Text>
|
|
289
|
-
</View>
|
|
290
|
-
)}
|
|
291
|
-
</ScrollView>
|
|
292
|
-
</View>
|
|
293
|
-
);
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const styles = StyleSheet.create({
|
|
297
|
-
container: {
|
|
298
|
-
flex: 1,
|
|
299
|
-
backgroundColor: '#f5f5f5',
|
|
300
|
-
},
|
|
301
|
-
scrollView: {
|
|
302
|
-
flex: 1,
|
|
303
|
-
},
|
|
304
|
-
content: {
|
|
305
|
-
padding: 20,
|
|
306
|
-
},
|
|
307
|
-
title: {
|
|
308
|
-
fontSize: 24,
|
|
309
|
-
fontWeight: 'bold',
|
|
310
|
-
textAlign: 'center',
|
|
311
|
-
marginBottom: 30,
|
|
312
|
-
color: '#333',
|
|
313
|
-
},
|
|
314
|
-
section: {
|
|
315
|
-
backgroundColor: '#fff',
|
|
316
|
-
padding: 15,
|
|
317
|
-
borderRadius: 8,
|
|
318
|
-
marginBottom: 15,
|
|
319
|
-
elevation: 2,
|
|
320
|
-
shadowOffset: { width: 0, height: 2 },
|
|
321
|
-
shadowOpacity: 0.1,
|
|
322
|
-
shadowRadius: 4,
|
|
323
|
-
gap: 10,
|
|
324
|
-
},
|
|
325
|
-
sectionTitle: {
|
|
326
|
-
fontSize: 18,
|
|
327
|
-
fontWeight: 'bold',
|
|
328
|
-
marginBottom: 10,
|
|
329
|
-
color: '#333',
|
|
330
|
-
},
|
|
331
|
-
dataContainer: {
|
|
332
|
-
gap: 5,
|
|
333
|
-
},
|
|
334
|
-
dataLabel: {
|
|
335
|
-
fontSize: 14,
|
|
336
|
-
fontWeight: '600',
|
|
337
|
-
color: '#666',
|
|
338
|
-
marginTop: 8,
|
|
339
|
-
},
|
|
340
|
-
dataValue: {
|
|
341
|
-
fontSize: 14,
|
|
342
|
-
color: '#333',
|
|
343
|
-
fontFamily: 'monospace',
|
|
344
|
-
backgroundColor: '#f8f8f8',
|
|
345
|
-
padding: 4,
|
|
346
|
-
borderRadius: 4,
|
|
347
|
-
},
|
|
348
|
-
noData: {
|
|
349
|
-
fontSize: 14,
|
|
350
|
-
color: '#999',
|
|
351
|
-
fontStyle: 'italic',
|
|
352
|
-
},
|
|
353
|
-
input: {
|
|
354
|
-
borderWidth: 1,
|
|
355
|
-
borderColor: '#ddd',
|
|
356
|
-
borderRadius: 8,
|
|
357
|
-
padding: 12,
|
|
358
|
-
fontSize: 14,
|
|
359
|
-
minHeight: 80,
|
|
360
|
-
textAlignVertical: 'top',
|
|
361
|
-
},
|
|
362
|
-
explanation: {
|
|
363
|
-
fontSize: 14,
|
|
364
|
-
color: '#666',
|
|
365
|
-
lineHeight: 20,
|
|
366
|
-
},
|
|
367
|
-
debugText: {
|
|
368
|
-
fontSize: 12,
|
|
369
|
-
fontFamily: 'monospace',
|
|
370
|
-
color: '#333',
|
|
371
|
-
backgroundColor: '#f8f8f8',
|
|
372
|
-
padding: 8,
|
|
373
|
-
borderRadius: 4,
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
export default AttributionExample;
|