Skip to content

crisp-im/crisp-sdk-react-native

Repository files navigation

crisp-banner

crisp-sdk-react-native

The official Crisp SDK for React Native — Add live chat to your Expo & React Native apps

npm version license Expo SDK 53+ platforms

See Crisp Support Chat SDKs  •  React Native Support Chat SDK  •  Developer Docs


Trusted by

Fruitz Fruitz  ·  and many more companies rely on Crisp to power their in-app customer support.


Warning

Expo SDK 53+ Required

This SDK is exclusively compatible with Expo SDK version 53 and newer. For projects using older Expo versions, please use the legacy React Native SDK. If you're migrating from the legacy SDK, see the Migration Guide.

Warning

Expo Go is Not Supported

The Crisp SDK uses native modules that are not available in Expo Go. You must use a development build:

npx expo run:ios
# or
npx expo run:android

Installation

For Expo Apps

Install the SDK using your preferred package manager:

# Using bun
bunx expo install crisp-sdk-react-native

# Using pnpm
pnpm dlx expo install crisp-sdk-react-native

# Using npm
npx expo install crisp-sdk-react-native

# Using yarn
yarn dlx expo install crisp-sdk-react-native

Version Targeting

The Crisp SDK requires minimum OS versions to function properly. Install expo-build-properties and configure your app.json:

npx expo install expo-build-properties
{
  "expo": {
    "plugins": [
      [
        "expo-build-properties",
        {
          "ios": {
            "deploymentTarget": "15.1"
          },
          "android": {
            "minSdkVersion": 21
          }
        }
      ]
    ]
  }
}

Note

This ensures your project targets iOS 15.1+ and Android SDK 21+, which are required by the native Crisp SDKs.

For Bare React Native Apps

This guide is for React Native developers who want to integrate Crisp using the Expo SDK in a project that doesn't use Expo as its development framework.

Prerequisites

Before starting, ensure you have:

  • React Native 0.79+
  • iOS deployment target 15.1+
  • Android minSdkVersion 21+
  • Node.js 18+

Step 1: Install Expo Modules

Run the following command in your project root:

npx install-expo-modules@latest

This command automatically configures your iOS and Android projects to support Expo modules.

Note

For comprehensive installation details or manual installation steps, refer to Expo's official guide.

Step 2: Install Crisp SDK

# Using npm
npm install crisp-sdk-react-native

# Using yarn
yarn add crisp-sdk-react-native

# Using pnpm
pnpm add crisp-sdk-react-native

# Using bun
bun add crisp-sdk-react-native

Step 3: Platform Configuration

iOS:

cd ios && pod install

Android:

Ensure your android/app/build.gradle has:

android {
    compileSdkVersion 34

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 34
    }
}

Configuration

Get Your Website ID

To use the Crisp SDK, you need your Website ID from the Crisp Dashboard.

  1. Sign up for a free account on Crisp (or log in)
  2. Go to Settings > Website Settings > Setup instructions
  3. Copy your Website ID

Setup and Integrations

Initialize Crisp

Configure the SDK at app startup with your Website ID:

import { useEffect } from "react";
import { configure } from "crisp-sdk-react-native";

export default function App() {
  useEffect(() => {
    configure("YOUR_WEBSITE_ID");
  }, []);

  return (
    // Your app content
  );
}

Push Notifications (Config Plugin)

To enable push notifications, add the config plugin to your app.json or app.config.js:

{
  "expo": {
    "plugins": [
      [
        "crisp-sdk-react-native",
        {
          "websiteId": "YOUR_WEBSITE_ID",
          "notifications": {
            "enabled": true,
            "mode": "sdk-managed"
          }
        }
      ]
    ]
  }
}

Plugin Options

Option Type Default Description
websiteId string - Your Crisp Website ID. Required when notifications are enabled.
notifications.enabled boolean false Enable push notifications for Crisp Chat.
notifications.mode "sdk-managed" | "coexistence" "sdk-managed" Notification handling mode. See Coexistence Mode below.

Important

The websiteId is required when notifications.enabled is true. The plugin will throw an error if it's missing.

What the Plugin Configures

iOS:

  • Adds remote-notification to UIBackgroundModes
  • Adds aps-environment entitlement for APNs
  • Registers for remote notifications on app launch
  • Forwards device token to Crisp SDK

Android:

  • Adds CrispNotificationService to AndroidManifest
  • Adds firebase-messaging dependency
  • Configures Crisp SDK with websiteId

