SDK Integration
Integrate LinkForty's mobile SDK to enable deferred deep linking, attribution tracking, and in-app event analytics.
Overview
The LinkForty SDK enables your mobile app to:
- ✅ Deferred deep linking - Route new users to specific content after install
- ✅ Attribution tracking - Know which links drive installs
- ✅ Event tracking - Track in-app actions with attribution
- ✅ Fingerprint matching - 70%+ attribution accuracy without device IDs
- ✅ Cross-platform - iOS, Android, React Native, Flutter
Prerequisites
Before integrating the SDK:
- Create LinkForty account (Cloud or self-hosted)
- Get API key from Settings → API Keys
- Create at least one link to test with
- Have your app built and ready for SDK integration
Platform SDKs
Choose your platform:
React Native SDK
Best for: React Native apps
npm install @linkforty/react-native
Features:
- Cross-platform (iOS + Android)
- TypeScript support
- Auto-linking (RN 0.60+)
iOS SDK
Best for: Native iOS apps (Swift/Objective-C)
pod 'LinkFortySDK'
Features:
- Swift Package Manager support
- iOS 12+ compatible
- SwiftUI + UIKit examples
Android SDK
Best for: Native Android apps (Kotlin/Java)
implementation 'com.linkforty:sdk:2.0.0'
Features:
- Kotlin-first API
- Android 5.0+ (API 21+)
- Jetpack Compose examples
Flutter SDK
Best for: Flutter apps
dependencies:
linkforty_flutter: ^2.0.0
Features:
- Pure Dart API
- iOS + Android support
- Null safety
Quick Start (React Native)
1. Install SDK
npm install @linkforty/react-native
2. Initialize SDK
In your App.tsx:
import React, { useEffect } from 'react';
import { LinkFortySDK } from '@linkforty/react-native';
function App() {
useEffect(() => {
LinkFortySDK.initialize({
apiKey: 'your-api-key',
apiUrl: 'https://api.linkforty.com', // Optional for Cloud
enableLogging: __DEV__
});
}, []);
return (
// Your app
);
}
3. Check for Deep Link
import { useEffect } from 'react';
import { LinkFortySDK } from '@linkforty/react-native';
import { useNavigation } from '@react-navigation/native';
function App() {
const navigation = useNavigation();
useEffect(() => {
checkDeepLink();
}, []);
const checkDeepLink = async () => {
const deepLinkData = await LinkFortySDK.getDeepLinkData();
if (deepLinkData) {
// User installed from a link - route to specific content
if (deepLinkData.productId) {
navigation.navigate('Product', { id: deepLinkData.productId });
}
}
};
return (
// Your app
);
}
4. Track Events
import { LinkFortySDK } from '@linkforty/react-native';
// Track purchase
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 29.99,
currency: 'USD',
properties: {
productId: '123',
category: 'Electronics'
}
});
Core Concepts
Deferred Deep Linking
What it does: Routes new users to specific content after app install.
Flow:
- User clicks link (e.g., product page)
- User doesn't have app → Goes to App Store
- User installs and opens app
- SDK retrieves deep link data
- App navigates to original product page
Code:
const data = await LinkFortySDK.getDeepLinkData();
// { productId: "123", utm_source: "instagram" }
Attribution Tracking
What it does: Tracks which links drive app installs.
Flow:
- User clicks link → Fingerprint created
- User installs app
- SDK checks for matching fingerprint
- Install attributed to link (if within attribution window)
View in dashboard: Analytics → Links → Select link → View installs
Event Tracking
What it does: Tracks in-app actions with attribution.
Flow:
- User makes purchase in app
- SDK tracks event with attribution
- Event appears in analytics with original link/campaign
Code:
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 49.99,
properties: { productId: '456' }
});
View in dashboard: Analytics → Events
Integration Steps
Step 1: Get API Key
- Log into LinkForty dashboard
- Go to Settings → API Keys
- Click "Create API Key"
- Name it "Mobile App SDK"
- Copy the API key (starts with
lf_live_)
Step 2: Install SDK
See platform-specific guides:
Step 3: Initialize on App Launch
Call initialize() as early as possible:
React Native:
useEffect(() => {
LinkFortySDK.initialize({
apiKey: process.env.LINKFORTY_API_KEY
});
}, []);
iOS:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
LinkFortySDK.initialize(apiKey: "your-api-key")
return true
}
Android:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
LinkFortySDK.initialize(this, "your-api-key")
}
}
Step 4: Check for Deferred Deep Link
Call getDeepLinkData() on first app launch:
React Native:
const data = await LinkFortySDK.getDeepLinkData();
if (data) {
// Route to specific content
navigation.navigate('Product', { id: data.productId });
}
iOS:
LinkFortySDK.getDeepLinkData { result in
if case .success(let data) = result {
// Route to specific content
navigateToProduct(id: data["productId"])
}
}
Android:
LinkFortySDK.getDeepLinkData { data ->
data?.let {
// Route to specific content
navigateToProduct(it["productId"])
}
}
Step 5: Track Key Events
Track important actions:
// User registration
await LinkFortySDK.trackEvent({
eventName: 'signup',
properties: { method: 'email' }
});
// Purchase
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 29.99,
currency: 'USD',
properties: { productId: '123' }
});
// Custom events
await LinkFortySDK.trackEvent({
eventName: 'level_completed',
properties: { level: 5 }
});
Step 6: Test Integration
Create test link:
curl -X POST https://api.linkforty.com/api/links \
-H "Authorization: Bearer $LINKFORTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "template_123",
"originalUrl": "https://example.com/product/123?productId=123",
"iosUrl": "https://apps.apple.com/app/id123",
"androidUrl": "https://play.google.com/store/apps/details?id=com.app"
}'
Test flow:
- Uninstall app from test device
- Click test link on device
- Install app from App Store/Google Play
- Open app
- Check console logs for deep link data
- Verify navigation to product page
Expected result:
[LinkForty] Deep link data: {
productId: "123",
utm_source: undefined,
utm_campaign: undefined
}
Step 7: Deploy to Production
-
Remove debug logging:
LinkFortySDK.initialize({
apiKey: PRODUCTION_API_KEY,
enableLogging: false // Disable in production
}); -
Use environment-specific API keys:
- Development:
lf_test_...(when available) - Production:
lf_live_...
- Development:
-
Test on real devices (not simulators/emulators)
-
Monitor attribution in dashboard after launch
Best Practices
1. Initialize Early
Initialize SDK in app entry point, before any navigation:
✅ Good:
function App() {
useEffect(() => {
LinkFortySDK.initialize({ apiKey: API_KEY });
}, []);
}
❌ Bad:
function HomeScreen() {
useEffect(() => {
LinkFortySDK.initialize({ apiKey: API_KEY });
}, []);
}
2. Check Deep Link Once
Only check for deep link on first app launch, not every time:
const [hasCheckedDeepLink, setHasCheckedDeepLink] = useState(false);
useEffect(() => {
if (!hasCheckedDeepLink) {
checkDeepLink();
setHasCheckedDeepLink(true);
}
}, []);
3. Handle Navigation Carefully
Wait for navigation to be ready:
const checkDeepLink = async () => {
const data = await LinkFortySDK.getDeepLinkData();
if (data && navigationRef.isReady()) {
navigationRef.current?.navigate('Product', { id: data.productId });
}
};
4. Track Key Events Only
Don't track every single action. Focus on:
- User registration
- Purchases/conversions
- Key feature usage
- Level/milestone completions
❌ Don't track:
- Button clicks
- Screen views (unless key screens)
- Every user interaction
5. Use Environment Variables
Never hardcode API keys:
// .env
LINKFORTY_API_KEY=lf_live_a1b2c3d4e5f6g7h8
// App.tsx
LinkFortySDK.initialize({
apiKey: process.env.LINKFORTY_API_KEY
});
6. Set User Identifiers
Associate events with user IDs:
// After login
LinkFortySDK.setUserIdentifier(user.id);
// Events now associated with this user
await LinkFortySDK.trackEvent({ eventName: 'purchase' });
// After logout
LinkFortySDK.clearUserIdentifier();
7. Test on Real Devices
Fingerprint matching doesn't work reliably in simulators. Always test on physical devices.
Troubleshooting
Deep Link Data Returns Null
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
-
SDK not initialized before calling getDeepLinkData
- Ensure
initialize()completes before calling
- Ensure
-
Different network/device
- User clicked on WiFi, installed on cellular
- Fingerprint won't match (expected)
-
Testing in simulator
- Fingerprint matching unreliable in simulators
- Test on real device
Solution:
// Enable debug logging
LinkFortySDK.initialize({
apiKey: API_KEY,
enableLogging: true
});
// Check result
const data = await LinkFortySDK.getDeepLinkData();
console.log('Deep link result:', data);
Events Not Appearing in Dashboard
Symptoms:
trackEvent()succeeds but events don't show in analytics
Possible causes:
-
Network connectivity
- Events are queued and sent when online
-
Invalid API key
- Check API key is correct
-
Events delayed (batched)
- Events may take 1-2 minutes to appear
Solution:
try {
await LinkFortySDK.trackEvent({
eventName: 'test_event'
});
console.log('Event tracked successfully');
} catch (error) {
console.error('Error tracking event:', error);
}
Build Errors After Installation
iOS:
cd ios && pod install
Android:
cd android && ./gradlew clean
React Native:
npm install
npx react-native link @linkforty/react-native
Attribution Accuracy Lower Than Expected
Expected: 70-80% accuracy with fingerprint matching
If lower:
-
Check attribution window
- May be too short for your use case
- Increase to 7-14 days
-
Verify SDK integration
- Ensure
getDeepLinkData()called on first launch - Check logs for errors
- Ensure
-
Network conditions
- VPN/proxy usage reduces accuracy
- Cellular vs WiFi switching
-
Device factors
- iOS 14+ privacy features
- Different browsers (in-app vs Safari)
Security Best Practices
1. Protect API Keys
✅ Good:
- Store in environment variables
- Use different keys for dev/prod
- Rotate keys quarterly
❌ Bad:
- Hardcode in source code
- Commit to Git
- Share publicly
2. Validate Deep Link Data
Don't trust deep link data blindly:
const data = await LinkFortySDK.getDeepLinkData();
if (data && data.productId) {
// Validate product ID exists
const product = await api.getProduct(data.productId);
if (product) {
navigation.navigate('Product', { id: product.id });
} else {
// Invalid product ID - don't navigate
console.warn('Invalid product ID from deep link');
}
}
3. Rate Limit Event Tracking
Prevent abuse:
const eventQueue = [];
const MAX_EVENTS_PER_MINUTE = 60;
async function trackEventSafely(event) {
const now = Date.now();
const recentEvents = eventQueue.filter(t => now - t < 60000);
if (recentEvents.length >= MAX_EVENTS_PER_MINUTE) {
console.warn('Event rate limit exceeded');
return;
}
eventQueue.push(now);
await LinkFortySDK.trackEvent(event);
}
Advanced Features
Custom Event Properties
Track rich event data:
await LinkFortySDK.trackEvent({
eventName: 'purchase',
value: 149.99,
currency: 'USD',
properties: {
productId: '123',
productName: 'Wireless Headphones',
category: 'Electronics',
brand: 'TechCo',
quantity: 1,
couponCode: 'SUMMER20',
paymentMethod: 'credit_card',
shippingMethod: 'express'
}
});
Timed Events
Track event duration:
const startTime = Date.now();
// User completes tutorial
const duration = Date.now() - startTime;
await LinkFortySDK.trackEvent({
eventName: 'tutorial_completed',
properties: {
duration_seconds: Math.floor(duration / 1000),
steps_completed: 5
}
});
User Properties
Set user attributes:
// After user logs in or signs up
LinkFortySDK.setUserIdentifier(user.id);
// Track user properties
await LinkFortySDK.trackEvent({
eventName: 'user_properties',
properties: {
email: user.email,
subscription_tier: 'pro',
signup_date: user.createdAt,
country: user.country
}
});
Performance Optimization
1. Lazy Initialize
For faster app startup, initialize SDK after critical path:
useEffect(() => {
// Critical startup tasks first
loadUserData();
initializeAuth();
// Then initialize LinkForty
setTimeout(() => {
LinkFortySDK.initialize({ apiKey: API_KEY });
}, 100);
}, []);
2. Batch Events
SDK automatically batches events, but you can optimize further:
const events = [];
function queueEvent(event) {
events.push(event);
// Send batch every 10 events or 30 seconds
if (events.length >= 10) {
sendBatch();
}
}
async function sendBatch() {
const batch = events.splice(0, events.length);
await Promise.all(batch.map(e => LinkFortySDK.trackEvent(e)));
}
3. Cache Deep Link Data
Avoid calling getDeepLinkData() multiple times:
let cachedDeepLinkData = null;
async function getDeepLink() {
if (!cachedDeepLinkData) {
cachedDeepLinkData = await LinkFortySDK.getDeepLinkData();
}
return cachedDeepLinkData;
}
Next Steps
- 📱 React Native SDK - Complete React Native guide
- 🍎 iOS SDK - Native iOS integration
- 🤖 Android SDK - Native Android integration
- 🎯 Deferred Deep Linking - How it works
- 📊 Analytics - View attribution data
- 🔗 Creating Links - Create deep links
Support
- 📚 SDK Documentation
- 🐛 Report Issues
- 💬 Community Forum
- 📧 Email: support@linkforty.com