npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@linkforty/mobile-sdk-react-native

v1.3.0

Published

React Native SDK for LinkForty - open-source alternative to Branch.io, AppsFlyer OneLink, and Firebase Dynamic Links. Deferred deep linking, attribution, and smart routing.

Readme

LinkForty React Native SDK

React Native 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 React Native app. Self-hosted, privacy-first, no per-click pricing.

npm version License: MIT

Features

  • Direct Deep Linking - Handle Universal Links (iOS) and App Links (Android) with automatic server-side resolution
  • Deferred Deep Linking - Route new users to specific content after install
  • Link Creation - Create short links programmatically from your app
  • Probabilistic Attribution - Match installs to clicks via device fingerprinting
  • Event Tracking - Track in-app events with attribution
  • Privacy-Focused - No persistent device IDs required
  • TypeScript Support - Full type definitions included
  • Works with Core & Cloud - Compatible with self-hosted and Cloud instances

Installation

npm install @linkforty/mobile-sdk-react-native

Requirements

  • React Native >= 0.64.0
  • React >= 17.0.0
  • Node.js >= 20.0.0

Peer Dependencies

npm install @react-native-async-storage/async-storage react-native-device-info

iOS Setup

  1. Install CocoaPods dependencies:
cd ios && pod install
  1. Configure Universal Links in Xcode:

    • Open your project in Xcode
    • Select your app target > Signing & Capabilities
    • Add "Associated Domains" capability
    • Add domain: applinks:go.yourdomain.com (replace with your LinkForty domain)
  2. Host an Apple App Site Association (AASA) file at:

    https://go.yourdomain.com/.well-known/apple-app-site-association
    {
      "applinks": {
        "apps": [],
        "details": [
          {
            "appID": "TEAM_ID.com.yourapp.bundle",
            "paths": ["*"]
          }
        ]
      }
    }

Android Setup

  1. Add an App Links intent filter in android/app/src/main/AndroidManifest.xml:
<activity android:name=".MainActivity">
  <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" />
    <data android:host="go.yourdomain.com" />
  </intent-filter>
</activity>
  1. Host a Digital Asset Links file at:

    https://go.yourdomain.com/.well-known/assetlinks.json
    [{
      "relation": ["delegate_permission/common.handle_all_urls"],
      "target": {
        "namespace": "android_app",
        "package_name": "com.yourapp",
        "sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"]
      }
    }]
  2. Ensure MainActivity preserves the Intent for React Native. In MainActivity.kt:

override fun onNewIntent(intent: Intent) {
    setIntent(intent) // Required for React Native's Linking.getInitialURL()
    super.onNewIntent(intent)
}

Note: If you use other SDKs that consume Intent data (e.g., CleverTap), make sure they receive a copy of the URI in onCreate rather than consuming the original Intent, otherwise Linking.getInitialURL() may return null.

Quick Start

import LinkForty from '@linkforty/mobile-sdk-react-native';

// 1. Initialize the SDK (call once at app startup)
await LinkForty.init({
  baseUrl: 'https://go.yourdomain.com',
  apiKey: 'your-api-key', // Required for createLink(), optional otherwise
  debug: __DEV__,
});

// 2. Handle direct deep links (user taps a link while app is installed)
LinkForty.onDeepLink((url, data) => {
  if (data?.customParameters) {
    const { route, id } = data.customParameters;
    // Navigate to the target screen
    navigation.navigate(route, { id });
  }
});

// 3. Handle deferred deep links (user installs app after tapping a link)
LinkForty.onDeferredDeepLink((data) => {
  if (data?.customParameters) {
    const { route, id } = data.customParameters;
    navigation.navigate(route, { id });
  } else {
    console.log('Organic install — no link clicked');
  }
});

API Reference

init(config)

Initialize the SDK. Must be called before any other method.

