Skip to content
Sendora Cloud
Create account
TypeScript • npm 0.17.0+ • Expo Go for auth+analytics, Dev Client for push

React Native SDK

First-party RN / Expo SDK. Analytics, identity, push, full auth surface, deep links (Branch parity). Zero-config install — CSPRNG polyfill auto-applied at SDK load.

What's included

  • Deep links: typed `linkData<T>` generic, `LinkError` w/ 12 codes, `prewarm` cache, `attachLinkingApi` (one-call replacement for Linking boilerplate), `computeDeviceFingerprint`, `revoke`, `getStats`.
  • Auth: anonymous, email+pass, magic, OTP, TOTP MFA, recovery codes, OIDC SSO + deep-link return, Sign in with Apple / Google / Microsoft / LinkedIn / Facebook / Discord.
  • Analytics: identify / track / screen + auto-tracked lifecycle (`app.opened` / `app.foregrounded` / `app.backgrounded` / `session.start`).
  • Push: registers APNs / FCM tokens via `expo-notifications` or `@react-native-firebase/messaging` — **requires Dev Client (Expo Go dropped remote push in SDK 53)**.
  • Hermes CSPRNG polyfill bundled + auto-applied — no manual `import "react-native-get-random-values"` in your entry file required (since 0.17.0).
  • Runs in Expo Go for auth + analytics + warm deep links. Move to a Dev Client (`npx expo prebuild` or EAS Build) for push registration and Play Install Referrer.

Install

npx expo install @sendoracloud/sdk-react-native @react-native-async-storage/async-storage

# That's it. The CSPRNG polyfill (react-native-get-random-values) is bundled
# as a hard dependency since 0.17.0 and auto-applied at SDK load — no manual
# import "react-native-get-random-values" required in your entry file.
Peers
  • @react-native-async-storage/async-storageRequired peer — persists anonymous id across app restarts.
  • expo-localizationOptional — improves device-fingerprint locale accuracy.
  • expo-cryptoOptional — hardens the SHA-256 used by `computeDeviceFingerprint()`. Falls back to web crypto or pure-JS if missing.
  • react-native-play-install-referrerOptional (Android) — enables 100%-accurate deferred deep-link matching.

Quickstart

import SendoraCloud, { LinkError } from "@sendoracloud/sdk-react-native";

await SendoraCloud.init({
  apiKey: "pk_prod_...",
  iosBundleId: "com.yourapp",
  androidPackageName: "com.yourapp",
});

SendoraCloud.identify("user_123", { email: "u@e.co" });
SendoraCloud.track("signup.completed", { plan: "growth" });

// Deep links — one-call wiring
useEffect(() => {
  const off = SendoraCloud.links.onLinkOpened((event) => {
    // navigate via event.linkData
  });
  let detach: (() => void) | undefined;
  void SendoraCloud.links
    .attachLinkingApi({ onLegacyUrl: (url) => myRouter.handle(url) })
    .then((d) => { detach = d; });
  void SendoraCloud.links.matchDeferred();
  return () => { detach?.(); off(); };
}, []);

Security posture

  • Public key only — SDK throws on `sk_*` at init.
  • HTTPS enforced outside `localhost` / `127.0.0.1`.
  • AsyncStorage persists anonymous id only — no PII written to disk.
  • Opaque userIds — `identify(userId)` persists to AsyncStorage in plaintext, so pass internal UUIDs, not emails.
  • Push token + metadata capped at 4 KB each.
  • Bundle-id gate — `links.create()` auto-forwards `iosBundleId` / `androidPackageName`; backend rejects leaked key + wrong bundle.

Related