Skip to content

React Native

Overview

Getting started for apps that are built with React Native.

Installation

  1. We prefer you to use React Native version >=0.71.x as it has first class support for Typescript. If you're on an older version and run in to any issues, please reach out to your CX Team.

  2. Install the SDK

    $ npm install @movable/react-native-sdk
    
  3. The minimum iOS version supported is 13. Make sure to update your min_ios_version_supported in your Podfile if it's below 13; then install pods.

    $ cd ios
    $ pod install
    
  4. Import RNMovableInk in your project:

    import RNMovableInk from '@movable/react-native-sdk';
    

Android Setup

Android Deeplinking

You can follow the instructions on the Android Deeplinking article to learn more.

You can also read more on React Native's Deeplinking documentation page.

Android Behavior Events

If you want to use the Behavior Events features of the SDK, you'll need an API Key to enable Behavior Events for your app. If you don't already have one, please reach out to your CX Team at MovableInk with your applications bundle identifier (both Android and iOS).

Open local.properties file, found at android > local.properties

Within the application's local.properties, the provided API Key should be specified as follows:

MOVABLE_INK_SDK_API_KEY = "XXX"

Also, in the application manifest file the following meta-data tag should be specified within the application tag:

<meta-data
  android:name="com.movableink.inked.API_KEY"
  android:value="${MOVABLE_INK_SDK_API_KEY}"
/>

Lastly, in the Application level gradle file, under the defaultConfig section:

defaultConfig {
    ....
    manifestPlaceholders["MOVABLE_INK_SDK_API_KEY"] = localProperties['MOVABLE_INK_SDK_API_KEY']
    ....
}

After making changes to the gradle file, perform a gradle sync.

iOS Setup

Open Xcode and open your projects xcworkspace:

File > Open > project/ios/*/*.xcworkspace

In your Info.plist, add the movable_ink_universal_link_domains key as an array containing all the domains that you'd like the MovableInk SDK to handle. Note: These should only be domains that are shown in your Creative Tags, such as mi.example.com:

<key>movable_ink_universal_link_domains</key>
<array>
  <string>mi.example.com</string>
</array>

Info plist example

You can also edit the Info.plist in the Project Settings. Navigate to the Project Settings, then to the Info tab. Here, you can add the movable_ink_universal_link_domains key as an array:

Project Settings gif

Under the Signing & Capabilities tab, add the Associated Domains Capability, then add the applinks that you can support. These should include the same domains as the ones in the movable_ink_universal_link_domains in the step before. For example, if your MovableInk Domain is mi.example.com, you'd want to add applinks:mi.example.com.

Project Settings Capabilities gif

If you want to deeplink to your app via a custom scheme, such as myapp://products/1, you'll need to register this custom scheme in your info plist.

Custom Scheme Creation

iOS Deeplinking

You can read how to enable Deeplinking on iOS from React Native's Deeplinking documentation page; here's the gist:

Open the AppDelegate.mm file, import RCTLinkingManager from React, and implement the openURL and continueUserActivityMethods like below:

#import <React/RCTLinkingManager.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)app 
    openURL:(NSURL *)url 
    options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options  {
  return [RCTLinkingManager application:app openURL:url options:options];
}

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


@end

iOS Behavior Events

You'll need an API Key to enable Behavior Events for your app. If you don't already have one, please reach out to your CX Team at MovableInk with your applications bundle identifier.

Once you have an API Key, you can add a new key/value pair in your applications Info.plist

<key>movable_ink_api_key</key>
    <string>YOUR_API_KEY</string>

Deeplinking

You will be notified of an incoming deeplink that opens the app using Linking, then asking MovableInk to resolve it if it can.

import * as React from 'react';
import { StyleSheet, View, Text, Linking, Button } from 'react-native';
import RNMovableInk from '@movable/react-native-sdk';

export default function App() {
  const [link, setLink] = React.useState<string | undefined>();

  React.useEffect(() => {
    // Make sure to call RNMovableInk.start when your app start
    RNMovableInk.start();

    // Get the intial deeplink used to open the app if there was one.
    // This will be set if your app was not already launched.
    const getInitialURL = async () => {
      const universalLink = await Linking.getInitialURL();

      try {
        // If there was a link, ask RNMovableInk to resolve it.
        // If it's not a MovableInk Link, resolveURL will return null.
        // If MovableInk can handle the link, and resolution fails, it will reject.
        if (universalLink) {
          await resolveURL(universalLink);
        }
      } catch (error) {
        console.log(error);
      }
    };

    // Call the function!
    getInitialURL();

    // Setup a listener to receive updates while your app is launched
    const urlListener = Linking.addEventListener(
      'url',
      (event: { url: string }) => {
        (async () => {
          await resolveURL(event.url);
        })();
      }
    );

    return () => {
      urlListener.remove();
    };
  }, []);

  // A function to ask RNMovableInk to resolve an incoming deeplink
  const resolveURL = async (url: string) => {
    const clickthroughLink = await RNMovableInk.resolveURL(url);

    if (clickthroughLink) {
      setLink(clickthroughLink);
    }
  };

  return (...);
}

React.useEffect(() => {
  // Whenever the link changes, navigate to the correct page
  ...
}, [link]);

In the above example, link will be set to the resolved clickthrough link if it could be resolved. You can use this to navigate to the correct page when it changes.

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
RNMovableInk.setAppInstallEventEnabled(true);

// Make sure to call RNMovableInk.start when your app starts
RNMovableInk.start();

// Call this anytime after you've called start when youre 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.

Behavior Events

Setting MIU (mi_u)

An MIU is an identifier used by your companies marketing team and email/mobile messaging provider, that when shared with MovableInk, allows to uniquely identify each of your customers when the interact with campaigns or any other MovableInk content.

Most distribution partners provide a unique user identifier as an available merge tag that distinctly identifies every recipient on your list(s). Using this merge tag allows MovableInk to provide users with a consistent experience when opening the same email multiple times and across multiple devices. Providing an MIU is required for accurate behavior and conversion tracking.

You'll need to work with your distribution partners to identify a unique user identifier. It must meet the following criteria:

You should make the following call as soon as the user is identified (usually after logging in) to set the MIU. Double check with your marketing team that the MIU you're using matches the values they are using. It's imperative that they match for accurate behavior event tracking.

RNMovableInk.setMIU("YOUR_MIU");

If your app has support for guest/anonymous users, you can still track events without setting an MIU. Once a user does login, you should call RNMovableInk.setMIU() with the MIU of the user, then call RNMovableInk.identifyUser(). This will attempt to associate any events that user made as a guest to this user.

Inherited MIUs

If a user interacts with a MovableInk Link that contains an MIU and deeplinks into your app, the SDK will use that MIU value automatically for all subsequent behavior events if you don't manually set an MIU.

If you manually set an MIU, events will use that instead.

Suggested MIU naming convention

We strongly recommend you use a UUID for MIUs.

If you find your ids include names, email addresses, timestamps, or are easily incremental (1, 2, 3), we suggest using a new naming method that is more secure so that your MIUs are not as easy to guess or impersonate.

Recommended NOT Recommended
42772706-c225-43ad-837e-c01e94907c3c user@example.com
d68d3dbe-86e1-43ce-bf5f-2dafd2f6af45 123456789
6ec4f1dd-0998-4ca8-8793-7511c2625a45 john-smith-123

Product Searched

Key Type Description Max
query String, required The query the user used for a given search 256
url String A URL for the given query 512
RNMovableInk.productSearched({ query: 'Test Event' });

Product Viewed

Key Type Description Max
id String, required The ID of a product 256
title String The title of the product 512
price String The price of the product in Dollars and Cents
url String The URL of the product 512
categories Array<ProductCategory> An array of ProductCategory associated with the product. A ProductCategory must contain an id (String) and optionally a url (String) and/or title (String) 10 Items
meta Record<String, unknown> An open Record of any extra data you'd like to associate to this event 20 Items
RNMovableInk.productViewed({
  id: "1",
  title: "Hyperion",
  price: "15.99",
  url: "https://inkrediblebooks.com/hyperion-dan-simmons",
  categories: [
    {
      id: "Sci-Fi",
      url: "https://inkrediblebooks.com/categories/scifi"
    },
    {
      id: "Fiction",
      url: "https://inkrediblebooks.com/categories/fiction"
    }
  ],
  meta: { pages: 496 }
});

Product Added

Key Type Description Max
id String, required The ID of a product 256
title String The title of the product 512
price String The price of the product in Dollars and Cents
url String The URL of the product 512
categories Array<ProductCategory> An array of ProductCategory associated with the product. A ProductCategory must contain an id (String) and optionally a url (String) and/or title (String) 10 Items
meta Record<String, unknown> An open Record of any extra data you'd like to associate to this event 20 Items
void productAdded() {
RNMovableInk.productAdded({
  id: "1",
  title: "Hyperion",
  price: "15.99",
  url: "https://inkrediblebooks.com/hyperion-dan-simmons",
  categories: [
    {
      id: "Sci-Fi",
      url: "https://inkrediblebooks.com/categories/scifi"
    },
    {
      id: "Fiction",
      url: "https://inkrediblebooks.com/categories/fiction"
    }
  ],
  meta: { pages: 496 }
});
}

Product Removed

Key Type Description Max
id String, required The ID of a product 256
title String The title of the product 512
price String The price of the product in Dollars and Cents
url String The URL of the product 512
categories Array<ProductCategory> An array of ProductCategory associated with the product. A ProductCategory must contain an id (String) and optionally a url (String) and/or title (String) 10 Items
meta Record<String, unknown> An open Record of any extra data you'd like to associate to this event 20 Items
void productRemoved() {
RNMovableInk.productRemoved({
  id: "1",
  title: "Hyperion",
  price: "15.99",
  url: "https://inkrediblebooks.com/hyperion-dan-simmons",
  categories: [
    {
      id: "Sci-Fi",
      url: "https://inkrediblebooks.com/categories/scifi"
    },
    {
      id: "Fiction",
      url: "https://inkrediblebooks.com/categories/fiction"
    }
  ],
  meta: { pages: 496 }
});
}

Category Viewed

Key Type Description Max
id String, required The ID of a category 256
title String The title of the category 512
url String The URL of the category 512
RNMovableInk.categoryViewed({
  id: "scifi",
  title: "Sci-Fi",
  url: "https://inkrediblebooks.com/categories/scifi"
});

Order Completed

Key Type Description Max
id String The ID of a order 256
revenue String The total of the order in Dollars and Cents
products Array<OrderCompletedProduct> An array of the products in an order. OrderCompletedProduct must contain an id (String), and optionally a price (String), quantity (Number), title (String), and/or url (String). 100 Items
RNMovableInk.orderCompleted({
  id: "1",
  revenue: "15.99",
  products: [
    {
      id: "1",
      price: "15.99", 
      quantity: 1,
      title: "Hyperion",
      url: "https://inkrediblebooks.com/hyperion-dan-simmons"
    }
  ]
});

Custom Defined Events

In addition to the pre-defined events we provide, you can log custom events tailored to your business specific requirements. This flexibility enables you to monitor and understand user interactions beyond what our pre-defined events offer.

This type of event has a custom name name, such as video_started, and optional parameters as the payload.

The name and properties of a custom event must first be defined on your companies account. Please reach out to your CX Team at MovableInk to get started with this.

RNMovableInk.logEvent("video_started", {title: "Cat Bloopers"})

Identity

Identify User

If a user has used your app as a guest, then logs in, you can attempt to associate any events that user made as a guest using the identifyUser method.

RNMovableInk.identifyUser();

Testing Behavior Events

When you're ready to test an event, you need to set the MIU to a known value. You should let your CX Team know that you're ready to start testing events and give them the MIU that you are going to use before you do so. This will allow them to verify that the events are being sent correctly.

We usually use an empty UUID for testing, such as 00000000-0000-0000-0000-000000000000.

When you're ready to test an event, you should open the Console app on your Mac, select your device on the sidebar, then press the start button on the top bar. To filter the logs to just view MovableInk SDK logs, search for MI SDK.

When you send an event, you should see the event logged in the console. If the event was structured correctly, you should see a success message in the console along side the event name.

In App Message

The MovableInk SDK supports showing HTML based MI Content as In App Messages.

RNMovableInk.showInAppMessage("https://mi.example.com/p/rp/abcd12345.html", (buttonId) => {
  // User interacted with a link that has a buttonID
})

Note the link ends with .html. When exporting your links from Studio, make sure to add this suffix when using it as an In App Message in the SDK.

If you're already using an In App Message provider, such as Braze or Salesforce Marketing Cloud, you can still use MovableInk driven messages from those tools.

Go to the In App Message article to learn more.