Note

After enabling notifications, rebuild your app with npx expo prebuild --clean followed by npx expo run:ios or npx expo run:android.

Crisp Dashboard Configuration

Push notifications require additional setup in your Crisp Dashboard (APNs for iOS, Firebase for Android).

See the Push Notifications Setup Guide for detailed step-by-step instructions.

Coexistence Mode

By default, Crisp handles all push notification routing exclusively ("sdk-managed" mode). If your app uses another notification system (like expo-notifications, @react-native-firebase/messaging, or OneSignal), use "coexistence" mode to let both systems work together:

{
  "expo": {
    "plugins": [
      [
        "crisp-sdk-react-native",
        {
          "websiteId": "YOUR_WEBSITE_ID",
          "notifications": {
            "enabled": true,
            "mode": "coexistence"
          }
        }
      ]
    ]
  }
}

In coexistence mode, the plugin:

  • Android: Generates a chained FirebaseMessagingService that routes Crisp notifications to the Crisp SDK and delegates all others to expo-notifications (or Firebase directly)
  • iOS: Implements a UNUserNotificationCenterDelegate that filters Crisp notifications and forwards the rest to the previous delegate (chain of responsibility)

JS API for coexistence mode:

import {
  registerPushToken,
  isCrispPushNotification,
  setShouldPromptForNotificationPermission,
} from "crisp-sdk-react-native";

// Register a push token obtained from your notification system
registerPushToken(expoPushToken);

// Check if a notification payload is from Crisp
const isCrisp = isCrispPushNotification(notificationData);

// Control whether Crisp auto-prompts for notification permissions (iOS only)
setShouldPromptForNotificationPermission(false);

Listen for Crisp notifications in the foreground (iOS only):

import { useCrispEvents } from "crisp-sdk-react-native";

useCrispEvents({
  onPushNotificationReceived: ({ title, body }) => {
    console.log("Crisp notification:", title, body);
    // Update badge count, show toast, log analytics, etc.
  },
});

Note

onPushNotificationReceived is currently iOS only. On Android, the Crisp SDK does not expose a foreground notification callback — notifications are handled entirely at the native FirebaseMessagingService level.

Note

In coexistence mode, the native routing is automatic — you don't need to write JS filtering code. The JS API methods (registerPushToken, isCrispPushNotification) are optional utilities for advanced use cases.


Usage Examples

Open Chat

Display the Crisp chat widget:

import { show } from "crisp-sdk-react-native";

function ChatButton() {
  const openChat = () => {
    show();
  };

  return <Button title="Chat with us" onPress={openChat} />;
}

User Identification

Set user information to personalize the chat experience:

import {
  setUserEmail,
  setUserNickname,
  setUserPhone,
  setUserAvatar,
  setUserCompany,
  setTokenId,
  resetSession,
} from "crisp-sdk-react-native";

// After user logs in
function identifyUser(user) {
  // Basic identification
  setUserEmail(user.email);
  setUserNickname(user.name);
  setUserPhone(user.phone); // E.164 format recommended: "+1234567890"
  setUserAvatar(user.avatarUrl);

  // Set company information
  setUserCompany({
    name: "Acme Corporation",
    url: "https://acme.com",
    companyDescription: "Leading provider of innovative solutions",
    employment: {
      title: "Software Engineer",
      role: "Engineering",
    },
    geolocation: {
      country: "France",
      city: "Paris",
    },
  });

  // Enable session persistence across devices
  setTokenId(user.id);
}

// On logout
function onLogout() {
  setTokenId(null);
  resetSession();
}

Session Data

Store custom data visible to operators in the Crisp dashboard:

import {
  setSessionString,
  setSessionBool,
  setSessionInt,
  setSessionSegment,
  setSessionSegments,
  getSessionIdentifier,
} from "crisp-sdk-react-native";

// Store different data types
setSessionString("plan", "premium");
setSessionBool("verified", true);
setSessionInt("loginCount", 42);

// Categorize users with segments
setSessionSegment("vip");

// Or set multiple segments at once
setSessionSegments(["premium", "early-adopter", "beta-tester"]);

// Replace all existing segments
setSessionSegments(["enterprise"], true);

// Get the current session identifier
const sessionId = await getSessionIdentifier();
console.log("Session ID:", sessionId);

Event Tracking

Track user actions in the chat timeline:

import {
  pushSessionEvent,
  pushSessionEvents,
  CrispSessionEventColors,
} from "crisp-sdk-react-native";

