@linkforty/mobile-sdk-expo
v1.1.0
Published
Expo SDK for LinkForty - open-source alternative to Branch.io, AppsFlyer OneLink, and Firebase Dynamic Links. Deferred deep linking, attribution, and smart routing.
Maintainers
Readme
LinkForty Expo SDK
Expo SDK for LinkForty — the open-source alternative to Branch.io, AppsFlyer OneLink, and Firebase Dynamic Links. Add deferred deep linking, mobile attribution, and smart link routing to your Expo app. Self-hosted, privacy-first, no per-click pricing. Pure Expo modules — no native linking required.
Features
- Deferred deep linking (install attribution via device fingerprinting)
- Direct deep linking with server-side URL resolution
- Event tracking with offline queue (persists across app restarts)
- Revenue tracking
- Programmatic link creation
- Pure Expo modules - no native linking required (
expo-device,expo-application,expo-localization,expo-linking)
Installation
npx expo install @linkforty/mobile-sdk-expo expo-device expo-application expo-localization expo-linking @react-native-async-storage/async-storageQuick Start
import LinkForty from '@linkforty/mobile-sdk-expo';
// Initialize (call once at app startup)
const response = await LinkForty.initialize({
baseUrl: 'https://go.yourdomain.com',
apiKey: 'your-api-key', // Optional, required for link creation
debug: true, // Optional, enables verbose logging
attributionWindowHours: 168, // Optional, default 7 days
});
// Check attribution
if (response.attributed) {
console.log('Install attributed!', response.deepLinkData);
}
// Listen for deferred deep links (new installs)
LinkForty.onDeferredDeepLink((data) => {
if (data) {
console.log('Deferred deep link:', data.shortCode);
// Navigate to content
}
});
// Listen for direct deep links (existing users)
LinkForty.onDeepLink((url, data) => {
console.log('Deep link received:', url);
if (data?.customParameters?.route) {
// Navigate to route
}
});API Reference
Initialization
await LinkForty.initialize(config); // Returns InstallAttributionResponse
LinkForty.isInitialized; // boolean getterDeep Linking
LinkForty.onDeferredDeepLink(callback); // Deferred (install attribution)
LinkForty.onDeepLink(callback); // Direct (multiple callbacks supported)
LinkForty.handleDeepLink(url); // Manual URL pass-throughEvent Tracking
await LinkForty.trackEvent(name, properties?);
await LinkForty.trackRevenue(amount, currency, properties?);
await LinkForty.flushEvents(); // Flush offline queue
await LinkForty.clearEventQueue(); // Clear without sending
LinkForty.queuedEventCount; // Queue size getterLink Creation
Requires apiKey in config.
const result = await LinkForty.createLink({
deepLinkParameters: { route: 'PRODUCT', id: '123' },
title: 'Check out this product',
utmParameters: { source: 'app', medium: 'share' },
});
console.log(result.url); // https://go.yourdomain.com/tmpl/abc123Attribution Data
await LinkForty.getInstallId(); // Cached install UUID
await LinkForty.getInstallData(); // Cached DeepLinkData
await LinkForty.isFirstLaunch(); // First launch statusData Management
await LinkForty.clearData(); // Wipe all stored SDK data
LinkForty.reset(); // Return to uninitialized stateNamed Exports
import { LinkFortySDK, LinkFortyError, LinkFortyErrorCode } from '@linkforty/mobile-sdk-expo';
import type {
LinkFortyConfig,
DeepLinkData,
InstallAttributionResponse,
UTMParameters,
DeviceFingerprint,
CreateLinkOptions,
CreateLinkResult,
EventRequest,
DeferredDeepLinkCallback,
DeepLinkCallback,
} from '@linkforty/mobile-sdk-expo';Error Handling
All SDK errors are instances of LinkFortyError with a .code property:
| Code | When |
|-------------------------|----------------------------------------------------------------|
| NOT_INITIALIZED | Method called before initialize() |
| ALREADY_INITIALIZED | initialize() called twice |
| INVALID_CONFIGURATION | Bad config (HTTP on non-localhost, invalid attribution window) |
| NETWORK_ERROR | Network request failed after retries |
| INVALID_RESPONSE | Server returned non-2xx response |
| DECODING_ERROR | Failed to parse server response |
| INVALID_EVENT_DATA | Empty event name or negative revenue |
| MISSING_API_KEY | createLink() called without API key |
Offline Resilience
Events that fail to send are automatically queued in AsyncStorage (max 100 events, persists across app restarts). Successfully tracked events trigger a queue flush attempt. You can also manually flush or clear the queue.
Configuration
| Field | Type | Required | Default | Description |
|--------------------------|-----------|------------|-----------|-----------------------------------|
| baseUrl | string | Yes | - | LinkForty server URL |
| apiKey | string | No | - | API key for link creation |
| debug | boolean | No | false | Enable verbose logging |
| attributionWindowHours | number | No | 168 | Attribution window (1–2160 hours) |
Other SDKs
| Platform | Package |
|----------|---------|
| React Native | @linkforty/mobile-sdk-react-native |
| iOS (Swift) | LinkFortySDK |
| Android (Kotlin) | LinkFortySDK |
Contributing
Contributions are welcome! Please open an issue or pull request.
License
MIT License - see LICENSE for details.
Support
- Documentation: docs.linkforty.com
- Issues: GitHub Issues
- Core Engine: LinkForty Core — self-hosted open-source backend
- Cloud Platform: LinkForty Cloud — hosted SaaS with dashboard, teams, and billing
