React Native SDK
Integrate deferred deep linking and mobile attribution into your React Native app with the LinkForty SDK.
Features
- ✅ Deferred Deep Linking - Route new users to specific content after install
- ✅ Direct Deep Linking - Handle links for existing users
- ✅ Attribution Tracking - Track which links drive installs
- ✅ Event Tracking - Log in-app events with attribution
- ✅ Fingerprint Matching - 70%+ attribution accuracy
- ✅ TypeScript Support - Full type definitions included
- ✅ Cross-Platform - iOS and Android with single codebase
Installation
1. Install Package
npm install @linkforty/react-native
or
yarn add @linkforty/react-native
2. Link Native Dependencies
For React Native 0.60+: Auto-linking handles this automatically.
For React Native < 0.60:
react-native link @linkforty/react-native
3. iOS Setup
cd ios && pod install && cd ..
Add to ios/YourApp/Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>linkforty</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
</array>
4. Android Setup
Add to android/app/src/main/AndroidManifest.xml:
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourapp" />
</intent-filter>
</activity>
Quick Start
1. Initialize SDK
In your App.tsx or App.js:
import React, { useEffect } from 'react';
import { LinkFortySDK } from '@linkforty/react-native';
function App() {
useEffect(() => {
// Initialize SDK on app launch
LinkFortySDK.initialize({
apiKey: 'your-api-key',
apiUrl: 'https://api.linkforty.com', // Optional: defaults to LinkForty Cloud
enableLogging: __DEV__, // Enable debug logs in development
});
}, []);
return (
// Your app components
);
}
export default App;
2. Handle Deep Links
import React, { useEffect } from 'react';
import { LinkFortySDK } from '@linkforty/react-native';
import { useNavigation } from '@react-navigation/native';
function App() {
const navigation = useNavigation();
useEffect(() => {
// Initialize SDK
LinkFortySDK.initialize({
apiKey: 'your-api-key',
});
// Check for deep link data on app launch
checkDeepLink();
}, []);
const checkDeepLink = async () => {
try {
const deepLinkData = await LinkFortySDK.getDeepLinkData();
if (deepLinkData) {
console.log('Deep link data:', deepLinkData);
// Navigate to specific content
if (deepLinkData.productId) {
navigation.navigate('Product', { id: deepLinkData.productId });
} else if (deepLinkData.screen) {
navigation.navigate(deepLinkData.screen);
}
}
} catch (error) {
console.error('Error getting deep link data:', error);
}
};
return (
// Your app components
);
}
3. Track Events
import { LinkFortySDK } from '@linkforty/react-native';
// Track purchase
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 29.99,
currency: 'USD',
properties: {
productId: '123',
productName: 'Wireless Headphones',
quantity: 1
}
});
// Track registration
await LinkFortySDK.trackEvent({
eventName: 'signup',
properties: {
method: 'email'
}
});
// Track custom event
await LinkFortySDK.trackEvent({
eventName: 'level_completed',
properties: {
level: 5,
score: 1250
}
});
Configuration Options
Initialize Options
interface InitializeOptions {
apiKey: string; // Required: Your LinkForty API key
apiUrl?: string; // Optional: API URL (defaults to Cloud)
enableLogging?: boolean; // Optional: Enable debug logs (default: false)
timeout?: number; // Optional: Network timeout in ms (default: 10000)
}
LinkFortySDK.initialize({
apiKey: 'your-api-key',
apiUrl: 'https://api.linkforty.com',
enableLogging: __DEV__,
timeout: 15000
});
Self-Hosted Configuration
If you're self-hosting LinkForty:
LinkFortySDK.initialize({
apiKey: 'your-api-key',
apiUrl: 'https://your-domain.com' // Your self-hosted URL
});
Deep Linking
Creating a Link
Create links via dashboard or API that include deep link parameters:
curl -X POST https://api.linkforty.com/api/links \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "550e8400-e29b-41d4-a716-446655440000",
"originalUrl": "https://example.com/products/123?productId=123&utm_source=instagram",
"iosUrl": "https://apps.apple.com/app/id123456789",
"androidUrl": "https://play.google.com/store/apps/details?id=com.yourapp"
}'
Deep Link Parameters:
- Any query parameter in
originalUrlbecomes available in deep link data - Example:
?productId=123&category=electronics
Handling Deep Links
Deferred Deep Linking (new installs):
useEffect(() => {
const handleDeepLink = async () => {
const data = await LinkFortySDK.getDeepLinkData();
if (data) {
// User clicked a link before installing
console.log('Deferred deep link:', data);
// Example data:
// {
// productId: "123",
// category: "electronics",
// utm_source: "instagram",
// utm_campaign: "spring-sale"
// }
// Navigate to product
navigation.navigate('Product', { id: data.productId });
}
};
handleDeepLink();
}, []);
Direct Deep Linking (existing users):
import { Linking } from 'react-native';
useEffect(() => {
// Listen for deep link opens
const subscription = Linking.addEventListener('url', ({ url }) => {
handleDirectDeepLink(url);
});
// Check if app was opened with a URL
Linking.getInitialURL().then(url => {
if (url) {
handleDirectDeepLink(url);
}
});
return () => {
subscription.remove();
};
}, []);
const handleDirectDeepLink = (url: string) => {
// Parse URL: yourapp://product/123
const parts = url.replace('yourapp://', '').split('/');
if (parts[0] === 'product' && parts[1]) {
navigation.navigate('Product', { id: parts[1] });
}
};
Combined Approach (Recommended)
Handle both deferred and direct deep links:
import React, { useEffect, useCallback } from 'react';
import { Linking } from 'react-native';
import { LinkFortySDK } from '@linkforty/react-native';
import { useNavigation } from '@react-navigation/native';
function App() {
const navigation = useNavigation();
useEffect(() => {
// Initialize SDK
LinkFortySDK.initialize({
apiKey: 'your-api-key',
});
// Check for deferred deep link (new installs)
checkDeferredDeepLink();
// Set up direct deep link listener (existing users)
setupDirectDeepLinking();
}, []);
const checkDeferredDeepLink = async () => {
const data = await LinkFortySDK.getDeepLinkData();
if (data) {
handleDeepLinkData(data);
}
};
const setupDirectDeepLinking = () => {
// Handle app opened with URL
Linking.getInitialURL().then(url => {
if (url) handleDirectDeepLink(url);
});
// Listen for URL opens while app is running
const subscription = Linking.addEventListener('url', ({ url }) => {
handleDirectDeepLink(url);
});
return () => subscription.remove();
};
const handleDirectDeepLink = (url: string) => {
// Parse yourapp:// URLs
const route = url.replace('yourapp://', '');
// Navigate based on route
if (route.startsWith('product/')) {
const id = route.split('/')[1];
navigation.navigate('Product', { id });
}
};
const handleDeepLinkData = (data: any) => {
// Handle deferred deep link data
if (data.productId) {
navigation.navigate('Product', { id: data.productId });
} else if (data.screen) {
navigation.navigate(data.screen, data.params || {});
}
};
return (
// Your app
);
}
Event Tracking
Track Events with Attribution
import { LinkFortySDK } from '@linkforty/react-native';
// Purchase event
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 49.99,
currency: 'USD',
properties: {
productId: '123',
productName: 'Wireless Headphones',
category: 'Electronics',
quantity: 1
}
});
// Add to cart
await LinkFortySDK.trackEvent({
eventName: 'add_to_cart',
value: 49.99,
currency: 'USD',
properties: {
productId: '123',
source: 'product_page'
}
});
// User registration
await LinkFortySDK.trackEvent({
eventName: 'signup',
properties: {
method: 'email',
referralCode: 'FRIEND123'
}
});
// Custom event
await LinkFortySDK.trackEvent({
eventName: 'tutorial_completed',
properties: {
duration_seconds: 120,
steps_completed: 5
}
});
Event Properties
interface TrackEventParams {
eventName: string; // Required: Event name
value?: number; // Optional: Monetary value
currency?: string; // Optional: Currency code (USD, EUR, etc.)
properties?: { // Optional: Custom properties
[key: string]: string | number | boolean;
};
}
Standard Events
Recommended event names for common actions:
| Event Name | Description | Properties |
|---|---|---|
purchase | User completes purchase | value, currency, productId |
add_to_cart | Item added to cart | productId, value |
begin_checkout | Checkout started | value, currency |
signup | User registers | method (email, social, etc.) |
login | User logs in | method |
view_content | Content viewed | contentType, contentId |
search | User searches | query, results |
share | Content shared | contentType, method |
level_completed | Game level completed | level, score |
achievement_unlocked | Achievement earned | achievement_id |
API Reference
initialize()
Initialize the SDK. Call once on app launch.
LinkFortySDK.initialize(options: InitializeOptions): void
Parameters:
{
apiKey: string; // Your LinkForty API key
apiUrl?: string; // API URL (default: https://api.linkforty.com)
enableLogging?: boolean; // Enable debug logs (default: false)
timeout?: number; // Network timeout in ms (default: 10000)
}
Example:
LinkFortySDK.initialize({
apiKey: 'your-api-key',
enableLogging: __DEV__
});
getDeepLinkData()
Get deep link data from initial click (deferred deep linking).
LinkFortySDK.getDeepLinkData(): Promise<DeepLinkData | null>
Returns: Object with deep link parameters, or null if no match found.
Example:
const data = await LinkFortySDK.getDeepLinkData();
if (data) {
console.log(data);
// {
// productId: "123",
// utm_source: "instagram",
// utm_campaign: "spring-sale"
// }
}
Attribution Matching:
- Checks if user clicked a LinkForty link before installing
- Uses device fingerprint for matching
- Respects attribution window configured in link (default: 7 days)
- Returns
nullif no match or window expired
trackEvent()
Track custom events with attribution.
LinkFortySDK.trackEvent(params: TrackEventParams): Promise<void>
Parameters:
{
eventName: string; // Event name
value?: number; // Monetary value
currency?: string; // Currency (USD, EUR, etc.)
properties?: object; // Custom properties
}
Example:
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 29.99,
currency: 'USD',
properties: {
productId: '123',
category: 'Electronics'
}
});
setUserIdentifier()
Associate events with a user ID.
LinkFortySDK.setUserIdentifier(userId: string): void
Example:
// After user logs in
LinkFortySDK.setUserIdentifier('user_abc123');
// Events are now associated with this user
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 49.99
});
clearUserIdentifier()
Clear user identifier (e.g., on logout).
LinkFortySDK.clearUserIdentifier(): void
Example:
// On logout
LinkFortySDK.clearUserIdentifier();
Complete Example
E-commerce App
import React, { useEffect, useState } from 'react';
import { View, Text, Button } from 'react-native';
import { LinkFortySDK } from '@linkforty/react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function App() {
useEffect(() => {
// Initialize SDK
LinkFortySDK.initialize({
apiKey: 'your-api-key',
enableLogging: __DEV__
});
// Check for deferred deep link
checkForDeepLink();
}, []);
const checkForDeepLink = async () => {
const deepLinkData = await LinkFortySDK.getDeepLinkData();
if (deepLinkData) {
console.log('User installed from link:', deepLinkData);
// Navigate to product if specified
if (deepLinkData.productId) {
// Wait for navigation to be ready
setTimeout(() => {
navigation.navigate('Product', { id: deepLinkData.productId });
}, 100);
}
}
};
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Product" component={ProductScreen} />
<Stack.Screen name="Cart" component={CartScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
function ProductScreen({ route }) {
const { id } = route.params;
const [product, setProduct] = useState(null);
useEffect(() => {
// Load product data
loadProduct(id);
// Track product view
LinkFortySDK.trackEvent({
eventName: 'view_content',
properties: {
contentType: 'product',
contentId: id
}
});
}, [id]);
const handleAddToCart = async () => {
// Track add to cart
await LinkFortySDK.trackEvent({
eventName: 'add_to_cart',
value: product.price,
currency: 'USD',
properties: {
productId: id,
productName: product.name
}
});
// Add to cart logic...
};
const handlePurchase = async () => {
// Track purchase
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: product.price,
currency: 'USD',
properties: {
productId: id,
productName: product.name,
category: product.category
}
});
// Complete purchase...
};
return (
<View>
<Text>{product?.name}</Text>
<Text>${product?.price}</Text>
<Button title="Add to Cart" onPress={handleAddToCart} />
<Button title="Buy Now" onPress={handlePurchase} />
</View>
);
}
export default App;
Troubleshooting
Deep Link Data Not Returning
Symptoms:
getDeepLinkData()returnsnull- User definitely clicked link before installing
Possible Causes:
-
Attribution window expired
- Check link's attribution window setting
- User may have installed too long after clicking
-
Fingerprint mismatch
- Different WiFi network for click vs install
- VPN or proxy usage
- iOS 14+ privacy features
-
SDK not initialized
- Verify
initialize()is called beforegetDeepLinkData()
- Verify
-
Wrong API key
- Check API key is correct
- Verify it's for the right environment
Solutions:
// Enable logging to debug
LinkFortySDK.initialize({
apiKey: 'your-api-key',
enableLogging: true
});
// Check for detailed errors
const data = await LinkFortySDK.getDeepLinkData();
console.log('Deep link result:', data);
Events Not Tracking
Symptoms:
trackEvent()succeeds but events don't appear in analytics
Possible Causes:
- Network connectivity issues
- Invalid API key
- Events delayed (batched)
Solutions:
try {
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 29.99
});
console.log('Event tracked successfully');
} catch (error) {
console.error('Error tracking event:', error);
}
iOS Build Errors
Symptoms:
- Build fails after installing SDK
Solution:
cd ios
pod deintegrate
pod install
cd ..
Next Steps
- 📊 View Analytics - Monitor app performance
- 🔗 Create Links - Set up deep links
- 🎯 Attribution Windows - Configure attribution
- 📱 iOS SDK - Native iOS implementation
- 🤖 Android SDK - Native Android implementation