// Track a single event
pushSessionEvent("Purchase completed", CrispSessionEventColors.GREEN);
pushSessionEvent("Payment failed", CrispSessionEventColors.RED);

// Track multiple events at once
pushSessionEvents([
  { name: "Viewed pricing page", color: CrispSessionEventColors.BLUE },
  { name: "Started free trial", color: CrispSessionEventColors.GREEN },
  { name: "Upgraded to Pro", color: CrispSessionEventColors.PURPLE },
]);

Event Listeners

Subscribe to SDK events using the useCrispEvents hook:

import { useState } from "react";
import { View, Button } from "react-native";
import { show, useCrispEvents } from "crisp-sdk-react-native";

function ChatScreen() {
  const [unreadCount, setUnreadCount] = useState(0);

  useCrispEvents({
    onSessionLoaded: (sessionId) => {
      console.log("Crisp session ready:", sessionId);
    },
    onChatOpened: () => {
      console.log("Chat opened");
      setUnreadCount(0); // Reset unread count
    },
    onChatClosed: () => {
      console.log("Chat closed");
    },
    onMessageSent: (message) => {
      console.log("User sent:", message.content);
    },
    onMessageReceived: (message) => {
      console.log("Received:", message.content);
      if (message.fromOperator) {
        setUnreadCount((count) => count + 1);
      }
    },
  });

  return (
    <View>
      <Button title={`Open Chat (${unreadCount})`} onPress={() => show()} />
    </View>
  );
}

Show Messages

Display messages programmatically in the chat:

import { showMessage } from "crisp-sdk-react-native";

// Simple text message
showMessage({
  type: "text",
  text: "Hello! How can I help you today?",
});

// File attachment
showMessage({
  type: "file",
  url: "https://example.com/document.pdf",
  name: "Document.pdf",
  mimeType: "application/pdf",
});

// Animation (GIF)
showMessage({
  type: "animation",
  url: "https://example.com/celebration.gif",
  mimeType: "image/gif",
});

// Audio message
showMessage({
  type: "audio",
  url: "https://example.com/voice-note.mp3",
  mimeType: "audio/mpeg",
  duration: 15,
});

// Picker for user choice
showMessage({
  type: "picker",
  id: "satisfaction",
  text: "How satisfied are you with our service?",
  choices: [
    { value: "happy", label: "Very satisfied" },
    { value: "neutral", label: "Neutral" },
    { value: "sad", label: "Not satisfied" },
  ],
});

// Field for user input
showMessage({
  type: "field",
  id: "email",
  text: "What's your email address?",
  explain: "We'll send you updates",
  required: true,
});

// Carousel with multiple items
showMessage({
  type: "carousel",
  text: "Check out our products",
  targets: [
    {
      title: "Product A",
      description: "Great for beginners",
      imageUrl: "https://example.com/product-a.jpg",
      actionUrl: "https://example.com/products/a",
    },
    {
      title: "Product B",
      description: "For power users",
      imageUrl: "https://example.com/product-b.jpg",
      actionUrl: "https://example.com/products/b",
    },
  ],
});

Helpdesk

Access your knowledge base:

import { searchHelpdesk, openHelpdeskArticle } from "crisp-sdk-react-native";

// Open helpdesk search (automatically opens the chat)
searchHelpdesk();

// Open a specific article (automatically opens the chat)
openHelpdeskArticle({
  id: "getting-started",
  locale: "en",
  title: "Getting Started", // Optional
  category: "Onboarding", // Optional
});

Bot Scenarios

Trigger automated conversation flows:

import { runBotScenario } from "crisp-sdk-react-native";

// Start a bot scenario configured in your Crisp dashboard
runBotScenario("welcome-flow");

Debug Logging

Enable native SDK logging to help debug integration issues:

import {
  setLogLevel,
  CrispLogLevel,
  useCrispEvents,
} from "crisp-sdk-react-native";

// Set the minimum log level (default: WARN)
setLogLevel(CrispLogLevel.DEBUG);

// Listen to log messages from the native SDK
useCrispEvents({
  onLogReceived: (log) => {
    console.log(`[Crisp] [${log.level}] ${log.tag}: ${log.message}`);
  },
});

Available log levels (from most to least verbose):

Level Value Description
VERBOSE 0 Most verbose, all log messages
DEBUG 1 Debug information
INFO 2 Informational messages
WARN 3 Warnings (default)
ERROR 4 Error messages only
ASSERT 5 Critical assertion failures

