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/mobile-sdk-react-native
or
yarn add @linkforty/mobile-sdk-react-native
2. Install Peer Dependencies
The SDK requires these peer dependencies:
npm install @react-native-async-storage/async-storage react-native-device-info
3. Link Native Dependencies
For React Native 0.60+: Auto-linking handles this automatically.
For React Native < 0.60:
react-native link @linkforty/mobile-sdk-react-native
react-native link @react-native-async-storage/async-storage
react-native link react-native-device-info
4. 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>
5. 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/mobile-sdk-react-native';
function App() {
useEffect(() => {
// Initialize SDK on app launch
LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com', // Your LinkForty instance URL
apiKey: 'your-api-key', // Optional for cloud, required for some features
debug: __DEV__, // Enable debug logs in development
});
}, []);
return (
// Your app components
);
}
export default App;
2. Handle Deep Links
import React, { useEffect } from 'react';
import { LinkFortySDK, DeepLinkData } from '@linkforty/mobile-sdk-react-native';
import { useNavigation } from '@react-navigation/native';
function App() {
const navigation = useNavigation();
useEffect(() => {
// Initialize SDK
LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com',
apiKey: 'your-api-key',
});
// Set up deep link listeners
setupDeepLinkHandlers();
}, []);
const setupDeepLinkHandlers = () => {
// Handle deferred deep links (new installs)
LinkFortySDK.onDeferredDeepLink((data: DeepLinkData) => {
console.log('Deferred deep link:', data);
handleDeepLinkData(data);
});
// Handle direct deep links (app already installed)
LinkFortySDK.onDeepLink((data: DeepLinkData) => {
console.log('Direct deep link:', data);
handleDeepLinkData(data);
});
};
const handleDeepLinkData = (data: DeepLinkData) => {
// Access custom parameters from the link
const productId = data.customParameters?.productId;
const screen = data.customParameters?.screen;
// Access UTM parameters
const utmSource = data.utmParameters?.utm_source;
if (productId) {
navigation.navigate('Product', { id: productId });
} else if (screen) {
navigation.navigate(screen);
}
};
return (
// Your app components
);
}
3. Track Events
import { LinkFortySDK } from '@linkforty/mobile-sdk-react-native';
// Track purchase
LinkFortySDK.trackEvent('purchase', {
value: 29.99,
currency: 'USD',
productId: '123',
productName: 'Wireless Headphones',
quantity: 1
});
// Track registration
LinkFortySDK.trackEvent('signup', {
method: 'email'
});
// Track custom event
LinkFortySDK.trackEvent('level_completed', {
level: 5,
score: 1250
});
Configuration Options
Init Options
interface LinkFortyConfig {
baseUrl: string; // Required: Your LinkForty instance URL
apiKey?: string; // Optional: API key for authentication
debug?: boolean; // Optional: Enable debug logs (default: false)
attributionWindow?: number; // Optional: Attribution window in days (default: 7)
}
LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com',
apiKey: 'your-api-key',
debug: __DEV__,
attributionWindow: 7
});
Self-Hosted Configuration
If you're self-hosting LinkForty:
LinkFortySDK.init({
baseUrl: 'https://your-domain.com', // Your self-hosted URL
apiKey: 'your-api-key',
debug: false
});
Deep Linking
Creating a Link
Create links via dashboard or API that include deep link parameters:
curl -X POST https://your-linkforty-domain.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:
- Query parameters in
originalUrlbecome available incustomParameters - UTM parameters are automatically extracted to
utmParameters - Example:
?productId=123&category=electronics&utm_source=instagram
DeepLinkData Structure
The DeepLinkData object contains:
interface DeepLinkData {
shortCode: string; // The short link code
iosUrl?: string; // iOS app store URL
androidUrl?: string; // Android play store URL
webUrl?: string; // Web fallback URL
utmParameters?: { // UTM tracking parameters
utm_source?: string;
utm_medium?: string;
utm_campaign?: string;
utm_term?: string;
utm_content?: string;
};
customParameters?: { // Custom parameters from link URL
[key: string]: string;
};
clickedAt?: string; // When the link was clicked
linkId?: string; // Unique link identifier
}
Handling Deep Links
Deferred Deep Linking (new installs):
useEffect(() => {
// Register callback for deferred deep links
LinkFortySDK.onDeferredDeepLink((data: DeepLinkData) => {
// User clicked a link before installing
console.log('Deferred deep link:', data);
// Example data structure:
// {
// shortCode: "abc123",
// customParameters: {
// productId: "123",
// category: "electronics"
// },
// utmParameters: {
// utm_source: "instagram",
// utm_campaign: "spring-sale"
// }
// }
// Navigate to product
if (data.customParameters?.productId) {
navigation.navigate('Product', { id: data.customParameters.productId });
}
});
}, []);
Direct Deep Linking (existing users):
useEffect(() => {
// Register callback for direct deep links
LinkFortySDK.onDeepLink((data: DeepLinkData) => {
console.log('Direct deep link:', data);
if (data.customParameters?.productId) {
navigation.navigate('Product', { id: data.customParameters.productId });
}
});
}, []);
Combined Approach (Recommended)
Handle both deferred and direct deep links:
import React, { useEffect } from 'react';
import { LinkFortySDK, DeepLinkData } from '@linkforty/mobile-sdk-react-native';
import { useNavigation } from '@react-navigation/native';
function App() {
const navigation = useNavigation();
useEffect(() => {
// Initialize SDK
LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com',
apiKey: 'your-api-key',
debug: __DEV__,
});
// Handle deferred deep links (new installs)
LinkFortySDK.onDeferredDeepLink((data: DeepLinkData) => {
console.log('Deferred deep link:', data);
handleDeepLinkData(data);
});
// Handle direct deep links (existing users)
LinkFortySDK.onDeepLink((data: DeepLinkData) => {
console.log('Direct deep link:', data);
handleDeepLinkData(data);
});
}, []);
const handleDeepLinkData = (data: DeepLinkData) => {
// Extract routing info from customParameters
const route = data.customParameters?.route;
const productId = data.customParameters?.productId;
const screen = data.customParameters?.screen;
if (productId) {
navigation.navigate('Product', { id: productId });
} else if (route) {
navigation.navigate(route, data.customParameters);
} else if (screen) {
navigation.navigate(screen);
}
};
return (
// Your app
);
}
Event Tracking
Track Events with Attribution
import { LinkFortySDK } from '@linkforty/mobile-sdk-react-native';
// Purchase event
LinkFortySDK.trackEvent('purchase', {
value: 49.99,
currency: 'USD',
productId: '123',
productName: 'Wireless Headphones',
category: 'Electronics',
quantity: 1
});
// Add to cart
LinkFortySDK.trackEvent('add_to_cart', {
value: 49.99,
currency: 'USD',
productId: '123',
source: 'product_page'
});
// User registration
LinkFortySDK.trackEvent('signup', {
method: 'email',
referralCode: 'FRIEND123'
});
// Custom event
LinkFortySDK.trackEvent('tutorial_completed', {
duration_seconds: 120,
steps_completed: 5
});
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
init()
Initialize the SDK. Call once on app launch.
LinkFortySDK.init(config: LinkFortyConfig): Promise<void>
Parameters:
{
baseUrl: string; // Your LinkForty instance URL
apiKey?: string; // API key for authentication
debug?: boolean; // Enable debug logs (default: false)
attributionWindow?: number; // Attribution window in days (default: 7)
}
Example:
await LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com',
apiKey: 'your-api-key',
debug: __DEV__
});
onDeferredDeepLink()
Register a callback for deferred deep links (new installs).
LinkFortySDK.onDeferredDeepLink(callback: (data: DeepLinkData) => void): void
Example:
LinkFortySDK.onDeferredDeepLink((data) => {
console.log('User installed from link:', data);
if (data.customParameters?.productId) {
navigation.navigate('Product', { id: data.customParameters.productId });
}
});
onDeepLink()
Register a callback for direct deep links (existing users).
LinkFortySDK.onDeepLink(callback: (data: DeepLinkData) => void): void
Example:
LinkFortySDK.onDeepLink((data) => {
console.log('Deep link received:', data);
if (data.customParameters?.productId) {
navigation.navigate('Product', { id: data.customParameters.productId });
}
});
trackEvent()
Track custom events with attribution.
LinkFortySDK.trackEvent(eventName: string, properties?: Record<string, any>): void
Parameters:
eventName- Name of the eventproperties- Optional object with event properties
Example:
LinkFortySDK.trackEvent('purchase', {
value: 29.99,
currency: 'USD',
productId: '123',
category: 'Electronics'
});
getInstallId()
Get the unique installation identifier.
LinkFortySDK.getInstallId(): Promise<string | null>
Example:
const installId = await LinkFortySDK.getInstallId();
console.log('Install ID:', installId);
getInstallData()
Retrieve cached attribution information.
LinkFortySDK.getInstallData(): Promise<DeepLinkData | null>
Example:
const installData = await LinkFortySDK.getInstallData();
if (installData) {
console.log('Attribution data:', installData);
}
clearData()
Clear all cached SDK data.
LinkFortySDK.clearData(): Promise<void>
Example:
// On user logout or data reset
await LinkFortySDK.clearData();
Complete Example
E-commerce App
import React, { useEffect, useState } from 'react';
import { View, Text, Button } from 'react-native';
import { LinkFortySDK, DeepLinkData } from '@linkforty/mobile-sdk-react-native';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function App() {
useEffect(() => {
initializeLinkForty();
}, []);
const initializeLinkForty = async () => {
// Initialize SDK
await LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com',
apiKey: 'your-api-key',
debug: __DEV__
});
// Handle deferred deep links (new installs)
LinkFortySDK.onDeferredDeepLink((data: DeepLinkData) => {
console.log('User installed from link:', data);
handleDeepLink(data);
});
// Handle direct deep links (existing users)
LinkFortySDK.onDeepLink((data: DeepLinkData) => {
console.log('Deep link received:', data);
handleDeepLink(data);
});
};
const handleDeepLink = (data: DeepLinkData) => {
if (data.customParameters?.productId) {
// Navigate after a short delay to ensure navigation is ready
setTimeout(() => {
navigation.navigate('Product', { id: data.customParameters.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('view_content', {
contentType: 'product',
contentId: id
});
}, [id]);
const handleAddToCart = () => {
// Track add to cart
LinkFortySDK.trackEvent('add_to_cart', {
value: product.price,
currency: 'USD',
productId: id,
productName: product.name
});
// Add to cart logic...
};
const handlePurchase = () => {
// Track purchase
LinkFortySDK.trackEvent('purchase', {
value: product.price,
currency: 'USD',
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 Callbacks Not Firing
Symptoms:
onDeferredDeepLinkoronDeepLinkcallbacks never fire- User definitely clicked a 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
init()is called before registering callbacks
- Verify
-
Wrong API key or base URL
- Check the configuration is correct
- Verify it's for the right environment
Solutions:
// Enable debug logging to troubleshoot
await LinkFortySDK.init({
baseUrl: 'https://your-linkforty-domain.com',
apiKey: 'your-api-key',
debug: true // Enable verbose logging
});
// Register callbacks after init
LinkFortySDK.onDeferredDeepLink((data) => {
console.log('Deferred deep link data:', JSON.stringify(data, null, 2));
});
Events Not Tracking
Symptoms:
trackEvent()called but events don't appear in analytics
Possible Causes:
- Network connectivity issues
- Invalid API key
- SDK not initialized
Solutions:
// Ensure SDK is initialized first
await LinkFortySDK.init({ ... });
// Then track events
LinkFortySDK.trackEvent('purchase', {
value: 29.99
});
console.log('Event tracked');
iOS Build Errors
Symptoms:
- Build fails after installing SDK
Solution:
cd ios
pod deintegrate
pod install
cd ..
Android Build Errors
Symptoms:
- Build fails with dependency conflicts
Solution:
Ensure your android/build.gradle has the correct minSdkVersion:
minSdkVersion = 21
TypeScript Types
The SDK exports these TypeScript types:
import {
LinkFortySDK,
DeepLinkData,
LinkFortyConfig
} from '@linkforty/mobile-sdk-react-native';
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