@slnka/react-native
v1.0.0-beta.4
Published
SLNKA SDK for React Native - Deep linking, attribution & analytics
Maintainers
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-nativeNo authentication or registry config needed — published on the public npm registry.
iOS
cd ios && pod installAndroid
No additional steps -- the module auto-links.
Expo
For Expo managed workflow:
npx expo install @slnka/react-nativeAdd 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:androidThe 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 withuseDeepLink()and checkdeepLink.isDeferredinstead. 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.comIn 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
