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

@slnka/react-native

v1.0.0-beta.4

Published

SLNKA SDK for React Native - Deep linking, attribution & analytics

Readme

@slnka/react-native

SLNKA SDK for React Native — deep linking, attribution, and analytics.

GDPR + CNDP compliant by default: no tracking without explicit user consent.

Installation

# npm
npm install @slnka/react-native

# yarn
yarn add @slnka/react-native

No authentication or registry config needed — published on the public npm registry.

iOS

cd ios && pod install

Android

No additional steps -- the module auto-links.

Expo

For Expo managed workflow:

npx expo install @slnka/react-native

Add the config plugin to app.json to automatically configure deep linking:

{
  "expo": {
    "plugins": [
      ["@slnka/react-native/expo-plugin", {
        "domains": ["slnk.ma"]
      }]
    ]
  }
}

Then create a development build:

npx expo prebuild
npx expo run:ios
npx expo run:android

The plugin automatically configures:

  • iOS: Associated Domains entitlement (applinks:slnk.ma)
  • Android: Intent filters with android:autoVerify="true" in AndroidManifest.xml

Multiple domains are supported:

{
  "expo": {
    "plugins": [
      ["@slnka/react-native/expo-plugin", {
        "domains": ["slnk.ma", "go.client.ma"]
      }]
    ]
  }
}

The SDK includes a JS-only fallback for Expo Go (deep linking and attribution require a development build with native modules).

Quick Start

1. Wrap your app with SlnkaProvider

import { SlnkaProvider } from '@slnka/react-native';

export default function App() {
  return (
    <SlnkaProvider
      apiKey="lsk_live_your_api_key"
      config={{
        serverUrl: 'https://your-instance.slnk.ma',  // Required
        enableDeepLinks: true,
        enableAttribution: true,
        cndpCompliant: true,
        debug: __DEV__,
      }}
    >
      <AppNavigator />
    </SlnkaProvider>
  );
}

2. Grant consent (CNDP mode)

When cndpCompliant: true (the default), no events are tracked until the user grants consent:

import { useSlnka } from '@slnka/react-native';

function ConsentBanner() {
  const { optIn, optOut } = useSlnka();

  return (
    <View>
      <Text>We use analytics to improve your experience.</Text>
      <Button title="Accept" onPress={optIn} />
      <Button title="Decline" onPress={optOut} />
    </View>
  );
}

3. Track events

import { useTrack } from '@slnka/react-native';

function ProductScreen({ productId }) {
  const { track, identify } = useTrack();

  useEffect(() => {
    track('product_viewed', { productId });
  }, [productId]);

  const handlePurchase = () => {
    track('purchase_completed', { productId, amount: 299.99 });
  };

  return <Button title="Buy Now" onPress={handlePurchase} />;
}

4. Handle deep links (direct + deferred)

useDeepLink() is a unified hook that handles all deep link scenarios: direct clicks (Universal Links / App Links), cold-start URLs, and deferred deep links (post-install fingerprint matching). Use deepLink.isDeferred to distinguish the source.

import { useDeepLink } from '@slnka/react-native';
import { useNavigation } from '@react-navigation/native';

function DeepLinkHandler() {
  const { deepLink, isLoading } = useDeepLink();
  const navigation = useNavigation();

  useEffect(() => {
    if (deepLink) {
      // Works for both direct clicks AND first-install deferred matches
      navigation.navigate(deepLink.screen, deepLink.params);

      if (deepLink.isDeferred) {
        console.log('User came from campaign before installing:', deepLink.utmCampaign);
      }
    }
  }, [deepLink]);

  return null;
}

Migration note: useDeferredDeepLink() is deprecated. Replace it with useDeepLink() and check deepLink.isDeferred instead. The old hook still works for backward compatibility.

6. Attribution

import { useAttribution } from '@slnka/react-native';

function AnalyticsDebug() {
  const { attribution, isLoading } = useAttribution();

  if (isLoading) return <Text>Loading attribution...</Text>;

  if (attribution) {
    return (
      <View>
        <Text>Source: {attribution.utmSource}</Text>
        <Text>Medium: {attribution.utmMedium}</Text>
        <Text>Campaign: {attribution.utmCampaign}</Text>
        <Text>Confidence: {(attribution.confidence * 100).toFixed(0)}%</Text>
        <Text>Method: {attribution.method}</Text>
      </View>
    );
  }

  return <Text>No attribution data</Text>;
}

API Reference

SlnkaProvider

| Prop | Type | Required | Description | |------|------|----------|-------------| | apiKey | string | Yes | SLNKA API key (lsk_live_* or lsk_test_*) | | config.serverUrl | string | Yes | API base URL (e.g., https://api.slnk.ma) | | config.enableDeepLinks | boolean | No | Enable deep link handling (default: true) | | config.enableAttribution | boolean | No | Enable attribution (default: true) | | config.cndpCompliant | boolean | No | Require consent before tracking (default: true) | | config.flushInterval | number | No | Flush interval in ms (default: 30000) | | config.flushSize | number | No | Max buffer size before auto-flush (default: 20) | | config.debug | boolean | No | Enable debug logging (default: false) |

Hooks

| Hook | Returns | Description | |------|---------|-------------| | useSlnka() | SlnkaContextType | Full SDK context (track, identify, deep links, attribution) | | useDeepLink() | { deepLink, isLoading, error } | Unified hook for all deep links (direct + deferred). Check deepLink.isDeferred to distinguish. | | ~~useDeferredDeepLink()~~ | { deferredLink, isLoading, error } | Deprecated. Use useDeepLink() instead. Kept for backward compatibility. | | useAttribution() | { attribution, isLoading, error } | Fetch attribution data | | useTrack() | { track, identify, reset } | Event tracking and identity methods |

Types

interface DeepLink {
  screen: string;
  params: Record<string, string>;
  utmSource?: string;
  utmMedium?: string;
  utmCampaign?: string;
  linkId?: string;
  confidence?: number;
  isDeferred?: boolean;
}

interface Attribution {
  linkId: string;
  confidence: number;
  method: 'server_fingerprint' | 'clipboard' | 'referrer';
  utmSource?: string;
  utmMedium?: string;
  utmCampaign?: string;
}

Native Setup (bare React Native only)

Expo users: Skip this section — the config plugin handles everything automatically.

iOS Setup: Universal Links

Add your SLNKA domain to Associated Domains in Xcode:

applinks:slnk.ma
applinks:yourdomain.com

In AppDelegate.mm, forward Universal Links:

- (BOOL)application:(UIApplication *)application
    continueUserActivity:(NSUserActivity *)userActivity
    restorationHandler:(void (^)(NSArray *))restorationHandler {
  return [RCTLinkingManager application:application
                   continueUserActivity:userActivity
                     restorationHandler:restorationHandler];
}

Android Setup: App Links

Add intent filters to AndroidManifest.xml:

<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" android:host="slnk.ma" />
</intent-filter>

License

MIT