React SDK
Use @sparrowdesk/react-chat to embed the widget in React and Next.js with a typed, SSR-safe API
@sparrowdesk/react-chat is the official React package for embedding the SparrowDesk chat widget. It handles script loading, configuration, and lifecycle — so you get a typed, SSR-safe component and hooks instead of managing the widget script yourself.
For low-level control from any page, see JavaScript API.
Install
pnpm add @sparrowdesk/react-chat
# or: npm install @sparrowdesk/react-chat
# or: yarn add @sparrowdesk/react-chatUse your SparrowDesk widget domain and token from Settings → Chat Widget in the app (same values the HTML snippet uses).
Chat component
Minimal usage:
import * as React from "react";
import { Chat } from "@sparrowdesk/react-chat";
export function App() {
return (
<Chat
domain="your-workspace.sparrowdesk.com"
token="YOUR_WIDGET_TOKEN"
openOnInit
/>
);
}Behavior highlights from the package:
- Injects the widget script once and dedupes duplicate mounts.
- SSR-safe: no-ops when
window/documentare unavailable. - TypeScript: typed
ChatProps. - Optional deferral: wait until user interaction before loading the script (see below).
Common props
| Prop | Notes |
|---|---|
domain | Required. SparrowDesk host for the widget, e.g. your-workspace.sparrowdesk.com. |
token | Required. Widget token from SparrowDesk settings. |
tags | Passed to window.sparrowDesk.setTags when the API is ready. |
contactFields | Record → setContactFields (internal names; invalid keys/values skipped server-side). |
conversationFields | Record → setConversationFields. |
onReady | Called when window.sparrowDesk is available; receives the API object. |
onOpen / onClose | Wired via onOpen / onClose on the global API. |
openOnInit | If true, calls openWidget() when ready. |
hideOnInit | If true, calls hideWidget() when ready. |
connectOnPageLoad | Default true. If false, can delay script injection (see performance below). |
initializeOnInteraction | Default true with deferred load: init on first pointerdown / keydown. |
readyTimeoutMs | How long to wait for window.sparrowDesk (default 10000). |
cleanupOnUnmount | If true, removes the injected script tag on unmount. |
Example with fields and events:
<Chat
domain="your-workspace.sparrowdesk.com"
token="YOUR_WIDGET_TOKEN"
tags={["vip", "returning-user"]}
contactFields={{
full_name: "Alex",
nick_name: "Alex",
}}
conversationFields={{
priority: "med",
status: "todo",
request_type: "ENQUIRY",
}}
onOpen={() => console.log("Widget opened")}
onClose={() => console.log("Widget closed")}
/>Provider and useSparrowDesk()
To open, close, hide, or set tags from anywhere under a subtree, wrap the app with SparrowDeskProvider and use useSparrowDesk():
import {
SparrowDeskProvider,
useSparrowDesk,
} from "@sparrowdesk/react-chat";
function HomePage() {
const { openWidget, closeWidget, hideWidget, setTags } = useSparrowDesk();
return (
<>
<button type="button" onClick={() => openWidget()}>Open</button>
<button type="button" onClick={() => closeWidget()}>Close</button>
<button type="button" onClick={() => hideWidget()}>Hide</button>
<button type="button" onClick={() => setTags(["vip"])}>Set tags</button>
</>
);
}
export function App() {
return (
<SparrowDeskProvider
domain="your-workspace.sparrowdesk.com"
token="YOUR_WIDGET_TOKEN"
openOnInit
>
<HomePage />
</SparrowDeskProvider>
);
}Next.js (App Router)
Route segments are Server Components by default. Because Chat (and the provider) use client-side hooks, put them in a Client Component ("use client") and render it from your root layout (typically at the end of <body>).
"use client";
import { Chat } from "@sparrowdesk/react-chat";
export function SparrowDeskChat() {
return (
<Chat
domain={process.env.NEXT_PUBLIC_SD_DOMAIN!}
token={process.env.NEXT_PUBLIC_SD_TOKEN!}
/>
);
}For the Pages Router, you can optionally load the widget with dynamic(..., { ssr: false }) if you want to guarantee client-only rendering.
Defer loading until interaction
To avoid loading the widget script on first paint, set connectOnPageLoad={false} and use initializeOnInteraction (default true in many setups) so the script loads after the first pointer or key event. You can also pair connectOnPageLoad={false} with initializeOnInteraction={false} and call openWidget() from a button via useSparrowDesk().
Examples
Full working examples for React and Next.js are available in the SparrowDesk/chat examples directory.