@linkforty/mobile-sdk-react-native 1.1.3 → 1.1.5
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 +4 -0
- package/README.md +214 -171
- package/package.json +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.1.5] - 2026-02-13
|
|
11
|
+
### Fixed
|
|
12
|
+
- Removed accidental self-referencing `file:` dependency in published package that prevented `npm install` from working
|
|
13
|
+
|
|
10
14
|
## [1.1.3] - 2026-02-12
|
|
11
15
|
### Fixed
|
|
12
16
|
- Replaced `new URL()` and `URLSearchParams` usage with manual string parsing — `URL.pathname` is not implemented in React Native's Hermes engine, which caused `parseURL()` to crash silently and skip server-side deep link resolution entirely
|
package/README.md
CHANGED
|
@@ -4,20 +4,19 @@ Official React Native SDK for [LinkForty](https://github.com/linkforty/core) - O
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
7
|
+
- **Direct Deep Linking** - Handle Universal Links (iOS) and App Links (Android) with automatic server-side resolution
|
|
8
|
+
- **Deferred Deep Linking** - Route new users to specific content after install
|
|
9
|
+
- **Link Creation** - Create short links programmatically from your app
|
|
10
|
+
- **Probabilistic Attribution** - Match installs to clicks via device fingerprinting
|
|
11
|
+
- **Event Tracking** - Track in-app events with attribution
|
|
12
|
+
- **Privacy-Focused** - No persistent device IDs required
|
|
13
|
+
- **TypeScript Support** - Full type definitions included
|
|
14
|
+
- **Works with Core & Cloud** - Compatible with self-hosted and Cloud instances
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
17
18
|
```bash
|
|
18
|
-
npm
|
|
19
|
-
# or
|
|
20
|
-
yarn add @linkforty/mobile-sdk-react-native
|
|
19
|
+
npm install @linkforty/mobile-sdk-react-native
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
### Requirements
|
|
@@ -26,9 +25,7 @@ yarn add @linkforty/mobile-sdk-react-native
|
|
|
26
25
|
- React >= 17.0.0
|
|
27
26
|
- Node.js >= 20.0.0
|
|
28
27
|
|
|
29
|
-
###
|
|
30
|
-
|
|
31
|
-
This SDK requires the following peer dependencies:
|
|
28
|
+
### Peer Dependencies
|
|
32
29
|
|
|
33
30
|
```bash
|
|
34
31
|
npm install @react-native-async-storage/async-storage react-native-device-info
|
|
@@ -44,16 +41,15 @@ cd ios && pod install
|
|
|
44
41
|
|
|
45
42
|
2. Configure Universal Links in Xcode:
|
|
46
43
|
- Open your project in Xcode
|
|
47
|
-
- Select your app target
|
|
44
|
+
- Select your app target > Signing & Capabilities
|
|
48
45
|
- Add "Associated Domains" capability
|
|
49
|
-
- Add domain: `applinks:go.yourdomain.com` (replace with your LinkForty
|
|
46
|
+
- Add domain: `applinks:go.yourdomain.com` (replace with your LinkForty domain)
|
|
50
47
|
|
|
51
|
-
3.
|
|
48
|
+
3. Host an Apple App Site Association (AASA) file at:
|
|
52
49
|
```
|
|
53
50
|
https://go.yourdomain.com/.well-known/apple-app-site-association
|
|
54
51
|
```
|
|
55
52
|
|
|
56
|
-
Example AASA file:
|
|
57
53
|
```json
|
|
58
54
|
{
|
|
59
55
|
"applinks": {
|
|
@@ -70,7 +66,7 @@ cd ios && pod install
|
|
|
70
66
|
|
|
71
67
|
### Android Setup
|
|
72
68
|
|
|
73
|
-
1.
|
|
69
|
+
1. Add an App Links intent filter in `android/app/src/main/AndroidManifest.xml`:
|
|
74
70
|
|
|
75
71
|
```xml
|
|
76
72
|
<activity android:name=".MainActivity">
|
|
@@ -84,12 +80,11 @@ cd ios && pod install
|
|
|
84
80
|
</activity>
|
|
85
81
|
```
|
|
86
82
|
|
|
87
|
-
2.
|
|
83
|
+
2. Host a Digital Asset Links file at:
|
|
88
84
|
```
|
|
89
85
|
https://go.yourdomain.com/.well-known/assetlinks.json
|
|
90
86
|
```
|
|
91
87
|
|
|
92
|
-
Example assetlinks.json:
|
|
93
88
|
```json
|
|
94
89
|
[{
|
|
95
90
|
"relation": ["delegate_permission/common.handle_all_urls"],
|
|
@@ -101,187 +96,223 @@ cd ios && pod install
|
|
|
101
96
|
}]
|
|
102
97
|
```
|
|
103
98
|
|
|
99
|
+
3. Ensure `MainActivity` preserves the Intent for React Native. In `MainActivity.kt`:
|
|
100
|
+
|
|
101
|
+
```kotlin
|
|
102
|
+
override fun onNewIntent(intent: Intent) {
|
|
103
|
+
setIntent(intent) // Required for React Native's Linking.getInitialURL()
|
|
104
|
+
super.onNewIntent(intent)
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> **Note:** If you use other SDKs that consume Intent data (e.g., CleverTap), make sure they receive a **copy** of the URI in `onCreate` rather than consuming the original Intent, otherwise `Linking.getInitialURL()` may return `null`.
|
|
109
|
+
|
|
104
110
|
## Quick Start
|
|
105
111
|
|
|
106
112
|
```typescript
|
|
107
113
|
import LinkForty from '@linkforty/mobile-sdk-react-native';
|
|
108
114
|
|
|
109
|
-
// Initialize SDK (call
|
|
115
|
+
// 1. Initialize the SDK (call once at app startup)
|
|
110
116
|
await LinkForty.init({
|
|
111
117
|
baseUrl: 'https://go.yourdomain.com',
|
|
112
|
-
apiKey: '
|
|
113
|
-
debug: __DEV__,
|
|
118
|
+
apiKey: 'your-api-key', // Required for createLink(), optional otherwise
|
|
119
|
+
debug: __DEV__,
|
|
114
120
|
});
|
|
115
121
|
|
|
116
|
-
// Handle
|
|
117
|
-
LinkForty.
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
// 2. Handle direct deep links (user taps a link while app is installed)
|
|
123
|
+
LinkForty.onDeepLink((url, data) => {
|
|
124
|
+
if (data?.customParameters) {
|
|
125
|
+
const { route, id } = data.customParameters;
|
|
126
|
+
// Navigate to the target screen
|
|
127
|
+
navigation.navigate(route, { id });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
121
130
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
131
|
+
// 3. Handle deferred deep links (user installs app after tapping a link)
|
|
132
|
+
LinkForty.onDeferredDeepLink((data) => {
|
|
133
|
+
if (data?.customParameters) {
|
|
134
|
+
const { route, id } = data.customParameters;
|
|
135
|
+
navigation.navigate(route, { id });
|
|
126
136
|
} else {
|
|
127
|
-
|
|
128
|
-
console.log('Organic install');
|
|
137
|
+
console.log('Organic install — no link clicked');
|
|
129
138
|
}
|
|
130
139
|
});
|
|
140
|
+
```
|
|
131
141
|
|
|
132
|
-
|
|
133
|
-
LinkForty.onDeepLink((url, deepLinkData) => {
|
|
134
|
-
console.log('Deep link opened:', url, deepLinkData);
|
|
142
|
+
## API Reference
|
|
135
143
|
|
|
136
|
-
|
|
137
|
-
// Navigate to specific content
|
|
138
|
-
navigation.navigate('Product', {
|
|
139
|
-
id: deepLinkData.utmParameters?.content
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
});
|
|
144
|
+
### `init(config)`
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
Initialize the SDK. Must be called before any other method.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
await LinkForty.init({
|
|
150
|
+
baseUrl: 'https://go.yourdomain.com', // Required
|
|
151
|
+
apiKey: 'your-api-key', // Optional (required for createLink)
|
|
152
|
+
debug: true, // Optional (default: false)
|
|
153
|
+
attributionWindow: 7, // Optional, in days (default: 7)
|
|
149
154
|
});
|
|
150
155
|
```
|
|
151
156
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
| Parameter | Type | Required | Description |
|
|
158
|
+
|-----------|------|----------|-------------|
|
|
159
|
+
| `baseUrl` | `string` | Yes | Base URL of your LinkForty instance |
|
|
160
|
+
| `apiKey` | `string` | No | API key for authenticated endpoints (Cloud) |
|
|
161
|
+
| `debug` | `boolean` | No | Enable debug logging |
|
|
162
|
+
| `attributionWindow` | `number` | No | Attribution window in days (default: 7) |
|
|
155
163
|
|
|
156
|
-
|
|
164
|
+
---
|
|
157
165
|
|
|
158
|
-
|
|
166
|
+
### `onDeepLink(callback)`
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
- `config.apiKey` (string, optional) - API key for Cloud authentication
|
|
162
|
-
- `config.debug` (boolean, optional) - Enable debug logging
|
|
163
|
-
- `config.attributionWindow` (number, optional) - Attribution window in days (default: 7)
|
|
168
|
+
Listen for direct deep links. Called when the app is opened via a Universal Link (iOS) or App Link (Android).
|
|
164
169
|
|
|
165
|
-
|
|
170
|
+
When the URL matches your LinkForty `baseUrl`, the SDK automatically resolves it via the server to retrieve the full link data including `customParameters`, UTM parameters, and metadata. If resolution fails, the SDK falls back to local URL parsing.
|
|
166
171
|
|
|
167
172
|
```typescript
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
LinkForty.onDeepLink((url: string, data: DeepLinkData | null) => {
|
|
174
|
+
console.log('Link URL:', url);
|
|
175
|
+
|
|
176
|
+
if (data?.customParameters) {
|
|
177
|
+
const { route, id } = data.customParameters;
|
|
178
|
+
navigation.navigate(route, { id });
|
|
179
|
+
}
|
|
172
180
|
});
|
|
173
181
|
```
|
|
174
182
|
|
|
175
|
-
|
|
183
|
+
| Callback Parameter | Type | Description |
|
|
184
|
+
|--------------------|------|-------------|
|
|
185
|
+
| `url` | `string` | The full URL that opened the app |
|
|
186
|
+
| `data` | `DeepLinkData \| null` | Parsed link data, or `null` if parsing failed |
|
|
176
187
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
**Parameters:**
|
|
188
|
+
---
|
|
180
189
|
|
|
181
|
-
|
|
190
|
+
### `onDeferredDeepLink(callback)`
|
|
182
191
|
|
|
183
|
-
|
|
192
|
+
Listen for deferred deep links. Called on first launch after install if the user clicked a LinkForty link before installing.
|
|
184
193
|
|
|
185
194
|
```typescript
|
|
186
|
-
LinkForty.onDeferredDeepLink((
|
|
187
|
-
if (
|
|
188
|
-
// Attributed install
|
|
189
|
-
console.log('
|
|
195
|
+
LinkForty.onDeferredDeepLink((data: DeepLinkData | null) => {
|
|
196
|
+
if (data) {
|
|
197
|
+
// Attributed install — user clicked a link before installing
|
|
198
|
+
console.log('Came from:', data.utmParameters?.source);
|
|
199
|
+
const { route, id } = data.customParameters || {};
|
|
200
|
+
if (route) navigation.navigate(route, { id });
|
|
190
201
|
} else {
|
|
191
|
-
// Organic install
|
|
202
|
+
// Organic install or attribution failed
|
|
192
203
|
console.log('Organic install');
|
|
193
204
|
}
|
|
194
205
|
});
|
|
195
206
|
```
|
|
196
207
|
|
|
197
|
-
|
|
208
|
+
| Callback Parameter | Type | Description |
|
|
209
|
+
|--------------------|------|-------------|
|
|
210
|
+
| `data` | `DeepLinkData \| null` | Attributed link data, or `null` for organic installs |
|
|
198
211
|
|
|
199
|
-
|
|
212
|
+
---
|
|
200
213
|
|
|
201
|
-
|
|
214
|
+
### `createLink(options)`
|
|
202
215
|
|
|
203
|
-
|
|
216
|
+
Create a short link programmatically. Requires `apiKey` to be set in `init()`.
|
|
204
217
|
|
|
205
|
-
|
|
218
|
+
When `templateId` is omitted, the server auto-selects your organization's default template.
|
|
206
219
|
|
|
207
220
|
```typescript
|
|
208
|
-
LinkForty.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
221
|
+
const result = await LinkForty.createLink({
|
|
222
|
+
deepLinkParameters: { route: 'VIDEO_VIEWER', id: 'e4338ed6-...' },
|
|
223
|
+
title: 'Check out this video',
|
|
224
|
+
utmParameters: { source: 'share', medium: 'app' },
|
|
213
225
|
});
|
|
226
|
+
|
|
227
|
+
console.log(result.url); // https://go.yourdomain.com/tmpl/abc123
|
|
228
|
+
console.log(result.shortCode); // abc123
|
|
229
|
+
console.log(result.linkId); // uuid
|
|
214
230
|
```
|
|
215
231
|
|
|
216
|
-
|
|
232
|
+
**Options:**
|
|
217
233
|
|
|
218
|
-
|
|
234
|
+
| Parameter | Type | Required | Description |
|
|
235
|
+
|-----------|------|----------|-------------|
|
|
236
|
+
| `deepLinkParameters` | `Record<string, string>` | No | Custom parameters embedded in the link (e.g., `{ route, id }`) |
|
|
237
|
+
| `title` | `string` | No | Link title for internal reference |
|
|
238
|
+
| `description` | `string` | No | Link description |
|
|
239
|
+
| `customCode` | `string` | No | Custom short code (auto-generated if omitted) |
|
|
240
|
+
| `utmParameters` | `object` | No | UTM parameters (`source`, `medium`, `campaign`, `term`, `content`) |
|
|
241
|
+
| `templateId` | `string` | No | Template UUID (auto-selected if omitted) |
|
|
242
|
+
| `templateSlug` | `string` | No | Template slug (only needed with `templateId`) |
|
|
219
243
|
|
|
220
|
-
**
|
|
244
|
+
**Returns:** `CreateLinkResult`
|
|
221
245
|
|
|
222
|
-
|
|
223
|
-
|
|
246
|
+
| Field | Type | Description |
|
|
247
|
+
|-------|------|-------------|
|
|
248
|
+
| `url` | `string` | Full shareable URL |
|
|
249
|
+
| `shortCode` | `string` | The generated short code |
|
|
250
|
+
| `linkId` | `string` | Link UUID |
|
|
224
251
|
|
|
225
|
-
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### `trackEvent(name, properties?)`
|
|
255
|
+
|
|
256
|
+
Track an in-app event for attribution analytics. Requires a successful install report (automatic on first launch).
|
|
226
257
|
|
|
227
258
|
```typescript
|
|
228
259
|
await LinkForty.trackEvent('purchase', {
|
|
229
260
|
amount: 99.99,
|
|
230
261
|
currency: 'USD',
|
|
231
262
|
productId: 'premium_plan',
|
|
232
|
-
category: 'subscription'
|
|
233
263
|
});
|
|
234
264
|
```
|
|
235
265
|
|
|
236
|
-
|
|
266
|
+
| Parameter | Type | Required | Description |
|
|
267
|
+
|-----------|------|----------|-------------|
|
|
268
|
+
| `name` | `string` | Yes | Event name (e.g., `'purchase'`, `'signup'`) |
|
|
269
|
+
| `properties` | `Record<string, any>` | No | Arbitrary event properties |
|
|
237
270
|
|
|
238
|
-
|
|
271
|
+
---
|
|
239
272
|
|
|
240
|
-
|
|
273
|
+
### `getInstallData()`
|
|
241
274
|
|
|
242
|
-
|
|
275
|
+
Retrieve cached install attribution data from a previous deferred deep link.
|
|
243
276
|
|
|
244
277
|
```typescript
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
console.log('Install
|
|
278
|
+
const data = await LinkForty.getInstallData();
|
|
279
|
+
if (data) {
|
|
280
|
+
console.log('Install attributed to:', data.utmParameters?.source);
|
|
248
281
|
}
|
|
249
282
|
```
|
|
250
283
|
|
|
251
|
-
|
|
284
|
+
**Returns:** `DeepLinkData | null`
|
|
252
285
|
|
|
253
|
-
|
|
286
|
+
---
|
|
254
287
|
|
|
255
|
-
|
|
288
|
+
### `getInstallId()`
|
|
256
289
|
|
|
257
|
-
|
|
290
|
+
Get the unique install ID assigned by the LinkForty server on first launch.
|
|
258
291
|
|
|
259
292
|
```typescript
|
|
260
293
|
const installId = await LinkForty.getInstallId();
|
|
261
|
-
console.log('Install ID:', installId);
|
|
262
294
|
```
|
|
263
295
|
|
|
264
|
-
|
|
296
|
+
**Returns:** `string | null`
|
|
265
297
|
|
|
266
|
-
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### `clearData()`
|
|
267
301
|
|
|
268
|
-
|
|
302
|
+
Clear all cached SDK data (install ID, attribution data, first-launch flag). The next app launch will behave as a fresh install.
|
|
269
303
|
|
|
270
304
|
```typescript
|
|
271
305
|
await LinkForty.clearData();
|
|
272
|
-
// App will behave as if it's a fresh install
|
|
273
306
|
```
|
|
274
307
|
|
|
275
|
-
##
|
|
308
|
+
## Types
|
|
276
309
|
|
|
277
310
|
### `DeepLinkData`
|
|
278
311
|
|
|
279
312
|
```typescript
|
|
280
313
|
interface DeepLinkData {
|
|
281
314
|
shortCode: string;
|
|
282
|
-
|
|
283
|
-
androidUrl?: string;
|
|
284
|
-
webUrl?: string;
|
|
315
|
+
customParameters?: Record<string, string>;
|
|
285
316
|
utmParameters?: {
|
|
286
317
|
source?: string;
|
|
287
318
|
medium?: string;
|
|
@@ -289,7 +320,11 @@ interface DeepLinkData {
|
|
|
289
320
|
term?: string;
|
|
290
321
|
content?: string;
|
|
291
322
|
};
|
|
292
|
-
|
|
323
|
+
iosUrl?: string;
|
|
324
|
+
androidUrl?: string;
|
|
325
|
+
webUrl?: string;
|
|
326
|
+
deepLinkPath?: string;
|
|
327
|
+
appScheme?: string;
|
|
293
328
|
clickedAt?: string;
|
|
294
329
|
linkId?: string;
|
|
295
330
|
}
|
|
@@ -306,79 +341,94 @@ interface LinkFortyConfig {
|
|
|
306
341
|
}
|
|
307
342
|
```
|
|
308
343
|
|
|
309
|
-
|
|
344
|
+
### `CreateLinkOptions`
|
|
310
345
|
|
|
311
|
-
|
|
346
|
+
```typescript
|
|
347
|
+
interface CreateLinkOptions {
|
|
348
|
+
templateId?: string;
|
|
349
|
+
templateSlug?: string;
|
|
350
|
+
deepLinkParameters?: Record<string, string>;
|
|
351
|
+
title?: string;
|
|
352
|
+
description?: string;
|
|
353
|
+
customCode?: string;
|
|
354
|
+
utmParameters?: {
|
|
355
|
+
source?: string;
|
|
356
|
+
medium?: string;
|
|
357
|
+
campaign?: string;
|
|
358
|
+
term?: string;
|
|
359
|
+
content?: string;
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
```
|
|
312
363
|
|
|
313
|
-
|
|
314
|
-
```typescript
|
|
315
|
-
await LinkForty.clearData();
|
|
316
|
-
```
|
|
364
|
+
### `CreateLinkResult`
|
|
317
365
|
|
|
318
|
-
|
|
366
|
+
```typescript
|
|
367
|
+
interface CreateLinkResult {
|
|
368
|
+
url: string;
|
|
369
|
+
shortCode: string;
|
|
370
|
+
linkId: string;
|
|
371
|
+
}
|
|
372
|
+
```
|
|
319
373
|
|
|
320
|
-
|
|
374
|
+
## How Deep Linking Works
|
|
321
375
|
|
|
322
|
-
|
|
376
|
+
### Direct Deep Links (App Installed)
|
|
323
377
|
|
|
324
|
-
|
|
378
|
+
When a user taps a LinkForty URL and the app is already installed:
|
|
325
379
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
});
|
|
332
|
-
```
|
|
380
|
+
1. The OS intercepts the URL via App Links (Android) or Universal Links (iOS) and opens your app directly
|
|
381
|
+
2. The SDK receives the URL via React Native's `Linking` API
|
|
382
|
+
3. The SDK calls your LinkForty server's resolve endpoint to retrieve the full link data (`customParameters`, UTM params, etc.)
|
|
383
|
+
4. Your `onDeepLink` callback fires with the resolved data
|
|
384
|
+
5. Your app navigates to the target screen
|
|
333
385
|
|
|
334
|
-
###
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
// Add API key for Cloud authentication
|
|
338
|
-
await LinkForty.init({
|
|
339
|
-
baseUrl: 'https://go.yourdomain.com',
|
|
340
|
-
apiKey: 'your-api-key-here',
|
|
341
|
-
debug: false,
|
|
342
|
-
});
|
|
343
|
-
```
|
|
386
|
+
### Deferred Deep Links (App Not Installed)
|
|
344
387
|
|
|
345
|
-
|
|
388
|
+
When a user taps a LinkForty URL and the app is **not** installed:
|
|
346
389
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
```
|
|
390
|
+
1. The LinkForty server records a click with the user's device fingerprint
|
|
391
|
+
2. The user is redirected to the App Store / Play Store
|
|
392
|
+
3. After installing and opening the app, the SDK reports the install with the device's fingerprint
|
|
393
|
+
4. The server matches the fingerprint to the original click (probabilistic attribution)
|
|
394
|
+
5. Your `onDeferredDeepLink` callback fires with the matched link data
|
|
395
|
+
6. Your app navigates to the content the user originally clicked on
|
|
354
396
|
|
|
355
397
|
## Troubleshooting
|
|
356
398
|
|
|
357
399
|
### Deep links not working on iOS
|
|
358
400
|
|
|
359
|
-
1. Verify
|
|
360
|
-
2. Check that
|
|
361
|
-
3.
|
|
362
|
-
4. Test
|
|
401
|
+
1. Verify AASA file is accessible at `https://yourdomain.com/.well-known/apple-app-site-association`
|
|
402
|
+
2. Check that Team ID and Bundle ID are correct in the AASA file
|
|
403
|
+
3. Confirm "Associated Domains" capability is added in Xcode with `applinks:yourdomain.com`
|
|
404
|
+
4. Test on a real device (Universal Links don't work in the simulator)
|
|
363
405
|
|
|
364
406
|
### Deep links not working on Android
|
|
365
407
|
|
|
366
|
-
1. Verify
|
|
367
|
-
2. Check
|
|
368
|
-
3. Run `adb shell pm get-app-links com.yourapp` to
|
|
369
|
-
4.
|
|
408
|
+
1. Verify assetlinks.json is accessible at `https://yourdomain.com/.well-known/assetlinks.json`
|
|
409
|
+
2. Check package name and SHA256 fingerprint are correct
|
|
410
|
+
3. Run `adb shell pm get-app-links com.yourapp` to check link verification status
|
|
411
|
+
4. Confirm `android:autoVerify="true"` is set in your intent filter
|
|
412
|
+
5. Ensure `MainActivity` calls `setIntent(intent)` in `onNewIntent` (see [Android Setup](#android-setup))
|
|
413
|
+
|
|
414
|
+
### `getInitialURL()` returns null on Android
|
|
415
|
+
|
|
416
|
+
This usually means another SDK or library is consuming the Intent data before React Native reads it. In `MainActivity.kt`:
|
|
417
|
+
|
|
418
|
+
- Call `setIntent(intent)` in `onNewIntent` so React Native sees the updated Intent on warm starts
|
|
419
|
+
- If using CleverTap or similar SDKs, pass a **copy** of the URI to them in `onCreate` rather than the original Intent data
|
|
370
420
|
|
|
371
421
|
### Deferred deep links not attributing
|
|
372
422
|
|
|
373
|
-
1.
|
|
374
|
-
2.
|
|
375
|
-
3. Verify your LinkForty
|
|
423
|
+
1. Confirm this is a first install (or call `clearData()` first)
|
|
424
|
+
2. Enable `debug: true` and check logs for fingerprint data
|
|
425
|
+
3. Verify your LinkForty server received the install event
|
|
376
426
|
4. Ensure the click and install happen within the attribution window (default: 7 days)
|
|
377
|
-
5.
|
|
427
|
+
5. Test on the same network for best fingerprint match accuracy
|
|
378
428
|
|
|
379
429
|
### TypeScript errors
|
|
380
430
|
|
|
381
|
-
|
|
431
|
+
Ensure peer dependencies are installed:
|
|
382
432
|
|
|
383
433
|
```bash
|
|
384
434
|
npm install --save-dev @types/react @types/react-native
|
|
@@ -386,25 +436,18 @@ npm install --save-dev @types/react @types/react-native
|
|
|
386
436
|
|
|
387
437
|
## Contributing
|
|
388
438
|
|
|
389
|
-
Contributions are welcome!
|
|
439
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
390
440
|
|
|
391
441
|
## License
|
|
392
442
|
|
|
393
|
-
MIT License - see [LICENSE](LICENSE)
|
|
443
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
394
444
|
|
|
395
445
|
## Support
|
|
396
446
|
|
|
397
|
-
- **
|
|
398
|
-
- **
|
|
399
|
-
- **Questions:** Open a GitHub Discussion or Issue
|
|
447
|
+
- **Issues:** [GitHub Issues](https://github.com/linkforty/react-native-sdk/issues)
|
|
448
|
+
- **Documentation:** [LinkForty Core](https://github.com/linkforty/core)
|
|
400
449
|
|
|
401
450
|
## Related Projects
|
|
402
451
|
|
|
403
452
|
- [LinkForty Cloud](https://linkforty.com) - Cloud platform with dashboard and API
|
|
404
453
|
- [LinkForty Core](https://github.com/linkforty/core) - Self-hosted open-source backend
|
|
405
|
-
- **iOS SDK** - Native Swift SDK (planned for future release)
|
|
406
|
-
- **Android SDK** - Native Kotlin SDK (planned for future release)
|
|
407
|
-
|
|
408
|
-
---
|
|
409
|
-
|
|
410
|
-
Made with ❤️ by the LinkForty team
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linkforty/mobile-sdk-react-native",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "React Native SDK for LinkForty - Open-source deep linking and mobile attribution platform",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
"react-native": ">=0.64.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@linkforty/mobile-sdk-react-native": "file:linkforty-mobile-sdk-react-native-1.1.2.tgz",
|
|
49
48
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
50
49
|
"react-native-device-info": "^15.0.0"
|
|
51
50
|
},
|