Deeplinking
Setup
iOS Setup
Update your app.json to include the associatedDomains for your MovableInk domain. Also update the infoPlist to include the key: movable_ink_universal_link_domains.
| Key | Description |
|---|---|
| scheme | If you don't already have a custom URI scheme for your app, add one here. This is required to support deeplinking - a scheme of myapp would allow links such as myapp://some/path to open your app. |
| movable_ink_universal_link_domains | The list of MovableInk domains that will open your app. This should match any MovableInk applinks in associatedDomains - Required for using Universal Links | App Links | Deeplinks |
{
"expo": {
"scheme": "myapp",
"ios": {
"associatedDomains": [
"applinks:mi.domain.com"
],
"infoPlist": {
"movable_ink_universal_link_domains": [
"mi.domain.com"
],
"movable_ink_api_key": "API KEY",
"movable_ink_region": "us" // or "eu"
}
}
}
}
Android Setup
Update your app.json to include the intentFilters for your MovableInk domain.
{
"expo": {
"android": {
"intentFilters": [
{
"action": "VIEW",
"autoVerify": true,
"data": [
{
"scheme": "https",
"host": "mi.domain.com",
"pathPrefix": "/p/cpm"
}
],
"category": ["BROWSABLE", "DEFAULT"]
},
{
"action": "VIEW",
"data": [
{
"scheme": "https",
"host": "mi.domain.com",
"pathPrefix": "/p/rpm"
}
],
"category": ["BROWSABLE", "DEFAULT"]
},
{
"action": "VIEW",
"data": [
{
"scheme": "https",
"host": "mi.domain.com",
"pathPrefix": "/p/gom"
}
],
"category": ["BROWSABLE", "DEFAULT"]
}
]
}
}
}
Make sure to update any instances of mi.domain.com to match your MovableInk domain.
Usage
We highly recommend using Expo Routers Native Intents.
Create a special file called +native-intent.tsx at the top level of your project's app directory.
This file exports a special redirectSystemPath method designed to handle URL/path processing. When invoked, it receives an options object with two attributes: path and initial.
import RNMovableInk from '@movable/react-native-sdk';
import * as Linking from 'expo-linking';
export async function redirectSystemPath({ path, initial }) {
try {
console.log('Received Path:', path);
let actualUrl = path;
if (initial) {
const initialUrl = await Linking.getInitialURL();
console.log('Initial URL from Linking:', initialUrl);
if (initialUrl) {
actualUrl = initialUrl;
}
}
// While the parameter is called `path` there is no guarantee that this is a path or a valid URL
const url = new URL(actualUrl, 'myapp://');
console.log('Received URL:', url.hostname);
// Detection of third-party URLs will change based on the provider
if (url.hostname === 'mi.domain.com') {
// If this is a MovableInk URL, we need to initialize the SDK here before we can resolve it
// If you already have `RNMovableInk.start()` in your app initialization code, that's ok as this is idempotent
// It's important to call this before attempting to resolve any URLs
RNMovableInk.start();
const clickthroughLink = await RNMovableInk.resolveURL(url.toString());
console.log('Resolved Clickthrough Link:', clickthroughLink);
// Switch over the clickthrough link to determine where to navigate
switch (clickthroughLink) {
case 'https://example.com/explore':
return '/(tabs)/explore';
case 'https://example.com/special-offer':
return '/(tabs)/special-offer';
default:
return '/(tabs)/index';
}
}
return path;
} catch {
// Do not crash inside this function! Instead you should redirect users
// to a custom route to handle unexpected errors.
// Here we're just sending them to the home page. You should handle this error more gracefully in a production app.
return '/(tabs)/index';
}
}
If you need to store the clickthrough link instead for later use, you can do so by storing it in a global state manager such as Redux, Context API, or any other state management solution you are using.
Expo Linking
If you'd rather use Expo Linking directly, you can read how to set that up here.
Deferred Deeplinking
When a user attempts to open a MovableInk Link that is designated as a deferred deeplink on an iOS device, and they don't already have your app installed, MovableInk will enable Deferred Deeplinking. Instead of being directed to your website experience, they will be shown a page to open the App Store to download your app.
Once downloaded, MovableInk can check the pasteboard for the original link and allow you to open that location inside your app instead.
Before you can use Deferred Deeplinking, you'll need to setup the sdk_install event schema.
You can read more about integrating Deferred Deeplinking here.
After you've setup Deferred Deeplinking, you'll need to enable the app install event before calling start:
// If using Deferred Deep Linking, make sure to enable the app install event before calling start
RNMovableInk.setAppInstallEventEnabled(true);
RNMovableInk.start();
// Call this anytime after you've called start when you're ready to check for a deferred deeplink
RNMovableInk.checkPasteboardOnInstall();
Warning
If this is ran on iOS 16+, this will prompt the user for permission to read from the pasteboard.