await LinkForty.init({
  baseUrl: 'https://go.yourdomain.com', // Required
  apiKey: 'your-api-key',               // Optional (required for createLink)
  debug: true,                           // Optional (default: false)
  attributionWindow: 7,                  // Optional, in days (default: 7)
});

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | baseUrl | string | Yes | Base URL of your LinkForty instance | | apiKey | string | No | API key for authenticated endpoints (Cloud) | | debug | boolean | No | Enable debug logging | | attributionWindow | number | No | Attribution window in days (default: 7) |


onDeepLink(callback)

Listen for direct deep links. Called when the app is opened via a Universal Link (iOS) or App Link (Android).

When the URL matches your LinkForty baseUrl, the SDK automatically resolves it via the server to retrieve the full link data including customParameters, UTM parameters, and metadata. If resolution fails, the SDK falls back to local URL parsing.

LinkForty.onDeepLink((url: string, data: DeepLinkData | null) => {
  console.log('Link URL:', url);

  if (data?.customParameters) {
    const { route, id } = data.customParameters;
    navigation.navigate(route, { id });
  }
});

| Callback Parameter | Type | Description | |--------------------|------|-------------| | url | string | The full URL that opened the app | | data | DeepLinkData \| null | Parsed link data, or null if parsing failed |


onDeferredDeepLink(callback)

Listen for deferred deep links. Called on first launch after install if the user clicked a LinkForty link before installing.

LinkForty.onDeferredDeepLink((data: DeepLinkData | null) => {
  if (data) {
    // Attributed install — user clicked a link before installing
    console.log('Came from:', data.utmParameters?.source);
    const { route, id } = data.customParameters || {};
    if (route) navigation.navigate(route, { id });
  } else {
    // Organic install or attribution failed
    console.log('Organic install');
  }
});

| Callback Parameter | Type | Description | |--------------------|------|-------------| | data | DeepLinkData \| null | Attributed link data, or null for organic installs |


createLink(options)

Create a short link programmatically. Requires apiKey to be set in init().

When templateId is omitted, the server auto-selects your organization's default template.

const result = await LinkForty.createLink({
  deepLinkParameters: { route: 'VIDEO_VIEWER', id: 'e4338ed6-...' },
  title: 'Check out this video',
  utmParameters: { source: 'share', medium: 'app' },
});

console.log(result.url);       // https://go.yourdomain.com/tmpl/abc123
console.log(result.shortCode); // abc123
console.log(result.linkId);    // uuid

Options:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | deepLinkParameters | Record<string, string> | No | Custom parameters embedded in the link (e.g., { route, id }) | | title | string | No | Link title for internal reference | | description | string | No | Link description | | customCode | string | No | Custom short code (auto-generated if omitted) | | utmParameters | object | No | UTM parameters (source, medium, campaign, term, content) | | templateId | string | No | Template UUID (auto-selected if omitted) | | templateSlug | string | No | Template slug (only needed with templateId) |

Returns: CreateLinkResult

| Field | Type | Description | |-------|------|-------------| | url | string | Full shareable URL | | shortCode | string | The generated short code | | linkId | string | Link UUID |


trackEvent(name, properties?)

Track an in-app event for attribution analytics. Requires a successful install report (automatic on first launch).

await LinkForty.trackEvent('purchase', {
  amount: 99.99,
  currency: 'USD',
  productId: 'premium_plan',
});

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | name | string | Yes | Event name (e.g., 'purchase', 'signup') | | properties | Record<string, any> | No | Arbitrary event properties |


getInstallData()

Retrieve cached install attribution data from a previous deferred deep link.

const data = await LinkForty.getInstallData();
if (data) {
  console.log('Install attributed to:', data.utmParameters?.source);
}

Returns: DeepLinkData | null


getInstallId()

Get the unique install ID assigned by the LinkForty server on first launch.

const installId = await LinkForty.getInstallId();

Returns: string | null


clearData()

Clear all cached SDK data (install ID, attribution data, first-launch flag). The next app launch will behave as a fresh install.