Note

Set the log level after calling configure(). Only logs at or above the configured level are emitted to the onLogReceived callback.


API Reference

Configuration Methods

Method Description Parameters Return
configure(websiteId) Initialize the SDK with your Website ID. Must be called once at app startup. websiteId: string void
setTokenId(tokenId) Set a token for session persistence across app reinstalls and devices. tokenId: string | null void

Logger Methods

Method Description Parameters Return
setLogLevel(level) Set the minimum log level for native SDK logging. Logs at or above this level are emitted via onLogReceived. level: CrispLogLevel void

User Information Methods

Method Description Parameters Return
setUserEmail(email, signature?) Set the user's email address. Optional HMAC signature for verification. email: string, signature?: string | null void
setUserNickname(name) Set the user's display name in the chat. name: string void
setUserPhone(phone) Set the user's phone number. E.164 format recommended. phone: string void
setUserAvatar(url) Set the user's avatar image URL. url: string void
setUserCompany(company) Set the user's company information. company: Company void

Session Data Methods

Method Description Parameters Return
setSessionString(key, value) Store a custom string value in session data. key: string, value: string void
setSessionBool(key, value) Store a custom boolean value in session data. key: string, value: boolean void
setSessionInt(key, value) Store a custom integer value in session data. key: string, value: number void
setSessionSegment(segment) Set a single segment to categorize the user. segment: string void
setSessionSegments(segments, overwrite?) Set multiple segments. If overwrite is true, replaces existing segments. segments: string[], overwrite?: boolean void
getSessionIdentifier() Get the current session identifier. - Promise<string | null>

Event Tracking Methods

Method Description Parameters Return
pushSessionEvent(name, color) Track a single event in the user's chat timeline. name: string, color: CrispSessionEventColors void
pushSessionEvents(events) Track multiple events at once. events: SessionEvent[] void

Session Management

Method Description Parameters Return
resetSession() Clear the current session and start a fresh conversation. - void

UI Methods

Method Description Parameters Return
show() Open the Crisp chat widget. - void
searchHelpdesk() Open the helpdesk search interface and the chat widget. - void
openHelpdeskArticle(options) Open a specific helpdesk article and the chat widget. options: HelpdeskArticleOptions void
runBotScenario(scenarioId) Trigger an automated bot scenario. scenarioId: string void

Push Notification Methods (Coexistence Mode)

Method Description Parameters Return
registerPushToken(token) Register a push token (FCM/APNs) with Crisp. token: string void
isCrispPushNotification(data) Check if a notification payload is from Crisp. data: Record<string, string> boolean
setShouldPromptForNotificationPermission(enabled) Control auto-prompting for notification permissions (iOS only, no-op on Android). enabled: boolean void

Message Methods

Method Description Parameters Return
showMessage(content) Display a message as operator in the local chatbox. content: MessageContent void

React Hook

Hook Description Parameters Return
useCrispEvents(callbacks) Subscribe to SDK events with automatic cleanup. callbacks: CrispEventCallbacks void

Utility Functions

Function Description Parameters Return
getSDKVersion() Get the crisp-sdk-react-native version string. - string

TypeScript Types

Core Interfaces

Company

interface Company {
  name: string; // Required: Company name
  url?: string; // Company website URL
  companyDescription?: string; // Brief company description
  employment?: Employment; // User's job details
  geolocation?: Geolocation; // Company location
}

Employment

interface Employment {
  title?: string; // Job title (e.g., "Software Engineer")
  role?: string; // Department/role (e.g., "Engineering")
}

Geolocation

interface Geolocation {
  country?: string; // Country name or ISO code
  city?: string; // City name
}

SessionEvent

interface SessionEvent {
  name: string; // Event name
  color: CrispSessionEventColors; // Event color
}

Message Types

CrispMessage

interface CrispMessage {
  content: string; // Message text
  timestamp: number; // Unix timestamp (ms)
  fromOperator: boolean; // true if from operator
  fingerprint: string; // Unique message ID
  isMe: boolean; // true if sent by current user
  origin: CrispMessageOrigin; // "local" | "network" | "update"
  user?: CrispUser; // Sender information
}

CrispUser

interface CrispUser {
  nickname?: string; // Display name
  userId?: string; // Unique identifier
  avatar?: string; // Avatar URL
}

Message Content Types

The showMessage method accepts these content types:

TextMessageContent

{ type: "text", text: string }

FileMessageContent

{ type: "file", url: string, name: string, mimeType: string }

