Skip to content
Tolinku
Tolinku
Sign In Start Free
Engineering · · 5 min read

Cross-Platform SDK Integration for Deep Linking

By Tolinku Staff
|
Tolinku cross platform dashboard screenshot for engineering blog posts

Cross-platform frameworks add a layer between your app code and the native platform. Deep linking SDKs need to bridge this gap: the native OS delivers the URL, the SDK processes it, and the result reaches your JavaScript, Dart, or TypeScript code. This guide covers SDK integration patterns for the major cross-platform frameworks.

For framework-specific deep linking setup (without an SDK), see React Native Deep Linking and Flutter Deep Linking. For the SDK feature comparison, see Deferred Deep Linking SDKs: Feature Comparison.

Why Use an SDK

You can implement basic deep linking without any SDK. The OS delivers the URL, and your router handles it. An SDK adds value when you need:

  • Deferred deep linking: Matching a link click to an app install that happens later. This requires server-side fingerprinting that you can't build into a URL alone.
  • Attribution: Knowing which link, campaign, or channel led to an install or conversion.
  • Link creation: Generating short links programmatically from within the app.
  • Analytics: Click counts, conversion rates, and device breakdown for your links.

If you only need direct deep linking (app is installed, user taps link, app opens to the right screen), the platform's built-in linking APIs are sufficient. No SDK required.

React Native Integration

Installation

npm install @tolinku/react-native-sdk
# or
yarn add @tolinku/react-native-sdk

cd ios && pod install

Initialization

import { Tolinku } from '@tolinku/react-native-sdk';

// Initialize early in your app's entry point
Tolinku.init({
  apiKey: 'tolk_pub_your_publishable_key',
});
import { Tolinku } from '@tolinku/react-native-sdk';

useEffect(() => {
  // Check for deferred deep link on first launch
  Tolinku.checkDeferredLink().then((result) => {
    if (result) {
      navigation.navigate(result.screen, result.params);
    }
  });
}, []);
const link = await Tolinku.createLink({
  path: '/invite/' + userId,
  campaign: 'referral',
  ogTitle: 'Join me on the app',
  ogDescription: 'Use my referral link to get started',
});
// link.url = "https://go.yourapp.com/abc123"

Native Setup

The React Native SDK still requires the same native configuration as manual deep linking:

  • iOS: Associated Domains entitlement, AppDelegate continueUserActivity handler
  • Android: Intent filters with autoVerify, Digital Asset Links file

The SDK doesn't replace this configuration; it adds deferred linking and analytics on top of it.

See the React Native SDK docs for the full API reference.

Flutter Integration

Installation

# pubspec.yaml
dependencies:
  tolinku: ^1.0.0

Initialization

import 'package:tolinku/tolinku.dart';

void main() {
  Tolinku.init(apiKey: 'tolk_pub_your_publishable_key');
  runApp(MyApp());
}
import 'package:tolinku/tolinku.dart';

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    _checkDeferredLink();
  }

  Future<void> _checkDeferredLink() async {
    final result = await Tolinku.checkDeferredLink();
    if (result != null) {
      router.go(result.path);
    }
  }
}
final link = await Tolinku.createLink(
  path: '/invite/$userId',
  campaign: 'referral',
  ogTitle: 'Join me on the app',
  ogDescription: 'Use my referral link to get started',
);
// link.url = "https://go.yourapp.com/abc123"

Native Setup

Same as React Native: the Flutter SDK requires Associated Domains (iOS) and intent filters (Android) to be configured in the native project.

See the Flutter SDK docs for the full API reference.

Capacitor / Ionic Integration

Capacitor apps use the @capacitor/app plugin to receive deep links, similar to React Native's Linking module.

Configuration

// capacitor.config.ts
const config: CapacitorConfig = {
  appId: 'com.yourapp',
  plugins: {
    App: {
      // Deep linking configuration
    },
  },
};

iOS Setup

Add Associated Domains in Xcode (same as native iOS or React Native).

Android Setup

Add intent filters to AndroidManifest.xml (same as native Android).

import { App } from '@capacitor/app';

App.addListener('appUrlOpen', (event) => {
  const url = new URL(event.url);
  const path = url.pathname;
  const params = Object.fromEntries(url.searchParams);

  // Route to the correct page
  router.navigateByUrl(path);
});

Using Tolinku Web SDK in Capacitor

Since Capacitor runs a web view, you can use the Tolinku Web SDK for analytics and link creation:

import { Tolinku } from '@tolinku/web-sdk';

Tolinku.init({ apiKey: 'tolk_pub_your_publishable_key' });

// Create a link
const link = await Tolinku.createLink({
  path: '/invite/' + userId,
});

For deferred deep linking in Capacitor, combine the native deep link listener with a server-side check:

App.addListener('appUrlOpen', async (event) => {
  // Handle direct deep links
  handleDeepLink(event.url);
});

// On first launch, check for deferred link
const deferred = await fetch('https://api.tolinku.com/v1/deferred-link', {
  method: 'POST',
  headers: { 'x-api-key': 'tolk_pub_your_key' },
  body: JSON.stringify({ fingerprint: getDeviceFingerprint() }),
});

Integration Architecture

Where the SDK Fits

User taps link
    │
    ▼
OS receives URL → checks App Links / Universal Links
    │
    ▼
App launches (or comes to foreground)
    │
    ▼
Native layer receives URL
    │
    ▼
SDK processes URL:
  - Records click event
  - Extracts parameters
  - Checks for deferred link (first launch only)
    │
    ▼
Cross-platform bridge (React Native bridge / Flutter platform channel)
    │
    ▼
Your JavaScript/Dart code receives parsed result
    │
    ▼
Router navigates to the correct screen

What the SDK Handles

Capability Without SDK With SDK
Direct deep links Yes (built-in) Yes
URL parsing Manual Automatic
Deferred deep links No Yes
Link creation Manual API calls SDK method
Click analytics No Automatic
Attribution No Automatic
Fingerprinting No Built-in

Best Practices

Initialize Early

Initialize the SDK before your app's navigation is ready. The deferred deep link check should happen before the user sees the home screen, so they're routed directly to the intended content.

Don't Block the UI

The deferred deep link check makes a network request. Show a splash or loading screen while the check runs, but set a timeout (2-3 seconds) to ensure the app isn't stuck waiting.

// React Native example with timeout
const result = await Promise.race([
  Tolinku.checkDeferredLink(),
  new Promise(resolve => setTimeout(() => resolve(null), 3000)),
]);

Test on Physical Devices

SDK features like deferred deep linking rely on device fingerprinting (IP address, user agent, device model). These signals are different in simulators and emulators. Always test on physical devices.

Handle Both Direct and Deferred

Your routing code should handle links from both sources:

function handleLink(result) {
  if (result.path.startsWith('/product/')) {
    navigation.navigate('Product', { id: result.params.id });
  } else if (result.path.startsWith('/invite/')) {
    navigation.navigate('Invite', { code: result.params.code });
  }
}

// Direct deep links
Linking.addEventListener('url', ({ url }) => {
  handleLink(parseUrl(url));
});

// Deferred deep links
Tolinku.checkDeferredLink().then((result) => {
  if (result) handleLink(result);
});

The same routing function handles both cases. This keeps your code DRY and ensures consistent behavior.

For the SDK swap process, see SDK Swap Guide. For all SDK documentation, see Tolinku SDK docs. For deep linking features, see Tolinku deep linking.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.