@datalyr/react-native 1.1.1 → 1.2.1
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 +31 -140
- package/LICENSE +21 -0
- package/README.md +434 -217
- package/datalyr-react-native.podspec +31 -0
- package/ios/DatalyrNative.m +74 -0
- package/ios/DatalyrNative.swift +332 -0
- package/ios/DatalyrSKAdNetwork.m +26 -0
- package/lib/datalyr-sdk.d.ts +73 -3
- package/lib/datalyr-sdk.js +353 -3
- package/lib/index.d.ts +2 -0
- package/lib/index.js +4 -2
- package/lib/integrations/apple-search-ads-integration.d.ts +43 -0
- package/lib/integrations/apple-search-ads-integration.js +106 -0
- package/lib/integrations/index.d.ts +7 -0
- package/lib/integrations/index.js +7 -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 +57 -0
- package/lib/native/DatalyrNativeBridge.js +187 -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 +11 -5
- package/src/datalyr-sdk-expo.ts +997 -0
- package/src/datalyr-sdk.ts +455 -19
- package/src/expo.ts +42 -18
- package/src/index.ts +8 -2
- package/src/integrations/apple-search-ads-integration.ts +119 -0
- package/src/integrations/index.ts +8 -0
- package/src/integrations/meta-integration.ts +238 -0
- package/src/integrations/tiktok-integration.ts +360 -0
- package/src/native/DatalyrNativeBridge.ts +313 -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
package/README.md
CHANGED
|
@@ -1,27 +1,42 @@
|
|
|
1
1
|
# @datalyr/react-native
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Mobile analytics and attribution SDK for React Native and Expo. Track events, identify users, and capture attribution data from ad platforms.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [How It Works](#how-it-works)
|
|
10
|
+
- [Configuration](#configuration)
|
|
11
|
+
- [Event Tracking](#event-tracking)
|
|
12
|
+
- [Custom Events](#custom-events)
|
|
13
|
+
- [Screen Views](#screen-views)
|
|
14
|
+
- [E-Commerce Events](#e-commerce-events)
|
|
15
|
+
- [User Identity](#user-identity)
|
|
16
|
+
- [Anonymous ID](#anonymous-id)
|
|
17
|
+
- [Identifying Users](#identifying-users)
|
|
18
|
+
- [User Properties](#user-properties)
|
|
19
|
+
- [Attribution](#attribution)
|
|
20
|
+
- [Automatic Capture](#automatic-capture)
|
|
21
|
+
- [Deferred Deep Links](#deferred-deep-links)
|
|
22
|
+
- [Event Queue](#event-queue)
|
|
23
|
+
- [Auto Events](#auto-events)
|
|
24
|
+
- [SKAdNetwork](#skadnetwork)
|
|
25
|
+
- [Platform Integrations](#platform-integrations)
|
|
26
|
+
- [Meta](#meta-facebook)
|
|
27
|
+
- [TikTok](#tiktok)
|
|
28
|
+
- [Apple Search Ads](#apple-search-ads)
|
|
29
|
+
- [Expo Support](#expo-support)
|
|
30
|
+
- [TypeScript](#typescript)
|
|
31
|
+
- [Troubleshooting](#troubleshooting)
|
|
32
|
+
- [License](#license)
|
|
4
33
|
|
|
5
|
-
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
|
|
8
|
-
## Features
|
|
9
|
-
|
|
10
|
-
- 🎯 **Complete Attribution** - Track users from ad click to conversion
|
|
11
|
-
- 📱 **React Native & Expo** - Works with both platforms
|
|
12
|
-
- 🔄 **Automatic Events** - Session tracking, screen views, app lifecycle
|
|
13
|
-
- 📊 **SKAdNetwork** - iOS 14+ attribution support
|
|
14
|
-
- 💾 **Offline Support** - Events saved and retried when reconnected
|
|
15
|
-
- 🔒 **Privacy First** - GDPR/CCPA compliant
|
|
16
|
-
- ⚡ **Lightweight** - < 100KB, minimal battery impact
|
|
17
|
-
- 🆔 **Identity Resolution** - Persistent anonymous ID links web → mobile → server events
|
|
34
|
+
---
|
|
18
35
|
|
|
19
36
|
## Installation
|
|
20
37
|
|
|
21
38
|
```bash
|
|
22
39
|
npm install @datalyr/react-native
|
|
23
|
-
# or
|
|
24
|
-
yarn add @datalyr/react-native
|
|
25
40
|
```
|
|
26
41
|
|
|
27
42
|
### iOS Setup
|
|
@@ -30,333 +45,535 @@ yarn add @datalyr/react-native
|
|
|
30
45
|
cd ios && pod install
|
|
31
46
|
```
|
|
32
47
|
|
|
33
|
-
|
|
48
|
+
This installs the SDK with bundled Meta and TikTok native SDKs.
|
|
49
|
+
|
|
50
|
+
Add to `ios/YourApp/Info.plist`:
|
|
51
|
+
|
|
52
|
+
```xml
|
|
53
|
+
<!-- Meta SDK -->
|
|
54
|
+
<key>FacebookAppID</key>
|
|
55
|
+
<string>YOUR_FACEBOOK_APP_ID</string>
|
|
56
|
+
<key>FacebookClientToken</key>
|
|
57
|
+
<string>YOUR_CLIENT_TOKEN</string>
|
|
58
|
+
<key>FacebookDisplayName</key>
|
|
59
|
+
<string>Your App Name</string>
|
|
60
|
+
|
|
61
|
+
<key>CFBundleURLTypes</key>
|
|
62
|
+
<array>
|
|
63
|
+
<dict>
|
|
64
|
+
<key>CFBundleURLSchemes</key>
|
|
65
|
+
<array>
|
|
66
|
+
<string>fbYOUR_FACEBOOK_APP_ID</string>
|
|
67
|
+
</array>
|
|
68
|
+
</dict>
|
|
69
|
+
</array>
|
|
70
|
+
|
|
71
|
+
<!-- TikTok SDK -->
|
|
72
|
+
<key>LSApplicationQueriesSchemes</key>
|
|
73
|
+
<array>
|
|
74
|
+
<string>tiktok</string>
|
|
75
|
+
<string>snssdk1180</string>
|
|
76
|
+
<string>snssdk1233</string>
|
|
77
|
+
</array>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Android Setup
|
|
34
81
|
|
|
35
|
-
|
|
82
|
+
No additional setup required.
|
|
83
|
+
|
|
84
|
+
---
|
|
36
85
|
|
|
37
86
|
## Quick Start
|
|
38
87
|
|
|
39
88
|
```typescript
|
|
40
89
|
import { Datalyr } from '@datalyr/react-native';
|
|
41
90
|
|
|
42
|
-
// Initialize
|
|
91
|
+
// Initialize
|
|
43
92
|
await Datalyr.initialize({
|
|
44
|
-
apiKey: 'dk_your_api_key',
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
enableAttribution: true, // Track attribution data from ads
|
|
93
|
+
apiKey: 'dk_your_api_key',
|
|
94
|
+
enableAutoEvents: true,
|
|
95
|
+
enableAttribution: true,
|
|
48
96
|
});
|
|
49
97
|
|
|
50
|
-
// Track
|
|
51
|
-
await Datalyr.track('
|
|
52
|
-
button_name: 'purchase',
|
|
53
|
-
value: 99.99,
|
|
54
|
-
});
|
|
98
|
+
// Track events
|
|
99
|
+
await Datalyr.track('button_clicked', { button: 'signup' });
|
|
55
100
|
|
|
56
|
-
// Identify
|
|
57
|
-
await Datalyr.identify('user_123', {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
101
|
+
// Identify users
|
|
102
|
+
await Datalyr.identify('user_123', { email: 'user@example.com' });
|
|
103
|
+
|
|
104
|
+
// Track purchases
|
|
105
|
+
await Datalyr.trackPurchase(99.99, 'USD', 'product_123');
|
|
61
106
|
```
|
|
62
107
|
|
|
63
|
-
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## How It Works
|
|
111
|
+
|
|
112
|
+
The SDK collects events and sends them to the Datalyr backend for analytics and attribution.
|
|
113
|
+
|
|
114
|
+
### Data Flow
|
|
115
|
+
|
|
116
|
+
1. Events are created with `track()`, `screen()`, or e-commerce methods
|
|
117
|
+
2. Each event includes device info, session data, and attribution parameters
|
|
118
|
+
3. Events are queued locally and sent in batches
|
|
119
|
+
4. If offline, events are stored and sent when connectivity returns
|
|
120
|
+
5. Events are processed server-side for analytics and attribution reporting
|
|
121
|
+
|
|
122
|
+
### Event Payload
|
|
123
|
+
|
|
124
|
+
Every event includes:
|
|
64
125
|
|
|
65
126
|
```typescript
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
127
|
+
{
|
|
128
|
+
event: 'purchase', // Event name
|
|
129
|
+
properties: { ... }, // Custom properties
|
|
130
|
+
|
|
131
|
+
// Identity
|
|
132
|
+
anonymous_id: 'uuid', // Persistent device ID
|
|
133
|
+
user_id: 'user_123', // Set after identify()
|
|
134
|
+
session_id: 'uuid', // Current session
|
|
135
|
+
|
|
136
|
+
// Device
|
|
137
|
+
platform: 'ios',
|
|
138
|
+
device_model: 'iPhone 14',
|
|
139
|
+
os_version: '17.0',
|
|
140
|
+
app_version: '1.2.0',
|
|
141
|
+
|
|
142
|
+
// Attribution (if captured)
|
|
143
|
+
utm_source: 'facebook',
|
|
144
|
+
fbclid: 'abc123',
|
|
145
|
+
|
|
146
|
+
// Timestamps
|
|
147
|
+
timestamp: '2024-01-15T10:30:00Z',
|
|
77
148
|
}
|
|
78
149
|
```
|
|
79
150
|
|
|
80
|
-
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Configuration
|
|
81
154
|
|
|
82
|
-
### Initialize
|
|
83
155
|
```typescript
|
|
84
156
|
await Datalyr.initialize({
|
|
85
|
-
|
|
86
|
-
|
|
157
|
+
// Required
|
|
158
|
+
apiKey: string,
|
|
159
|
+
|
|
160
|
+
// Features
|
|
161
|
+
debug?: boolean, // Console logging
|
|
162
|
+
enableAutoEvents?: boolean, // Track app lifecycle
|
|
163
|
+
enableAttribution?: boolean, // Capture attribution data
|
|
164
|
+
|
|
165
|
+
// Event Queue
|
|
166
|
+
batchSize?: number, // Events per batch (default: 10)
|
|
167
|
+
flushInterval?: number, // Send interval ms (default: 30000)
|
|
168
|
+
maxQueueSize?: number, // Max queued events (default: 100)
|
|
169
|
+
|
|
170
|
+
// iOS
|
|
171
|
+
skadTemplate?: 'ecommerce' | 'gaming' | 'subscription',
|
|
172
|
+
|
|
173
|
+
// Platform SDKs
|
|
174
|
+
meta?: MetaConfig,
|
|
175
|
+
tiktok?: TikTokConfig,
|
|
87
176
|
});
|
|
88
177
|
```
|
|
89
178
|
|
|
90
|
-
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Event Tracking
|
|
182
|
+
|
|
183
|
+
### Custom Events
|
|
184
|
+
|
|
185
|
+
Track any action in your app:
|
|
186
|
+
|
|
91
187
|
```typescript
|
|
92
188
|
// Simple event
|
|
93
|
-
await Datalyr.track('
|
|
189
|
+
await Datalyr.track('signup_started');
|
|
94
190
|
|
|
95
191
|
// Event with properties
|
|
96
|
-
await Datalyr.track('
|
|
192
|
+
await Datalyr.track('product_viewed', {
|
|
97
193
|
product_id: 'SKU123',
|
|
98
|
-
|
|
194
|
+
product_name: 'Blue Shirt',
|
|
195
|
+
price: 29.99,
|
|
99
196
|
currency: 'USD',
|
|
197
|
+
category: 'Apparel',
|
|
100
198
|
});
|
|
101
|
-
```
|
|
102
199
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
plan: 'premium',
|
|
109
|
-
company: 'Acme Inc',
|
|
200
|
+
// Event with value
|
|
201
|
+
await Datalyr.track('level_completed', {
|
|
202
|
+
level: 5,
|
|
203
|
+
score: 1250,
|
|
204
|
+
time_seconds: 120,
|
|
110
205
|
});
|
|
111
206
|
```
|
|
112
207
|
|
|
113
|
-
###
|
|
208
|
+
### Screen Views
|
|
209
|
+
|
|
210
|
+
Track navigation:
|
|
211
|
+
|
|
114
212
|
```typescript
|
|
213
|
+
await Datalyr.screen('Home');
|
|
214
|
+
|
|
115
215
|
await Datalyr.screen('Product Details', {
|
|
116
216
|
product_id: 'SKU123',
|
|
117
|
-
|
|
217
|
+
source: 'search',
|
|
118
218
|
});
|
|
119
219
|
```
|
|
120
220
|
|
|
121
|
-
###
|
|
221
|
+
### E-Commerce Events
|
|
222
|
+
|
|
223
|
+
Standard e-commerce events that also forward to Meta and TikTok:
|
|
224
|
+
|
|
122
225
|
```typescript
|
|
123
|
-
//
|
|
124
|
-
await Datalyr.
|
|
226
|
+
// View product
|
|
227
|
+
await Datalyr.trackViewContent('SKU123', 'Blue Shirt', 'product', 29.99, 'USD');
|
|
228
|
+
|
|
229
|
+
// Add to cart
|
|
230
|
+
await Datalyr.trackAddToCart(29.99, 'USD', 'SKU123', 'Blue Shirt');
|
|
125
231
|
|
|
126
|
-
//
|
|
232
|
+
// Start checkout
|
|
233
|
+
await Datalyr.trackInitiateCheckout(59.98, 'USD', 2, ['SKU123', 'SKU456']);
|
|
234
|
+
|
|
235
|
+
// Complete purchase
|
|
236
|
+
await Datalyr.trackPurchase(59.98, 'USD', 'order_123');
|
|
237
|
+
|
|
238
|
+
// Subscription
|
|
127
239
|
await Datalyr.trackSubscription(9.99, 'USD', 'monthly_pro');
|
|
128
240
|
|
|
129
|
-
//
|
|
130
|
-
await Datalyr.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
241
|
+
// Registration
|
|
242
|
+
await Datalyr.trackCompleteRegistration('email');
|
|
243
|
+
|
|
244
|
+
// Search
|
|
245
|
+
await Datalyr.trackSearch('blue shoes', ['SKU1', 'SKU2']);
|
|
246
|
+
|
|
247
|
+
// Lead
|
|
248
|
+
await Datalyr.trackLead(100.0, 'USD');
|
|
249
|
+
|
|
250
|
+
// Payment info
|
|
251
|
+
await Datalyr.trackAddPaymentInfo(true);
|
|
135
252
|
```
|
|
136
253
|
|
|
137
|
-
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## User Identity
|
|
257
|
+
|
|
258
|
+
### Anonymous ID
|
|
138
259
|
|
|
139
|
-
|
|
140
|
-
- Deep links and Universal Links
|
|
141
|
-
- UTM parameters
|
|
142
|
-
- Referrer data
|
|
143
|
-
- Install attribution
|
|
144
|
-
- Platform click IDs (fbclid, gclid, ttclid, etc.)
|
|
260
|
+
Every device gets a persistent anonymous ID on first launch:
|
|
145
261
|
|
|
146
|
-
### Get Attribution Data
|
|
147
262
|
```typescript
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
// {
|
|
151
|
-
// campaign: 'summer_sale',
|
|
152
|
-
// source: 'facebook',
|
|
153
|
-
// medium: 'social',
|
|
154
|
-
// fbclid: 'abc123',
|
|
155
|
-
// ...
|
|
156
|
-
// }
|
|
263
|
+
const anonymousId = Datalyr.getAnonymousId();
|
|
264
|
+
// 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
|
157
265
|
```
|
|
158
266
|
|
|
159
|
-
|
|
267
|
+
This ID:
|
|
268
|
+
- Persists across app sessions
|
|
269
|
+
- Links events before and after user identification
|
|
270
|
+
- Can be passed to your backend for server-side attribution
|
|
271
|
+
|
|
272
|
+
### Identifying Users
|
|
273
|
+
|
|
274
|
+
Link the anonymous ID to a known user:
|
|
275
|
+
|
|
160
276
|
```typescript
|
|
161
|
-
await Datalyr.
|
|
162
|
-
|
|
163
|
-
source: 'newsletter',
|
|
164
|
-
medium: 'email',
|
|
277
|
+
await Datalyr.identify('user_123', {
|
|
278
|
+
email: 'user@example.com',
|
|
165
279
|
});
|
|
166
280
|
```
|
|
167
281
|
|
|
168
|
-
|
|
282
|
+
After `identify()`:
|
|
283
|
+
- All future events include `user_id`
|
|
284
|
+
- Historical anonymous events can be linked server-side
|
|
285
|
+
- User data is forwarded to Meta/TikTok for Advanced Matching
|
|
286
|
+
|
|
287
|
+
### User Properties
|
|
169
288
|
|
|
170
|
-
|
|
289
|
+
Pass any user attributes:
|
|
171
290
|
|
|
172
291
|
```typescript
|
|
173
|
-
|
|
174
|
-
|
|
292
|
+
await Datalyr.identify('user_123', {
|
|
293
|
+
// Standard fields
|
|
294
|
+
email: 'user@example.com',
|
|
295
|
+
name: 'John Doe',
|
|
296
|
+
phone: '+1234567890',
|
|
175
297
|
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
items: cart,
|
|
181
|
-
anonymous_id: anonymousId // Links server events to mobile events
|
|
182
|
-
})
|
|
298
|
+
// Custom fields
|
|
299
|
+
plan: 'premium',
|
|
300
|
+
company: 'Acme Inc',
|
|
301
|
+
signup_date: '2024-01-15',
|
|
183
302
|
});
|
|
303
|
+
```
|
|
184
304
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
305
|
+
### Logout
|
|
306
|
+
|
|
307
|
+
Clear user data on logout:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
await Datalyr.reset();
|
|
190
311
|
```
|
|
191
312
|
|
|
192
|
-
|
|
193
|
-
-
|
|
194
|
-
-
|
|
195
|
-
-
|
|
313
|
+
This:
|
|
314
|
+
- Clears the user ID
|
|
315
|
+
- Starts a new session
|
|
316
|
+
- Keeps the anonymous ID (same device)
|
|
196
317
|
|
|
197
|
-
|
|
318
|
+
---
|
|
198
319
|
|
|
199
|
-
|
|
320
|
+
## Attribution
|
|
200
321
|
|
|
201
|
-
|
|
202
|
-
// Get current session
|
|
203
|
-
const session = Datalyr.getCurrentSession();
|
|
322
|
+
### Automatic Capture
|
|
204
323
|
|
|
205
|
-
|
|
206
|
-
await Datalyr.endSession();
|
|
324
|
+
The SDK captures attribution from deep links and referrers:
|
|
207
325
|
|
|
208
|
-
|
|
209
|
-
|
|
326
|
+
```typescript
|
|
327
|
+
const attribution = Datalyr.getAttributionData();
|
|
210
328
|
```
|
|
211
329
|
|
|
212
|
-
|
|
330
|
+
Captured parameters:
|
|
213
331
|
|
|
214
|
-
|
|
332
|
+
| Type | Parameters |
|
|
333
|
+
|------|------------|
|
|
334
|
+
| UTM | `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term` |
|
|
335
|
+
| Click IDs | `fbclid`, `gclid`, `ttclid`, `twclid`, `li_click_id`, `msclkid` |
|
|
336
|
+
| Campaign | `campaign_id`, `adset_id`, `ad_id` |
|
|
337
|
+
|
|
338
|
+
### Deferred Deep Links
|
|
339
|
+
|
|
340
|
+
Capture attribution from App Store installs (iOS):
|
|
215
341
|
|
|
216
342
|
```typescript
|
|
217
343
|
await Datalyr.initialize({
|
|
218
344
|
apiKey: 'dk_your_api_key',
|
|
219
|
-
|
|
345
|
+
meta: {
|
|
346
|
+
appId: '1234567890',
|
|
347
|
+
enableDeferredDeepLink: true,
|
|
348
|
+
},
|
|
220
349
|
});
|
|
221
350
|
|
|
222
|
-
//
|
|
223
|
-
|
|
351
|
+
// Check for deferred attribution
|
|
352
|
+
const deferred = Datalyr.getDeferredAttributionData();
|
|
353
|
+
if (deferred) {
|
|
354
|
+
console.log(deferred.fbclid); // Facebook click ID
|
|
355
|
+
console.log(deferred.campaignId); // Campaign ID
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Manual Attribution
|
|
224
360
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
361
|
+
Set attribution programmatically:
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
await Datalyr.setAttributionData({
|
|
365
|
+
utm_source: 'newsletter',
|
|
366
|
+
utm_campaign: 'spring_sale',
|
|
367
|
+
});
|
|
228
368
|
```
|
|
229
369
|
|
|
230
|
-
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Event Queue
|
|
231
373
|
|
|
232
|
-
|
|
374
|
+
Events are batched for efficiency and offline support.
|
|
233
375
|
|
|
234
|
-
|
|
235
|
-
- `app_open` - App launches
|
|
236
|
-
- `app_background` - App enters background
|
|
237
|
-
- `app_foreground` - App returns to foreground
|
|
238
|
-
- `app_update` - App version changes
|
|
239
|
-
- `session_start` - New session begins
|
|
240
|
-
- `session_end` - Session expires
|
|
376
|
+
### Configuration
|
|
241
377
|
|
|
242
|
-
|
|
378
|
+
```typescript
|
|
379
|
+
await Datalyr.initialize({
|
|
380
|
+
apiKey: 'dk_your_api_key',
|
|
381
|
+
batchSize: 10, // Send when 10 events queued
|
|
382
|
+
flushInterval: 30000, // Or every 30 seconds
|
|
383
|
+
maxQueueSize: 100, // Max events to store offline
|
|
384
|
+
});
|
|
385
|
+
```
|
|
243
386
|
|
|
244
|
-
|
|
387
|
+
### Manual Flush
|
|
388
|
+
|
|
389
|
+
Send all queued events immediately:
|
|
245
390
|
|
|
246
391
|
```typescript
|
|
247
|
-
// Manually flush queue
|
|
248
392
|
await Datalyr.flush();
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Queue Status
|
|
249
396
|
|
|
250
|
-
|
|
397
|
+
```typescript
|
|
251
398
|
const status = Datalyr.getStatus();
|
|
252
|
-
console.log(
|
|
399
|
+
console.log(status.queueStats.queueSize); // Events waiting
|
|
400
|
+
console.log(status.queueStats.pending); // Events being sent
|
|
253
401
|
```
|
|
254
402
|
|
|
255
|
-
|
|
403
|
+
### Offline Support
|
|
256
404
|
|
|
257
|
-
|
|
405
|
+
When the device is offline:
|
|
406
|
+
- Events are stored locally
|
|
407
|
+
- Queue persists across app restarts
|
|
408
|
+
- Events are sent when connectivity returns
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Auto Events
|
|
413
|
+
|
|
414
|
+
Enable automatic lifecycle tracking:
|
|
258
415
|
|
|
259
416
|
```typescript
|
|
260
417
|
await Datalyr.initialize({
|
|
261
418
|
apiKey: 'dk_your_api_key',
|
|
262
|
-
|
|
419
|
+
enableAutoEvents: true,
|
|
263
420
|
});
|
|
264
421
|
```
|
|
265
422
|
|
|
266
|
-
|
|
423
|
+
| Event | Trigger |
|
|
424
|
+
|-------|---------|
|
|
425
|
+
| `app_install` | First app open |
|
|
426
|
+
| `app_open` | App launch |
|
|
427
|
+
| `app_background` | App enters background |
|
|
428
|
+
| `app_foreground` | App returns to foreground |
|
|
429
|
+
| `app_update` | App version changes |
|
|
430
|
+
| `session_start` | New session begins |
|
|
431
|
+
| `session_end` | Session expires (30 min inactivity) |
|
|
432
|
+
|
|
433
|
+
---
|
|
267
434
|
|
|
268
|
-
|
|
435
|
+
## SKAdNetwork
|
|
436
|
+
|
|
437
|
+
iOS conversion tracking with Apple's SKAdNetwork:
|
|
269
438
|
|
|
270
439
|
```typescript
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
440
|
+
await Datalyr.initialize({
|
|
441
|
+
apiKey: 'dk_your_api_key',
|
|
442
|
+
skadTemplate: 'ecommerce',
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// E-commerce events update conversion values
|
|
446
|
+
await Datalyr.trackPurchase(99.99, 'USD');
|
|
278
447
|
```
|
|
279
448
|
|
|
280
|
-
|
|
449
|
+
| Template | Events |
|
|
450
|
+
|----------|--------|
|
|
451
|
+
| `ecommerce` | purchase, add_to_cart, begin_checkout, signup, subscribe, view_item |
|
|
452
|
+
| `gaming` | level_complete, tutorial_complete, purchase, achievement_unlocked |
|
|
453
|
+
| `subscription` | trial_start, subscribe, upgrade, cancel, signup |
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Platform Integrations
|
|
458
|
+
|
|
459
|
+
Bundled Meta and TikTok SDKs for iOS. No extra npm packages needed.
|
|
460
|
+
|
|
461
|
+
### Meta (Facebook)
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
await Datalyr.initialize({
|
|
465
|
+
apiKey: 'dk_your_api_key',
|
|
466
|
+
meta: {
|
|
467
|
+
appId: '1234567890',
|
|
468
|
+
clientToken: 'abc123',
|
|
469
|
+
enableDeferredDeepLink: true,
|
|
470
|
+
enableAppEvents: true,
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
```
|
|
281
474
|
|
|
282
|
-
|
|
475
|
+
### TikTok
|
|
283
476
|
|
|
284
477
|
```typescript
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
478
|
+
await Datalyr.initialize({
|
|
479
|
+
apiKey: 'dk_your_api_key',
|
|
480
|
+
tiktok: {
|
|
481
|
+
appId: 'your_app_id',
|
|
482
|
+
tiktokAppId: '7123456789',
|
|
483
|
+
enableAppEvents: true,
|
|
484
|
+
},
|
|
485
|
+
});
|
|
291
486
|
```
|
|
292
487
|
|
|
293
|
-
|
|
488
|
+
### Apple Search Ads
|
|
294
489
|
|
|
295
|
-
|
|
490
|
+
Attribution for users who install from Apple Search Ads (iOS 14.3+). Automatically fetched on initialization.
|
|
296
491
|
|
|
297
492
|
```typescript
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
493
|
+
// Check if user came from Apple Search Ads
|
|
494
|
+
const asaAttribution = Datalyr.getAppleSearchAdsAttribution();
|
|
495
|
+
|
|
496
|
+
if (asaAttribution?.attribution) {
|
|
497
|
+
console.log(asaAttribution.campaignId); // Campaign ID
|
|
498
|
+
console.log(asaAttribution.campaignName); // Campaign name
|
|
499
|
+
console.log(asaAttribution.adGroupId); // Ad group ID
|
|
500
|
+
console.log(asaAttribution.keyword); // Search keyword
|
|
501
|
+
console.log(asaAttribution.clickDate); // Click date
|
|
502
|
+
}
|
|
503
|
+
```
|
|
301
504
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
505
|
+
Attribution data is automatically included in all events with the `asa_` prefix:
|
|
506
|
+
- `asa_campaign_id`, `asa_campaign_name`
|
|
507
|
+
- `asa_ad_group_id`, `asa_ad_group_name`
|
|
508
|
+
- `asa_keyword_id`, `asa_keyword`
|
|
509
|
+
- `asa_org_id`, `asa_org_name`
|
|
510
|
+
- `asa_click_date`, `asa_conversion_type`
|
|
511
|
+
|
|
512
|
+
No additional configuration needed. The SDK uses Apple's AdServices API.
|
|
513
|
+
|
|
514
|
+
### App Tracking Transparency
|
|
515
|
+
|
|
516
|
+
Update after ATT dialog:
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
const { status } = await requestTrackingPermissionsAsync();
|
|
520
|
+
await Datalyr.updateTrackingAuthorization(status === 'granted');
|
|
305
521
|
```
|
|
306
522
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
### Methods
|
|
310
|
-
|
|
311
|
-
| Method | Description |
|
|
312
|
-
|--------|-------------|
|
|
313
|
-
| `initialize(config)` | Initialize SDK with configuration |
|
|
314
|
-
| `track(event, properties?)` | Track custom event |
|
|
315
|
-
| `identify(userId, properties?)` | Identify user |
|
|
316
|
-
| `screen(name, properties?)` | Track screen view |
|
|
317
|
-
| `alias(newUserId, previousId?)` | Create user alias |
|
|
318
|
-
| `reset()` | Reset user session |
|
|
319
|
-
| `flush()` | Flush event queue |
|
|
320
|
-
| `getStatus()` | Get SDK status |
|
|
321
|
-
| `getAttributionData()` | Get attribution data |
|
|
322
|
-
| `setAttributionData(data)` | Set attribution data |
|
|
323
|
-
| `getCurrentSession()` | Get current session |
|
|
324
|
-
| `endSession()` | End current session |
|
|
325
|
-
| `trackPurchase(value, currency, productId?)` | Track purchase |
|
|
326
|
-
| `trackSubscription(value, currency, plan?)` | Track subscription |
|
|
327
|
-
| `trackRevenue(event, properties?)` | Track revenue event |
|
|
523
|
+
### Check Status
|
|
328
524
|
|
|
329
|
-
|
|
525
|
+
```typescript
|
|
526
|
+
const status = Datalyr.getPlatformIntegrationStatus();
|
|
527
|
+
// { meta: true, tiktok: true, appleSearchAds: true }
|
|
528
|
+
```
|
|
330
529
|
|
|
331
|
-
|
|
332
|
-
1. Check your API key is correct
|
|
333
|
-
2. Enable debug mode to see logs
|
|
334
|
-
3. Verify network connectivity
|
|
335
|
-
4. Check `getStatus()` for queue information
|
|
530
|
+
---
|
|
336
531
|
|
|
337
|
-
|
|
338
|
-
- Ensure API key starts with `dk_`
|
|
339
|
-
- Get your API key from: https://app.datalyr.com/settings/api-keys
|
|
532
|
+
## Expo Support
|
|
340
533
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
npx react-native clean-project
|
|
534
|
+
```typescript
|
|
535
|
+
import { Datalyr } from '@datalyr/react-native/expo';
|
|
536
|
+
```
|
|
345
537
|
|
|
346
|
-
|
|
347
|
-
|
|
538
|
+
Same API as standard React Native.
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## TypeScript
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
import {
|
|
546
|
+
Datalyr,
|
|
547
|
+
DatalyrConfig,
|
|
548
|
+
EventData,
|
|
549
|
+
UserProperties,
|
|
550
|
+
AttributionData,
|
|
551
|
+
} from '@datalyr/react-native';
|
|
348
552
|
```
|
|
349
553
|
|
|
350
|
-
|
|
554
|
+
---
|
|
351
555
|
|
|
352
|
-
|
|
353
|
-
- 📚 Docs: https://docs.datalyr.com
|
|
354
|
-
- 🐛 Issues: https://github.com/datalyr/react-native/issues
|
|
556
|
+
## Troubleshooting
|
|
355
557
|
|
|
356
|
-
|
|
558
|
+
### Events not appearing
|
|
559
|
+
|
|
560
|
+
1. Check API key starts with `dk_`
|
|
561
|
+
2. Enable `debug: true`
|
|
562
|
+
3. Check `Datalyr.getStatus()` for queue info
|
|
563
|
+
4. Verify network connectivity
|
|
564
|
+
|
|
565
|
+
### iOS build errors
|
|
566
|
+
|
|
567
|
+
```bash
|
|
568
|
+
cd ios && pod deintegrate && pod install
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Meta/TikTok not working
|
|
357
572
|
|
|
358
|
-
|
|
573
|
+
Verify Info.plist contains required keys (see Installation).
|
|
359
574
|
|
|
360
575
|
---
|
|
361
576
|
|
|
362
|
-
|
|
577
|
+
## License
|
|
578
|
+
|
|
579
|
+
MIT
|