AnimationMessageContent

{ type: "animation", url: string, mimeType: string }

AudioMessageContent

{ type: "audio", url: string, mimeType: string, duration: number }

PickerMessageContent

{
  type: "picker",
  id: string,
  text: string,
  choices: Array<{ value: string, label: string, selected?: boolean }>
}

FieldMessageContent

{ type: "field", id: string, text: string, explain?: string, required?: boolean }

CarouselMessageContent

{
  type: "carousel",
  text: string,
  targets: Array<{
    title: string,
    description?: string,
    imageUrl?: string,
    actionUrl?: string
  }>
}

Event Callbacks

interface CrispEventCallbacks {
  onSessionLoaded?: (sessionId: string) => void;
  onChatOpened?: () => void;
  onChatClosed?: () => void;
  onMessageSent?: (message: CrispMessage) => void;
  onMessageReceived?: (message: CrispMessage) => void;
  onPushNotificationReceived?: (notification: PushNotificationPayload) => void; // iOS only
  onLogReceived?: (log: CrispLogEntry) => void;
}

Event Payload Types

These types are used internally by the event system:

// Payload for onSessionLoaded callback
interface SessionLoadedPayload {
  sessionId: string;
}

// Payload for onMessageSent and onMessageReceived callbacks
interface MessagePayload {
  message: CrispMessage;
}

// Empty payload for onChatOpened and onChatClosed callbacks
type EmptyPayload = Record<string, never>;

// Payload for onPushNotificationReceived callback (iOS only)
interface PushNotificationPayload {
  title: string;
  body: string;
}

// Payload for onLogReceived callback
interface LogReceivedPayload {
  log: CrispLogEntry;
}

// Log entry from the native SDK
interface CrispLogEntry {
  level: CrispLogLevel; // The log level
  tag: string; // Log category/source
  message: string; // Log message content
}

// Message origin type
type CrispMessageOrigin = "local" | "network" | "update";

Helper Types

Types used within message content interfaces:

// Choice option for picker messages
interface PickerChoice {
  value: string; // Unique identifier
  label: string; // Display text
  selected?: boolean; // Pre-selected state
}

// Target item for carousel messages
interface CarouselTarget {
  title: string; // Item title
  description?: string; // Item description
  imageUrl?: string; // Image URL
  actionUrl?: string; // Action URL when tapped
}

Enums

CrispSessionEventColors

Value Color Suggested Use
RED (0) Red Errors, failures, critical events
ORANGE (1) Orange Warnings, attention needed
YELLOW (2) Yellow Informational highlights
GREEN (3) Green Success, completion, positive events
BLUE (4) Blue Informational, neutral events
PURPLE (5) Purple Special, premium-related events
PINK (6) Pink Social, engagement events
BROWN (7) Brown Historical, archive events
GREY (8) Grey Secondary, low-priority events
BLACK (9) Black System, administrative events

CrispLogLevel

Value Description
VERBOSE (0) Most verbose; includes all log messages
DEBUG (1) Debug information for development
INFO (2) Informational messages
WARN (3) Warnings (default level)
ERROR (4) Error messages only
ASSERT (5) Critical assertion failures

Troubleshooting

"Expo Go is not supported"

The Crisp SDK requires native modules. Use a development build instead:

npx expo run:ios
# or
npx expo run:android

Chat not appearing after show()

Ensure you've called configure() with a valid Website ID before calling show().

Push notifications not working

  1. Verify the config plugin is properly configured in app.json
  2. Rebuild with npx expo prebuild --clean
  3. Ensure your Crisp dashboard has push notifications enabled
  4. For iOS: Verify APNs certificates are configured in Crisp dashboard
  5. For Android: Verify Firebase is properly configured

Session data not persisting

Use setTokenId() with a unique user identifier to enable session persistence across app reinstalls and devices.


Example Apps

Two fully functional example apps are included in the repository to help you get started:

App Directory Description
Expo /example Expo Router app with push notifications (coexistence mode with expo-notifications), event listeners, and all SDK features
Bare React Native /bare-example Bare React Native CLI app demonstrating integration without the Expo managed workflow

Both apps are pre-configured and ready to run — just add your Website ID and follow the setup instructions in each directory.


Resources

Contributing

Issues and pull requests are welcome on GitHub.

License

MIT - See LICENSE for details.

About

📦 Include the Crisp chat widget in your React Native app

Topics

Resources

Stars

Watchers

Forks

Contributors