@ada-cx/messaging-react-native
v1.1.0
Published
Ada Messaging React Native SDK — embeds Ada Chat in a WebView with a secure native bridge
Readme
Ada Messaging React Native SDK
This package is for React Native teams embedding Ada inside an iOS and Android app through react-native-webview.
Requirements
react >= 18.0.0react-native >= 0.73.0react-native-webview >= 13.0.0
This package does not ship a separate Ada native module of its own. Complete the normal react-native-webview native installation steps for your app first, then add this package on top.
Your minimum iOS and Android OS versions follow the versions supported by your React Native app and react-native-webview. The Ada package does not add a separate deployment-target requirement beyond that.
Install
npm install @ada-cx/messaging-react-native react-native-webviewIf your app does not already include compatible react and react-native versions, upgrade those first.
Quick Start
import { useRef } from "react";
import {
AdaMessagingView,
type AdaMessagingViewHandle,
} from "@ada-cx/messaging-react-native";
export function SupportScreen() {
const adaRef = useRef<AdaMessagingViewHandle>(null);
return (
<AdaMessagingView
ref={adaRef}
handle="my-bot"
language="en"
metaFields={{ plan: "pro", signedIn: true }}
onReady={() => {
adaRef.current?.setSensitiveMetaFields({
authToken: "secure-session-token",
});
adaRef.current?.setDeviceToken("push-token");
}}
onEvent={(key, data) => {
console.log("[Ada]", key, data);
}}
style={{ flex: 1 }}
/>
);
}Most customer apps only need handle. Leave cluster unset unless Ada tells you your AI agent is hosted on a non-default production region.
Imperative handle methods:
reset(...)setLanguage(...)sendMessage(...)setMetaFields(...)setSensitiveMetaFields(...)setDeviceToken(...)deleteHistory()
Useful component props:
handleclusterlanguagegreetingmetaFieldsstylesidentityToken(see Secure Identity Tokens)appUrl(add your app's origin to the handle's Allowed Websites list in the Ada dashboard, under Channels > Chat)headless(see Headless Mode)loadTimeoutMsdomain(legacy runtime only)onReadyonEventonStateCacheonError
Upgrade From The Legacy React Native SDK
The safest migration is:
- replace the old npm package
- keep the runtime on legacy first
- use the
AdaEmbedViewalias only as a temporary bridge if that reduces churn - move to
AdaMessagingViewand the new prop patterns once the package upgrade is stable
Side-by-side mapping
| Legacy | Messaging SDK |
|---|---|
| @ada-support/react-native-sdk | @ada-cx/messaging-react-native |
| AdaEmbedView | AdaMessagingView |
| require_relative '../node_modules/@ada-support/react-native-sdk/react_native_pods' in Podfile | remove it |
| use_ada!() in Podfile | remove it |
The new package also exports a deprecated AdaEmbedView alias to make the first migration smaller if needed.
Before / after: package
# Before
npm install @ada-support/react-native-sdk
# After
npm install @ada-cx/messaging-react-nativeIf your old integration added Ada-specific Podfile helpers from @ada-support/react-native-sdk, remove them. The new package relies on the standard React Native and react-native-webview native setup only.
Before / after: imports
Smallest possible migration:
import { AdaEmbedView } from "@ada-cx/messaging-react-native";Recommended end state:
import { AdaMessagingView } from "@ada-cx/messaging-react-native";Important Code Changes To Make
1. Most customer apps should only set handle
For the normal production path, keep your setup simple:
<AdaMessagingView handle="my-bot" />If Ada tells you your bot is hosted on a non-default production region such as Maple, pass the exact cluster value they give you:
<AdaMessagingView
handle="my-bot"
cluster="maple"
/>2. Move sensitive metadata and device tokens to the ref in onReady
This is the preferred pattern in the new package:
onReady={() => {
adaRef.current?.setSensitiveMetaFields({ authToken: "secure-session-token" });
adaRef.current?.setDeviceToken(deviceToken);
}}3. Move event handling to onEvent
For new code, prefer one event callback surface:
onEvent={(key, data) => {
if (key === "ada:end_conversation") {
console.log("Conversation ended", data);
}
}}Legacy Prop Compatibility
Some older props still work for compatibility, but they are no longer the preferred integration pattern.
| Legacy prop / pattern | Status in the new package | Recommended approach |
|---|---|---|
| sensitiveMetaFields prop | supported but deprecated | call ref.setSensitiveMetaFields() in onReady |
| deviceToken prop | supported but deprecated | call ref.setDeviceToken() in onReady |
| eventCallbacks | supported but deprecated | use onEvent |
| endConversationCallback | supported but deprecated | use onEvent and check for ada:end_conversation |
| thirdPartyCookiesEnabled | still present but deprecated; Android only | normally omit it |
| styles | supported | pass a CSS string on the legacy runtime, or a record of Messaging style tokens on the Messaging runtime |
| zdChatterAuthCallback | supported | keep using it when you need Zendesk chat auth |
Upload And Media Permissions
If your bot flow lets users upload files or capture media, make sure your app includes the normal platform permissions required by react-native-webview and the device features you use.
For iOS, that usually means Info.plist usage descriptions such as:
NSCameraUsageDescriptionNSPhotoLibraryUsageDescriptionNSMicrophoneUsageDescription
For Android, add any permissions your app's upload or capture flow requires in AndroidManifest.xml. If you are migrating from much older legacy guidance, re-check those permissions against your current Android target SDK rather than copying them forward blindly.
State Restoration
If your app wants to restore chat immediately after process recreation, use:
onStateCacheto persist the latest non-sensitive state snapshotinitialStateto inject that snapshot the next time the view mounts
That removes the loading spinner on WebView restart flows.
The SDK filters the snapshot, your app stores it
Your app owns the storage, but the component now controls what may reach it. Before
onStateCache runs, the component reduces the snapshot to the canonical allowlist and stamps
__ada_cached_at__. This is the same filter the iOS and Android SDKs apply before they write
to device storage. The snapshot you receive carries branding and feature configuration only.
It carries no tokens and no conversation content.
Persist only these keys, and drop anything else the snapshot contains:
chatEnabled, tintColor, button, intro, fallbackUi, advancedColorsEnabled,
allowedProtocols, textOverAccentColor, proactiveConversations, features,
__ada_cached_at__
The PERSISTABLE_STATE_KEYS export carries the same list, and the exported
toPersistableStateSnapshot() helper applies it. Use the helper to sanitize snapshots that an
older package version persisted, because those snapshots can contain session tokens.
On the next mount, pass the stored snapshot back as initialState. The component filters it
again and discards it when __ada_cached_at__ is older than the 10-minute TTL. A snapshot
without a stamp still injects (deliberate back-compat for older persisted state), but it never
expires. Keep the stamp so stale state is discarded instead of hydrated.
Secure Identity Tokens
Use identityToken to start the session as a known user.
- Mint a token from your backend with
POST /v2/auth/tokens/. The token is short-lived and single-use. - Pass the token to the view before you mount it.
const token = await fetchAdaIdentityToken(); // your backend call
<AdaMessagingView handle="my-bot" webSdk="messaging" identityToken={token} />The token is injected into the WebView document before content loads. It never appears in a URL. The injection only runs on the Ada webview origin, so other pages never see the token. The runtime reads it once per document load and then deletes it. A token set after mount only applies when the WebView reloads. Fetch a fresh token before each mount.
Headless Mode
Set headless to run the Ada runtime without its chat UI. The WebView stays mounted, but it is hidden and non-interactive. Events and all imperative handle methods keep working. Use them to build a fully native experience.
const adaRef = useRef<AdaMessagingViewHandle>(null);
const [unread, setUnread] = useState(0);
<AdaMessagingView
ref={adaRef}
handle="my-bot"
webSdk="messaging"
headless
onEvent={(key) => {
if (key === "ada:message:received") {
setUnread((count) => count + 1); // drive your own red-dot badge
}
}}
/>
// Later, from your own composer UI:
adaRef.current?.sendMessage("Where is my order?");Notes:
- Keep the component mounted while you need the live session. Unmounting the component ends the session.
- Persist snapshots with
onStateCacheand pass them back asinitialStateto rehydrate on the next mount. See State Restoration. - Headless applies to the Messaging runtime only. The SDK never sends the flag on the legacy runtime, the same as iOS and Android.
Programmatic Control
Programmatic control is always on for React Native. There is no enableProgrammaticControl
prop. The component exposes sendMessage() and forwards the gated ada:message:sent /
ada:message:received events without any opt-in. On iOS and Android the same surface is off
by default, and the host must enable it explicitly.
Release Checklist
Before shipping a migration:
- verify chat renders on both iOS and Android
- confirm
onReadyfires - confirm your event logging still receives Ada SDK events
- if you use push notifications, call
setDeviceToken()and verify registration - test background / foreground and process restart behavior
