npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

crisp-sdk-react-native

v0.1.0

Published

Expo Module bridge for Crisp Chat iOS and Android SDK

Readme


[!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.

[!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 expo-crisp-sdk

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

# Using npm
npx expo install expo-crisp-sdk

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

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 expo-crisp-sdk

# Using yarn
yarn add expo-crisp-sdk

# Using pnpm
pnpm add expo-crisp-sdk

# Using bun
bun add expo-crisp-sdk

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

Initialize Crisp

Configure the SDK at app startup with your Website ID:

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

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": [
      [
        "expo-crisp-sdk",
        {
          "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": [
      [
        "expo-crisp-sdk",
        {
          "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 "expo-crisp-sdk";

// 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 "expo-crisp-sdk";

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 "expo-crisp-sdk";

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 "expo-crisp-sdk";

// 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 "expo-crisp-sdk";

// 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 "expo-crisp-sdk";

// 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 "expo-crisp-sdk";

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 "expo-crisp-sdk";

// 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 "expo-crisp-sdk";

// Open helpdesk search
searchHelpdesk();

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

Bot Scenarios

Trigger automated conversation flows:

import { runBotScenario } from "expo-crisp-sdk";

// 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 "expo-crisp-sdk";

// 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. | - | void | | openHelpdeskArticle(options) | Open a specific helpdesk article. | 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 expo-crisp-sdk 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.