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

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.

npm version License: MIT

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

Quick 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 getter

Deep Linking

LinkForty.onDeferredDeepLink(callback); // Deferred (install attribution)
LinkForty.onDeepLink(callback);         // Direct (multiple callbacks supported)
LinkForty.handleDeepLink(url);          // Manual URL pass-through

Event 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 getter

Link 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/abc123

Attribution Data

await LinkForty.getInstallId();    // Cached install UUID
await LinkForty.getInstallData();  // Cached DeepLinkData
await LinkForty.isFirstLaunch();   // First launch status

Data Management

await LinkForty.clearData();  // Wipe all stored SDK data
LinkForty.reset();             // Return to uninitialized state

Named 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