await LinkForty.clearData();

Types

DeepLinkData

interface DeepLinkData {
  shortCode: string;
  customParameters?: Record<string, string>;
  utmParameters?: {
    source?: string;
    medium?: string;
    campaign?: string;
    term?: string;
    content?: string;
  };
  iosUrl?: string;
  androidUrl?: string;
  webUrl?: string;
  deepLinkPath?: string;
  appScheme?: string;
  clickedAt?: string;
  linkId?: string;
}

LinkFortyConfig

interface LinkFortyConfig {
  baseUrl: string;
  apiKey?: string;
  debug?: boolean;
  attributionWindow?: number;
}

CreateLinkOptions

interface CreateLinkOptions {
  templateId?: string;
  templateSlug?: string;
  deepLinkParameters?: Record<string, string>;
  title?: string;
  description?: string;
  customCode?: string;
  utmParameters?: {
    source?: string;
    medium?: string;
    campaign?: string;
    term?: string;
    content?: string;
  };
}

CreateLinkResult

interface CreateLinkResult {
  url: string;
  shortCode: string;
  linkId: string;
}

How Deep Linking Works

Direct Deep Links (App Installed)

When a user taps a LinkForty URL and the app is already installed:

  1. The OS intercepts the URL via App Links (Android) or Universal Links (iOS) and opens your app directly
  2. The SDK receives the URL via React Native's Linking API
  3. The SDK calls your LinkForty server's resolve endpoint to retrieve the full link data (customParameters, UTM params, etc.)
  4. Your onDeepLink callback fires with the resolved data
  5. Your app navigates to the target screen

Deferred Deep Links (App Not Installed)

When a user taps a LinkForty URL and the app is not installed:

  1. The LinkForty server records a click with the user's device fingerprint
  2. The user is redirected to the App Store / Play Store
  3. After installing and opening the app, the SDK reports the install with the device's fingerprint
  4. The server matches the fingerprint to the original click (probabilistic attribution)
  5. Your onDeferredDeepLink callback fires with the matched link data
  6. Your app navigates to the content the user originally clicked on

Troubleshooting

Deep links not working on iOS

  1. Verify AASA file is accessible at https://yourdomain.com/.well-known/apple-app-site-association
  2. Check that Team ID and Bundle ID are correct in the AASA file
  3. Confirm "Associated Domains" capability is added in Xcode with applinks:yourdomain.com
  4. Test on a real device (Universal Links don't work in the simulator)

Deep links not working on Android

  1. Verify assetlinks.json is accessible at https://yourdomain.com/.well-known/assetlinks.json
  2. Check package name and SHA256 fingerprint are correct
  3. Run adb shell pm get-app-links com.yourapp to check link verification status
  4. Confirm android:autoVerify="true" is set in your intent filter
  5. Ensure MainActivity calls setIntent(intent) in onNewIntent (see Android Setup)

getInitialURL() returns null on Android

This usually means another SDK or library is consuming the Intent data before React Native reads it. In MainActivity.kt:

  • Call setIntent(intent) in onNewIntent so React Native sees the updated Intent on warm starts
  • If using CleverTap or similar SDKs, pass a copy of the URI to them in onCreate rather than the original Intent data

Deferred deep links not attributing

  1. Confirm this is a first install (or call clearData() first)
  2. Enable debug: true and check logs for fingerprint data
  3. Verify your LinkForty server received the install event
  4. Ensure the click and install happen within the attribution window (default: 7 days)
  5. Test on the same network for best fingerprint match accuracy

TypeScript errors

Ensure peer dependencies are installed:

npm install --save-dev @types/react @types/react-native

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE for details.

Other SDKs

| Platform | Package | |----------|---------| | Expo | @linkforty/mobile-sdk-expo | | iOS (Swift) | LinkFortySDK | | Android (Kotlin) | LinkFortySDK |

Support