@linkforty/mobile-sdk-react-native 1.0.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 +136 -0
- package/CONTRIBUTING.md +340 -0
- package/LICENSE +21 -0
- package/README.md +410 -0
- package/dist/DeepLinkHandler.d.ts +25 -0
- package/dist/DeepLinkHandler.d.ts.map +1 -0
- package/dist/DeepLinkHandler.js +81 -0
- package/dist/FingerprintCollector.d.ts +23 -0
- package/dist/FingerprintCollector.d.ts.map +1 -0
- package/dist/FingerprintCollector.js +79 -0
- package/dist/LinkFortySDK.d.ts +58 -0
- package/dist/LinkFortySDK.d.ts.map +1 -0
- package/dist/LinkFortySDK.js +258 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/types.d.ts +106 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/examples/AdvancedHooks.tsx +230 -0
- package/examples/BasicSetup.tsx +100 -0
- package/examples/EcommerceTracking.tsx +142 -0
- package/examples/README.md +318 -0
- package/examples/SelfHostedSetup.tsx +126 -0
- package/package.json +68 -0
- package/src/DeepLinkHandler.ts +96 -0
- package/src/FingerprintCollector.ts +90 -0
- package/src/LinkFortySDK.ts +320 -0
- package/src/index.ts +26 -0
- package/src/types.ts +112 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Setup Example
|
|
3
|
+
*
|
|
4
|
+
* This example shows the minimal setup required to integrate
|
|
5
|
+
* LinkForty SDK into a React Native app.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { useEffect } from 'react';
|
|
9
|
+
import { View, Text, StyleSheet } from 'react-native';
|
|
10
|
+
import LinkForty from '@linkforty/react-native-sdk';
|
|
11
|
+
import { useNavigation } from '@react-navigation/native';
|
|
12
|
+
|
|
13
|
+
export default function App() {
|
|
14
|
+
const navigation = useNavigation();
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
// Initialize SDK on app launch
|
|
18
|
+
initializeLinkForty();
|
|
19
|
+
}, []);
|
|
20
|
+
|
|
21
|
+
const initializeLinkForty = async () => {
|
|
22
|
+
try {
|
|
23
|
+
// Initialize with your LinkForty instance URL
|
|
24
|
+
await LinkForty.init({
|
|
25
|
+
baseUrl: 'https://go.yourdomain.com',
|
|
26
|
+
debug: __DEV__, // Enable debug logging in development
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
console.log('LinkForty SDK initialized successfully');
|
|
30
|
+
|
|
31
|
+
// Handle deferred deep links (new installs)
|
|
32
|
+
LinkForty.onDeferredDeepLink((deepLinkData) => {
|
|
33
|
+
if (deepLinkData) {
|
|
34
|
+
console.log('User installed from link:', deepLinkData);
|
|
35
|
+
|
|
36
|
+
// Example: Navigate to a specific product
|
|
37
|
+
if (deepLinkData.customParameters?.productId) {
|
|
38
|
+
navigation.navigate('Product', {
|
|
39
|
+
id: deepLinkData.customParameters.productId,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
console.log('Organic install - no attribution');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Handle direct deep links (existing users)
|
|
48
|
+
LinkForty.onDeepLink((url, deepLinkData) => {
|
|
49
|
+
console.log('Deep link opened:', url);
|
|
50
|
+
|
|
51
|
+
if (deepLinkData) {
|
|
52
|
+
// Navigate based on deep link data
|
|
53
|
+
handleDeepLink(deepLinkData);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Failed to initialize LinkForty:', error);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleDeepLink = (deepLinkData) => {
|
|
62
|
+
// Example: Route to different screens based on UTM parameters
|
|
63
|
+
const { utmParameters, customParameters } = deepLinkData;
|
|
64
|
+
|
|
65
|
+
if (customParameters?.productId) {
|
|
66
|
+
navigation.navigate('Product', { id: customParameters.productId });
|
|
67
|
+
} else if (customParameters?.category) {
|
|
68
|
+
navigation.navigate('Category', { name: customParameters.category });
|
|
69
|
+
} else if (utmParameters?.campaign === 'summer-sale') {
|
|
70
|
+
navigation.navigate('Sale');
|
|
71
|
+
} else {
|
|
72
|
+
navigation.navigate('Home');
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<View style={styles.container}>
|
|
78
|
+
<Text style={styles.title}>LinkForty Example App</Text>
|
|
79
|
+
<Text style={styles.subtitle}>Check console for deep link logs</Text>
|
|
80
|
+
</View>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const styles = StyleSheet.create({
|
|
85
|
+
container: {
|
|
86
|
+
flex: 1,
|
|
87
|
+
justifyContent: 'center',
|
|
88
|
+
alignItems: 'center',
|
|
89
|
+
backgroundColor: '#f5f5f5',
|
|
90
|
+
},
|
|
91
|
+
title: {
|
|
92
|
+
fontSize: 24,
|
|
93
|
+
fontWeight: 'bold',
|
|
94
|
+
marginBottom: 8,
|
|
95
|
+
},
|
|
96
|
+
subtitle: {
|
|
97
|
+
fontSize: 14,
|
|
98
|
+
color: '#666',
|
|
99
|
+
},
|
|
100
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E-commerce Tracking Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to track e-commerce events
|
|
5
|
+
* like product views, add to cart, and purchases.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { useEffect, useState } from 'react';
|
|
9
|
+
import { View, Text, Button, StyleSheet } from 'react-native';
|
|
10
|
+
import LinkForty from '@linkforty/react-native-sdk';
|
|
11
|
+
|
|
12
|
+
export default function ProductScreen({ route }) {
|
|
13
|
+
const { productId } = route.params;
|
|
14
|
+
const [product, setProduct] = useState(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
// Track product view
|
|
18
|
+
trackProductView(productId);
|
|
19
|
+
|
|
20
|
+
// Fetch product data
|
|
21
|
+
fetchProduct(productId);
|
|
22
|
+
}, [productId]);
|
|
23
|
+
|
|
24
|
+
const fetchProduct = async (id: string) => {
|
|
25
|
+
// Your API call here
|
|
26
|
+
const productData = {
|
|
27
|
+
id,
|
|
28
|
+
name: 'Premium Subscription',
|
|
29
|
+
price: 99.99,
|
|
30
|
+
currency: 'USD',
|
|
31
|
+
};
|
|
32
|
+
setProduct(productData);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const trackProductView = async (id: string) => {
|
|
36
|
+
try {
|
|
37
|
+
await LinkForty.trackEvent('product_view', {
|
|
38
|
+
product_id: id,
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
});
|
|
41
|
+
console.log('Product view tracked');
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('Failed to track product view:', error);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const handleAddToCart = async () => {
|
|
48
|
+
if (!product) return;
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
// Track add to cart event
|
|
52
|
+
await LinkForty.trackEvent('add_to_cart', {
|
|
53
|
+
product_id: product.id,
|
|
54
|
+
product_name: product.name,
|
|
55
|
+
price: product.price,
|
|
56
|
+
currency: product.currency,
|
|
57
|
+
quantity: 1,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log('Add to cart event tracked');
|
|
61
|
+
// Navigate to cart or show confirmation
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Failed to track add to cart:', error);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handlePurchase = async () => {
|
|
68
|
+
if (!product) return;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
// Process payment with your payment processor
|
|
72
|
+
const orderId = await processPayment(product);
|
|
73
|
+
|
|
74
|
+
// Track purchase event (conversion event)
|
|
75
|
+
await LinkForty.trackEvent('purchase', {
|
|
76
|
+
order_id: orderId,
|
|
77
|
+
product_id: product.id,
|
|
78
|
+
product_name: product.name,
|
|
79
|
+
amount: product.price,
|
|
80
|
+
currency: product.currency,
|
|
81
|
+
quantity: 1,
|
|
82
|
+
payment_method: 'credit_card',
|
|
83
|
+
timestamp: new Date().toISOString(),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
console.log('Purchase event tracked - this triggers webhooks!');
|
|
87
|
+
|
|
88
|
+
// Show success message and navigate
|
|
89
|
+
alert('Purchase successful!');
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('Purchase failed:', error);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const processPayment = async (product) => {
|
|
96
|
+
// Your payment processing logic
|
|
97
|
+
return 'ORDER-' + Date.now();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
if (!product) {
|
|
101
|
+
return (
|
|
102
|
+
<View style={styles.container}>
|
|
103
|
+
<Text>Loading...</Text>
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<View style={styles.container}>
|
|
110
|
+
<Text style={styles.title}>{product.name}</Text>
|
|
111
|
+
<Text style={styles.price}>
|
|
112
|
+
${product.price} {product.currency}
|
|
113
|
+
</Text>
|
|
114
|
+
|
|
115
|
+
<View style={styles.buttonContainer}>
|
|
116
|
+
<Button title="Add to Cart" onPress={handleAddToCart} />
|
|
117
|
+
<Button title="Buy Now" onPress={handlePurchase} />
|
|
118
|
+
</View>
|
|
119
|
+
</View>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const styles = StyleSheet.create({
|
|
124
|
+
container: {
|
|
125
|
+
flex: 1,
|
|
126
|
+
padding: 20,
|
|
127
|
+
backgroundColor: '#fff',
|
|
128
|
+
},
|
|
129
|
+
title: {
|
|
130
|
+
fontSize: 24,
|
|
131
|
+
fontWeight: 'bold',
|
|
132
|
+
marginBottom: 10,
|
|
133
|
+
},
|
|
134
|
+
price: {
|
|
135
|
+
fontSize: 20,
|
|
136
|
+
color: '#26adae',
|
|
137
|
+
marginBottom: 20,
|
|
138
|
+
},
|
|
139
|
+
buttonContainer: {
|
|
140
|
+
gap: 10,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# LinkForty React Native SDK Examples
|
|
2
|
+
|
|
3
|
+
This directory contains practical examples demonstrating how to integrate and use the LinkForty React Native SDK in real-world applications.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### 1. BasicSetup.tsx
|
|
8
|
+
**Level:** Beginner
|
|
9
|
+
**Use Case:** Getting started with LinkForty
|
|
10
|
+
|
|
11
|
+
Shows the minimal setup required to integrate LinkForty into a React Native app:
|
|
12
|
+
- SDK initialization
|
|
13
|
+
- Handling deferred deep links (new installs)
|
|
14
|
+
- Handling direct deep links (existing users)
|
|
15
|
+
- Basic navigation based on deep link data
|
|
16
|
+
|
|
17
|
+
**Key Concepts:**
|
|
18
|
+
- SDK configuration
|
|
19
|
+
- Deep link callbacks
|
|
20
|
+
- UTM parameter routing
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### 2. EcommerceTracking.tsx
|
|
25
|
+
**Level:** Intermediate
|
|
26
|
+
**Use Case:** E-commerce and conversion tracking
|
|
27
|
+
|
|
28
|
+
Demonstrates tracking e-commerce events for attribution and analytics:
|
|
29
|
+
- Product view tracking
|
|
30
|
+
- Add to cart events
|
|
31
|
+
- Purchase conversion tracking
|
|
32
|
+
- Revenue and order tracking
|
|
33
|
+
|
|
34
|
+
**Key Concepts:**
|
|
35
|
+
- Event tracking API
|
|
36
|
+
- Conversion events
|
|
37
|
+
- Webhook triggers
|
|
38
|
+
- Revenue attribution
|
|
39
|
+
|
|
40
|
+
**Triggers Webhooks:** ✅ Yes (on purchase events)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### 3. SelfHostedSetup.tsx
|
|
45
|
+
**Level:** Intermediate
|
|
46
|
+
**Use Case:** Using self-hosted LinkForty Core
|
|
47
|
+
|
|
48
|
+
Shows how to configure the SDK for self-hosted LinkForty Core instances:
|
|
49
|
+
- Local development setup
|
|
50
|
+
- Production self-hosted setup
|
|
51
|
+
- Custom attribution windows
|
|
52
|
+
- Docker Compose configuration
|
|
53
|
+
|
|
54
|
+
**Key Concepts:**
|
|
55
|
+
- Self-hosting configuration
|
|
56
|
+
- Custom base URLs
|
|
57
|
+
- Development vs. production setups
|
|
58
|
+
- Docker deployment
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### 4. AdvancedHooks.tsx
|
|
63
|
+
**Level:** Advanced
|
|
64
|
+
**Use Case:** TypeScript and custom React hooks
|
|
65
|
+
|
|
66
|
+
Advanced patterns using custom React hooks and TypeScript:
|
|
67
|
+
- `useLinkForty` - SDK initialization hook
|
|
68
|
+
- `useInstallAttribution` - Attribution data hook
|
|
69
|
+
- `useDeepLink` - Deep link handling hook
|
|
70
|
+
- `useEventTracking` - Event tracking with state management
|
|
71
|
+
- TypeScript utility functions
|
|
72
|
+
- Error handling patterns
|
|
73
|
+
|
|
74
|
+
**Key Concepts:**
|
|
75
|
+
- Custom React hooks
|
|
76
|
+
- TypeScript patterns
|
|
77
|
+
- State management
|
|
78
|
+
- Error handling
|
|
79
|
+
- Utility functions
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Quick Start
|
|
84
|
+
|
|
85
|
+
### Running the Examples
|
|
86
|
+
|
|
87
|
+
1. **Create a new React Native project:**
|
|
88
|
+
```bash
|
|
89
|
+
npx react-native init LinkFortyExample
|
|
90
|
+
cd LinkFortyExample
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
2. **Install the SDK:**
|
|
94
|
+
```bash
|
|
95
|
+
npm install @linkforty/react-native-sdk
|
|
96
|
+
npm install @react-native-async-storage/async-storage react-native-device-info
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
3. **Copy an example:**
|
|
100
|
+
```bash
|
|
101
|
+
# Copy the example you want to try
|
|
102
|
+
cp node_modules/@linkforty/react-native-sdk/examples/BasicSetup.tsx ./App.tsx
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
4. **Update configuration:**
|
|
106
|
+
```typescript
|
|
107
|
+
// Replace with your LinkForty instance URL
|
|
108
|
+
await LinkForty.init({
|
|
109
|
+
baseUrl: 'https://go.yourdomain.com',
|
|
110
|
+
debug: true,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
5. **Configure deep linking:**
|
|
115
|
+
|
|
116
|
+
**iOS (ios/YourApp/Info.plist):**
|
|
117
|
+
```xml
|
|
118
|
+
<key>CFBundleURLTypes</key>
|
|
119
|
+
<array>
|
|
120
|
+
<dict>
|
|
121
|
+
<key>CFBundleURLSchemes</key>
|
|
122
|
+
<array>
|
|
123
|
+
<string>yourapp</string>
|
|
124
|
+
</array>
|
|
125
|
+
</dict>
|
|
126
|
+
</array>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Android (android/app/src/main/AndroidManifest.xml):**
|
|
130
|
+
```xml
|
|
131
|
+
<intent-filter android:autoVerify="true">
|
|
132
|
+
<action android:name="android.intent.action.VIEW" />
|
|
133
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
134
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
135
|
+
<data android:scheme="https" />
|
|
136
|
+
<data android:host="go.yourdomain.com" />
|
|
137
|
+
</intent-filter>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
6. **Run the app:**
|
|
141
|
+
```bash
|
|
142
|
+
# iOS
|
|
143
|
+
npx react-native run-ios
|
|
144
|
+
|
|
145
|
+
# Android
|
|
146
|
+
npx react-native run-android
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Testing Deep Links
|
|
152
|
+
|
|
153
|
+
### iOS Testing
|
|
154
|
+
|
|
155
|
+
1. **Create a test link** in your LinkForty dashboard
|
|
156
|
+
2. **Uninstall the app** from your device
|
|
157
|
+
3. **Open Safari** and navigate to your LinkForty short link
|
|
158
|
+
4. **Install the app** from the App Store or Xcode
|
|
159
|
+
5. **Check the console** for deferred deep link data
|
|
160
|
+
|
|
161
|
+
### Android Testing
|
|
162
|
+
|
|
163
|
+
1. **Create a test link** in your LinkForty dashboard
|
|
164
|
+
2. **Uninstall the app** from your device
|
|
165
|
+
3. **Open Chrome** and navigate to your LinkForty short link
|
|
166
|
+
4. **Install the app** from the Play Store or Android Studio
|
|
167
|
+
5. **Check Logcat** for deferred deep link data
|
|
168
|
+
|
|
169
|
+
### Testing Direct Deep Links (Existing Users)
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# iOS
|
|
173
|
+
xcrun simctl openurl booted "https://go.yourdomain.com/abc123"
|
|
174
|
+
|
|
175
|
+
# Android
|
|
176
|
+
adb shell am start -W -a android.intent.action.VIEW \
|
|
177
|
+
-d "https://go.yourdomain.com/abc123" com.yourapp
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Common Use Cases
|
|
183
|
+
|
|
184
|
+
### E-commerce App
|
|
185
|
+
Use `EcommerceTracking.tsx` to:
|
|
186
|
+
- Track product views for analytics
|
|
187
|
+
- Monitor add-to-cart conversion rates
|
|
188
|
+
- Attribute purchases to marketing campaigns
|
|
189
|
+
- Trigger conversion webhooks to your backend
|
|
190
|
+
|
|
191
|
+
### Content App
|
|
192
|
+
Use `BasicSetup.tsx` to:
|
|
193
|
+
- Route users to specific articles or videos
|
|
194
|
+
- Track content engagement
|
|
195
|
+
- Measure campaign effectiveness
|
|
196
|
+
- Enable social sharing with attribution
|
|
197
|
+
|
|
198
|
+
### SaaS/Subscription App
|
|
199
|
+
Combine `EcommerceTracking.tsx` + `AdvancedHooks.tsx` to:
|
|
200
|
+
- Track trial signups
|
|
201
|
+
- Monitor subscription conversions
|
|
202
|
+
- Attribute revenue to campaigns
|
|
203
|
+
- Calculate customer acquisition cost (CAC)
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🔗 Deep Link URL Structure
|
|
208
|
+
|
|
209
|
+
### Example LinkForty Link
|
|
210
|
+
```
|
|
211
|
+
https://go.yourdomain.com/summer24
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Configured URLs in LinkForty Dashboard
|
|
215
|
+
|
|
216
|
+
**iOS URL:**
|
|
217
|
+
```
|
|
218
|
+
yourapp://product/123?ref=summer24
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Android URL:**
|
|
222
|
+
```
|
|
223
|
+
yourapp://product/123?ref=summer24
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**UTM Parameters:**
|
|
227
|
+
```
|
|
228
|
+
utm_source=facebook
|
|
229
|
+
utm_medium=cpc
|
|
230
|
+
utm_campaign=summer-sale
|
|
231
|
+
utm_content=product-123
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Handling in Your App
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
LinkForty.onDeepLink((url, deepLinkData) => {
|
|
238
|
+
console.log('Full URL:', url);
|
|
239
|
+
// Output: yourapp://product/123?ref=summer24
|
|
240
|
+
|
|
241
|
+
console.log('Deep link data:', deepLinkData);
|
|
242
|
+
// Output: {
|
|
243
|
+
// shortCode: 'summer24',
|
|
244
|
+
// utmParameters: {
|
|
245
|
+
// source: 'facebook',
|
|
246
|
+
// medium: 'cpc',
|
|
247
|
+
// campaign: 'summer-sale',
|
|
248
|
+
// content: 'product-123'
|
|
249
|
+
// },
|
|
250
|
+
// customParameters: {
|
|
251
|
+
// ref: 'summer24'
|
|
252
|
+
// }
|
|
253
|
+
// }
|
|
254
|
+
|
|
255
|
+
// Navigate to product screen
|
|
256
|
+
navigation.navigate('Product', { id: '123' });
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Debugging Tips
|
|
263
|
+
|
|
264
|
+
### Enable Debug Logging
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
await LinkForty.init({
|
|
268
|
+
baseUrl: 'https://go.yourdomain.com',
|
|
269
|
+
debug: true, // Enable verbose logging
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Check Install Data
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
const installData = await LinkForty.getInstallData();
|
|
277
|
+
console.log('Install data:', installData);
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Clear Cached Data (Testing)
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
await LinkForty.clearData();
|
|
284
|
+
// App will behave as if it's a fresh install
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Verify SDK Health
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# Check if your LinkForty instance is reachable
|
|
291
|
+
curl https://go.yourdomain.com/api/sdk/v1/health
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Additional Resources
|
|
297
|
+
|
|
298
|
+
- **Full Documentation:** [https://docs.linkforty.com](https://docs.linkforty.com)
|
|
299
|
+
- **API Reference:** See main [README.md](../README.md#api-reference)
|
|
300
|
+
- **GitHub Issues:** [Report bugs or request features](https://github.com/linkforty/react-native-sdk/issues)
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Contributing
|
|
305
|
+
|
|
306
|
+
Have a great example to share? We'd love to include it!
|
|
307
|
+
|
|
308
|
+
1. Create your example following the existing pattern
|
|
309
|
+
2. Add documentation to this README
|
|
310
|
+
3. Submit a pull request
|
|
311
|
+
|
|
312
|
+
See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## License
|
|
317
|
+
|
|
318
|
+
All examples are licensed under the MIT License - use them freely in your projects!
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Hosted LinkForty Core Setup Example
|
|
3
|
+
*
|
|
4
|
+
* This example shows how to use the SDK with a self-hosted
|
|
5
|
+
* LinkForty Core instance.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { useEffect } from 'react';
|
|
9
|
+
import LinkForty from '@linkforty/react-native-sdk';
|
|
10
|
+
|
|
11
|
+
export default function App() {
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
initializeSelfHosted();
|
|
14
|
+
}, []);
|
|
15
|
+
|
|
16
|
+
const initializeSelfHosted = async () => {
|
|
17
|
+
try {
|
|
18
|
+
// Option 1: Local Development
|
|
19
|
+
await LinkForty.init({
|
|
20
|
+
baseUrl: 'http://192.168.1.100:3000', // Your local machine IP
|
|
21
|
+
debug: true,
|
|
22
|
+
attributionWindow: 7, // 7 days
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Option 2: Self-Hosted Production
|
|
26
|
+
// await LinkForty.init({
|
|
27
|
+
// baseUrl: 'https://links.yourcompany.com',
|
|
28
|
+
// debug: false,
|
|
29
|
+
// attributionWindow: 14, // 14 days
|
|
30
|
+
// });
|
|
31
|
+
|
|
32
|
+
// Option 3: Self-Hosted with Custom Domain
|
|
33
|
+
// await LinkForty.init({
|
|
34
|
+
// baseUrl: 'https://go.yourapp.com',
|
|
35
|
+
// debug: false,
|
|
36
|
+
// });
|
|
37
|
+
|
|
38
|
+
console.log('Connected to self-hosted LinkForty instance');
|
|
39
|
+
|
|
40
|
+
// Set up deep link handlers
|
|
41
|
+
setupDeepLinkHandlers();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('Failed to connect to self-hosted instance:', error);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const setupDeepLinkHandlers = () => {
|
|
48
|
+
LinkForty.onDeferredDeepLink((deepLinkData) => {
|
|
49
|
+
if (deepLinkData) {
|
|
50
|
+
console.log('Attribution data:', {
|
|
51
|
+
source: deepLinkData.utmParameters?.source,
|
|
52
|
+
medium: deepLinkData.utmParameters?.medium,
|
|
53
|
+
campaign: deepLinkData.utmParameters?.campaign,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Track install with custom properties
|
|
57
|
+
trackCustomInstall(deepLinkData);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
LinkForty.onDeepLink((url, deepLinkData) => {
|
|
62
|
+
console.log('Deep link URL:', url);
|
|
63
|
+
console.log('Deep link data:', deepLinkData);
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const trackCustomInstall = async (deepLinkData) => {
|
|
68
|
+
try {
|
|
69
|
+
// Track install event with custom attribution data
|
|
70
|
+
await LinkForty.trackEvent('app_install', {
|
|
71
|
+
source: deepLinkData.utmParameters?.source || 'organic',
|
|
72
|
+
medium: deepLinkData.utmParameters?.medium || 'none',
|
|
73
|
+
campaign: deepLinkData.utmParameters?.campaign || 'none',
|
|
74
|
+
click_id: deepLinkData.linkId,
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log('Install tracked on self-hosted instance');
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('Failed to track install:', error);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return null; // Your app UI
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Docker Compose Setup for Self-Hosting
|
|
89
|
+
*
|
|
90
|
+
* To run LinkForty Core locally with Docker:
|
|
91
|
+
*
|
|
92
|
+
* 1. Create docker-compose.yml:
|
|
93
|
+
*
|
|
94
|
+
* ```yaml
|
|
95
|
+
* version: '3.8'
|
|
96
|
+
* services:
|
|
97
|
+
* linkforty:
|
|
98
|
+
* image: linkforty/linkforty:latest
|
|
99
|
+
* ports:
|
|
100
|
+
* - "3000:3000"
|
|
101
|
+
* environment:
|
|
102
|
+
* DATABASE_URL: postgresql://postgres:password@postgres:5432/linkforty
|
|
103
|
+
* REDIS_URL: redis://redis:6379
|
|
104
|
+
* postgres:
|
|
105
|
+
* image: postgres:15-alpine
|
|
106
|
+
* environment:
|
|
107
|
+
* POSTGRES_DB: linkforty
|
|
108
|
+
* POSTGRES_PASSWORD: password
|
|
109
|
+
* redis:
|
|
110
|
+
* image: redis:7-alpine
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* 2. Start services:
|
|
114
|
+
* ```bash
|
|
115
|
+
* docker-compose up -d
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* 3. Access at http://localhost:3000
|
|
119
|
+
*
|
|
120
|
+
* 4. Update SDK to point to your local IP:
|
|
121
|
+
* ```typescript
|
|
122
|
+
* await LinkForty.init({
|
|
123
|
+
* baseUrl: 'http://192.168.1.100:3000'
|
|
124
|
+
* });
|
|
125
|
+
* ```
|
|
126
|
+
*/
|