Skip to main content

How to get started

Installation

Add dependency via npm or yarn package managers:

npm install @inappstory/react-native-sdk

Requirements

The React Native SDK supports both the New Architecture (Fabric, Turbo Modules, Codegen) and the Old Architecture (Bridge, Paper).

iOS

Install CocoaPods dependencies:

cd ios && pod install

Note on use_frameworks!: The SDK works out of the box with standard CocoaPods setups. If your project explicitly requires static frameworks (use_frameworks! :linkage => :static or USE_FRAMEWORKS=static), that is also supported.

Android

Step 1:

Make sure to update your Android SDK versions in android/app/build.gradle:

minSdkVersion = 24
compileSdkVersion = 35
targetSdkVersion = 35

If you use the New Architecture (default in React Native 0.76+), ensure newArchEnabled = true in your gradle.properties.

Step 2:

Update MainApplication class:

package com.example.yourapp

import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.inappstory.reactnativesdk.InAppStory

class MainApplication : Application(), ReactApplication {

override val reactHost: ReactHost by lazy {
getDefaultReactHost(
context = applicationContext,
packageList =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
},
)
}

override fun onCreate() {
super.onCreate()
InAppStory.initSDK(this)
loadReactNative(this)
}
}

Step 3:

Update MainActivity class:

package com.example.yourapp;

import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.inappstory.reactnativesdk.activity.InAppStoryActivity

class MainActivity : ReactActivity() {
class MainActivity : InAppStoryActivity() {

/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
override fun getMainComponentName(): String = "your_app"

/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
Why do I need this?

InAppStoryActivity extends ReactActivity and intercepts the Back button tap at the Android hardware/software level. This feature is only used when an In-App message (IAM) is shown. It first redirects the tap through the SDK, so pressing the Back button closes the In-App message within the app rather than navigating to another screen. If MainActivity continues to extend ReactActivity, the Back button bypasses the SDK, and the reader will not close correctly.

Basic Initialization

Initialize the SDK by creating StoryManager and configuring AppearanceManager:

import { StoryManager, AppearanceManager } from '@inappstory/react-native-sdk';

export const storyManager = await StoryManager.create({
apiKey: '<your-api-key>',
userId: '<user-id>',
});

export const appearanceManager = new AppearanceManager();
Complete setup example (StoryService.ts)
import {
StoryManager,
AppearanceManager,
type StoryManagerConfig,
StoriesListCardTitlePosition,
StoriesListCardViewVariant,
StoriesListCardTitleTextAlign,
StoryReaderCloseButtonPosition,
StoryReaderSwipeStyle,
} from '@inappstory/react-native-sdk';
import { Linking, Platform } from 'react-native';

const config: StoryManagerConfig = {
apiKey: '<your-api-key>',
userId: '<user-id>',
tags: ['tag1', 'tag2'],
placeholders: { username: 'Guest' },
lang: 'en-US',
defaultMuted: true,
};

export const storyManager = await StoryManager.create(config);

// Handle CTA clicks (buttons / deeplinks)
storyManager.storyLinkClickHandler = (payload) => {
if (payload.data.url) {
Linking.openURL(payload.data.url);
}
};

export const appearanceManager = new AppearanceManager()
.setCommonOptions({
hasLike: true,
hasLikeButton: true,
hasDislikeButton: false,
hasFavorite: true,
hasShare: true,
})
.setStoriesListOptions({
card: {
title: {
fontSize: 12,
fontWeight: 600,
fontFamily: Platform.OS === 'ios' ? 'System' : 'Roboto',
lineHeight: 14,
lineClamp: 2,
textAlign: StoriesListCardTitleTextAlign.LEFT,
position: StoriesListCardTitlePosition.CARD_INSIDE_BOTTOM,
},
height: 150,
variant: StoriesListCardViewVariant.RECTANGLE,
},
sidePadding: 16,
})
.setStoryReaderOptions({
closeButtonPosition: StoryReaderCloseButtonPosition.RIGHT,
scrollStyle: StoryReaderSwipeStyle.FLAT,
slideBorderRadius: 8,
});

Optional Settings

AppVersion override

Override app version and build for targeting (useful for CodePush):

const storyManager = await StoryManager.create({
apiKey: '<your-api-key>',
appVersion: {
version: '3.0.0',
build: 123,
},
});

Cache size and anonymous mode

const storyManager = await StoryManager.create({
apiKey: '<your-api-key>',
// Native story cache size. Android-only (iOS manages its own cache)
cacheSize: 'medium', // 'small' | 'medium' | 'large'
// Anonymous mode: no userId is sent to the backend
anonymous: true,
});

Next steps