Skip to main content

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

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;
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

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 originalUrl becomes available in deep link data
  • Example: ?productId=123&category=electronics

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] });
}
};

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 NameDescriptionProperties
purchaseUser completes purchasevalue, currency, productId
add_to_cartItem added to cartproductId, value
begin_checkoutCheckout startedvalue, currency
signupUser registersmethod (email, social, etc.)
loginUser logs inmethod
view_contentContent viewedcontentType, contentId
searchUser searchesquery, results
shareContent sharedcontentType, method
level_completedGame level completedlevel, score
achievement_unlockedAchievement earnedachievement_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 null if 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

Symptoms:

  • getDeepLinkData() returns null
  • User definitely clicked link before installing

Possible Causes:

  1. Attribution window expired

    • Check link's attribution window setting
    • User may have installed too long after clicking
  2. Fingerprint mismatch

    • Different WiFi network for click vs install
    • VPN or proxy usage
    • iOS 14+ privacy features
  3. SDK not initialized

    • Verify initialize() is called before getDeepLinkData()
  4. 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:

  1. Network connectivity issues
  2. Invalid API key
  3. 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

Support