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

linktrail-react-native

v0.0.4

Published

React Native SDK for LinkTrail — mobile attribution and deferred deep linking. A New Architecture TurboModule wrapping the native LinkTrail iOS and Android SDKs.

Readme

LinkTrail React Native SDK

Mobile attribution and deferred deep linking for React Native. A New Architecture TurboModule that wraps the native LinkTrail iOS and Android SDKs — the entry point is LinkTrail.

  • Package: linktrail-react-native (npm) · React Native: 0.76+ (New Architecture) · iOS: 15.1+ · Android: minSdk 26

Install

npm install linktrail-react-native

The native SDKs resolve automatically — LinkTrailSDK from the CocoaPods trunk, io.linktrail:sdk from Maven Central — so there's nothing else to add.

  • iOS — cd ios && pod install.

  • Android — nothing extra; just make sure your app's minSdkVersion is 26 or higher.

  • Expo — needs a development build (not Expo Go). Set minSdkVersion via expo-build-properties, then npx expo prebuild:

    { "expo": { "plugins": [["expo-build-properties", { "android": { "minSdkVersion": 26 } }]] } }

Quick start

import LinkTrail from 'linktrail-react-native';

// At app launch. The API key is required.
await LinkTrail.configure('lt_live_…');

// One listener handles both first-launch (deferred) AND re-engagement links:
LinkTrail.onLink((link, source) => {
  router.navigate(link.path, link.customData); // e.g. "/products/aj1" + { voucher: "SUMMER25" }
});

// Observe failures:
LinkTrail.onError((error) => console.warn(`[LinkTrail] ${error.code}: ${error.message}`));

The install is tracked automatically by configure, and incoming links (Universal Links / App Links / custom schemes) are forwarded via React Native's Linking API — no extra wiring.

More

// Custom post-install events:
await LinkTrail.trackEvent('purchase', { value: 59.99, currency: 'USD' });

// Cached results:
const attribution = await LinkTrail.getLastAttribution();
const lastLink = await LinkTrail.getLastDeepLink();
 
// iOS ATT / SKAdNetwork (no-ops on Android):
await LinkTrail.requestTrackingAuthorization();
LinkTrail.registerForSKAdAttribution();
LinkTrail.updateConversionValue(42, 'medium');

configure also takes { logEnabled, logLevel, requestTimeoutMillis, retryPolicy, linkDomains, autoTrackInstall, requireConsent, clickTokenSource, autoHandleLinks }. Set autoHandleLinks: false to forward URLs yourself via LinkTrail.handleDeepLink(url).

Consent gating

requireConsent (default true) gates attribution/tracking behind the user's decision — deny-by-default for GDPR / ePrivacy. While consent is unset or denied the SDK holds the install and drops events, but deep links still route (onLink fires) so the user reaches their destination. The SDK exposes no consent getter — your app is the source of truth: persist the choice and replay it with setConsent on every launch after configure.

await LinkTrail.configure('lt_live_…', { requireConsent: true });

// After your consent UI resolves (persist the choice yourself, e.g. AsyncStorage):
LinkTrail.setConsent(true);   // releases the held install + flushes queued events
LinkTrail.setConsent(false);  // stops sending + drops the queue

// On the next launch, replay the stored decision right after configure:
LinkTrail.setConsent(storedGranted);

Set requireConsent: false to attribute at init without a consent step. See the example app's src/consent.ts for the persist-and-replay pattern.

Deferred attribution & the paste button (iOS)

On iOS, deferred attribution recovers a click token the tapped link left on the clipboard. clickTokenSource (in configure) picks how it's read:

  • 'automatic' — the SDK reads the clipboard itself at install. Needs no UI, but iOS shows the system "Allow Paste" alert on first launch.
  • 'pasteButton' (default) — the token is read only when the user taps <LinkTrailPasteButton/> (Apple's UIPasteControl), with no "Allow Paste" alert. You render the button and set autoTrackInstall: false so the install waits for the tap.
  • 'none' — the SDK never touches the clipboard (no button, no alert); deferred matching falls back to probabilistic IP matching only.

Android uses the Play Install Referrer instead, so clickTokenSource is ignored there and <LinkTrailPasteButton/> renders nothing.

import { LinkTrail, LinkTrailPasteButton } from 'linktrail-react-native';

await LinkTrail.configure('lt_live_…', {
  clickTokenSource: 'pasteButton',
  autoTrackInstall: false, // required: the install fires when the button is tapped
});

// On your first-launch screen:
<LinkTrailPasteButton
  style={{ height: 46, alignSelf: 'stretch' }} // size via standard RN style
  cornerStyle="fixed"
  fillColor="#111"
  foregroundColor="#FFFFFF"
  onTokenPasted={(token) => {
    // The SDK already fired the install with this token; onLink routes the
    // recovered destination. Use this only for UI side effects.
  }}
/>

<LinkTrailPasteButton/> props (all optional; plus any ViewProps such as style):

| Prop | Type | Default | Notes | | --- | --- | --- | --- | | onTokenPasted | (token: string) => void | — | Fires after the SDK reads the token. | | displayMode | 'iconAndLabel' \| 'iconOnly' \| 'labelOnly' | 'labelOnly' | What the control shows. | | cornerStyle | 'dynamic' \| 'fixed' \| 'capsule' \| 'large' \| 'medium' \| 'small' | 'capsule' | Corner rounding. | | foregroundColor | ColorValue | system | Label/icon color. | | fillColor | ColorValue | system | Button background. | | style | ViewStyle | — | Size/layout (width, height, margins…). |

Requires iOS 16+. The on-screen label is the system "Paste" string — Apple's UIPasteControl doesn't allow custom text, fonts, or borders; displayMode, cornerStyle, the two colors, and size are the full set of what's customizable. For manual control there's also LinkTrail.trackInstallWithClickToken(token) (iOS).

Deep-link setup

Standard app deep-link config — the wrapper handles the rest. Declare your LinkTrail host as a Universal Link (iOS Associated Domains: applinks:kick.linktrail.io) and an App Links intent-filter (Android), plus any custom scheme. LinkTrail infra hosts the apple-app-site-association / assetlinks.json files for your link domains.

List every link host in linkDomains. When linkDomains is non-empty, the SDK routes re-engagement opens (app already installed) only for those hosts — a link on an unlisted host opens the app but never navigates. Deferred (install-time) links skip this check and route regardless, so a missing host can look fine on a fresh install yet fail once the app is installed. Leave linkDomains empty (the default) to handle every parseable link.

Example app

example/ is KickFlip, a storefront that shows deferred deep linking end to end, consuming this package the same way your app would. A link button fires the four scenarios (home · category · product · product + voucher):

cd example && npm install && npm run ios   # or: npm run android

Set your lt_live_… key in src/attribution.ts; without one the simulator's links route locally. See example/README.md.

License

MIT. See LICENSE.