Install Customerly in React and Next.js (react-live-chat-customerly)

Luca Micheli
Written by Luca MicheliLast updated 1 hour ago

The official React package for Customerly is react-live-chat-customerly. It wraps the same Customerly messenger snippet you would paste in HTML, so everything the messenger does (live chat, Aura AI agent, Help Center, surveys, in-app messages) works in React, Next.js (App Router and Pages Router), Vite, Remix and any React-based app. It is SSR-safe and has no external dependencies.

The most important step is not showing the chat: it is telling Customerly who the logged-in user is. When you pass user_id, email, name and your own attributes, every user who signs up to your app is created in Customerly automatically, lands in the New users list, and can be segmented and reached with newsletters, onboarding emails and targeted campaigns (see "Why passing user data matters" below).

1. Install the package

npm install react-live-chat-customerly
# or
yarn add react-live-chat-customerly
# or
pnpm add react-live-chat-customerly

You need your Project ID (also called app ID). Find it in Customerly under Settings → Installation → Install messenger. Store it in an environment variable, for example NEXT_PUBLIC_CUSTOMERLY_PROJECT_ID (Next.js) or VITE_CUSTOMERLY_PROJECT_ID (Vite). The Project ID is public: it is safe in client code.

2. Wrap your app with CustomerlyProvider

Vite / Create React App / Lovable / Bolt

// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { CustomerlyProvider } from "react-live-chat-customerly";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <CustomerlyProvider appId={import.meta.env.VITE_CUSTOMERLY_PROJECT_ID}>
    <App />
  </CustomerlyProvider>
);

Next.js App Router

The provider uses React hooks, so put it in a client component and use it in your root layout.

// app/customerly-provider.tsx
"use client";
import { CustomerlyProvider } from "react-live-chat-customerly";

export default function Customerly({ children }: { children: React.ReactNode }) {
  return (
    <CustomerlyProvider appId={process.env.NEXT_PUBLIC_CUSTOMERLY_PROJECT_ID!}>
      {children}
    </CustomerlyProvider>
  );
}

// app/layout.tsx
import Customerly from "./customerly-provider";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Customerly>{children}</Customerly>
      </body>
    </html>
  );
}

Next.js Pages Router

Wrap <Component {...pageProps} /> with CustomerlyProvider in pages/_app.tsx.

3. Load the messenger and identify the user

Call load() once so every visitor sees the chat: visitors who are not logged in are tracked as leads. When a user logs in, pass their data with update(). Call logout() only when a logged-in user signs out, never for anonymous visitors (it would reset their chat session).

"use client"; // only needed in the Next.js App Router
import { useEffect, useRef } from "react";
import { useCustomerly } from "react-live-chat-customerly";

type AppUser = {
  id: string;
  email: string;
  name?: string;
  plan?: string;
  createdAt?: string; // ISO date
};

export function CustomerlyIdentify({ user }: { user: AppUser | null }) {
  const { load, update, logout } = useCustomerly();
  const identifiedId = useRef<string | null>(null);

  useEffect(() => {
    load(); // show the messenger to everyone
  }, []);

  useEffect(() => {
    if (user) {
      update({
        user_id: user.id,
        email: user.email,
        name: user.name,
        attributes: {
          plan: user.plan,
          signed_up_at: user.createdAt
            ? Math.floor(new Date(user.createdAt).getTime() / 1000) // dates as Unix timestamps
            : undefined,
        },
      });
      identifiedId.current = user.id;
    } else if (identifiedId.current) {
      logout(); // a logged-in user just signed out
      identifiedId.current = null;
    }
  }, [user?.id]);

  return null;
}

Render <CustomerlyIdentify user={currentUser} /> once, inside the provider, wherever you already know the current user (for example in your auth context or root layout).

  • user_id: your own stable user ID (database or auth ID). Never use a placeholder: all users would share the same profile and conversations.

  • email and name: shown to your team and used for emails.

  • attributes: any key/value you want to see in the inbox, give to Aura, or segment on (plan, role, signup date, usage counters, trial end). Dates are Unix timestamps in seconds.

  • company: for B2B apps, { company_id, name, ... }, see Install live chat with Javascript API.

Example: Supabase Auth

import { useEffect, useState } from "react";
import type { User } from "@supabase/supabase-js";
import { supabase } from "./lib/supabase";
import { CustomerlyIdentify } from "./CustomerlyIdentify";

export function CustomerlyWithSupabase() {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    supabase.auth.getUser().then(({ data }) => setUser(data.user));
    const { data: sub } = supabase.auth.onAuthStateChange((_event, session) => {
      setUser(session?.user ?? null);
    });
    return () => sub.subscription.unsubscribe();
  }, []);

  return (
    <CustomerlyIdentify
      user={user ? {
        id: user.id,
        email: user.email ?? "",
        name: user.user_metadata?.full_name,
        createdAt: user.created_at,
      } : null}
    />
  );
}

With Identity Verification on, Customerly only accepts a user if you also send an email_hash: an HMAC-SHA256 of the lower-cased email, signed on your server with your verification secret. Never put the secret in client code. Get the secret from support via chat, then follow Setting up Identity Verification.

// Server only (Next.js server component, route handler, Supabase Edge Function, Node API)
import crypto from "node:crypto";

export function customerlyEmailHash(email: string) {
  return crypto
    .createHmac("sha256", process.env.CUSTOMERLY_IDENTITY_SECRET!)
    .update(email.toLowerCase())
    .digest("hex");
}

Pass the result from the server to your client component and add it next to the email: update({ user_id, email, email_hash, name, attributes }).

Warning: once Identity Verification is enabled, users without a valid email_hash can no longer authenticate in the chat. Ship the hash first, then turn verification on.

5. Single-page apps: keep data fresh

Call update() when the route changes or when user data changes (plan upgrade, profile edit). This refreshes in-app messages and surveys and keeps attributes current.

const { update } = useCustomerly();
useEffect(() => { update(); }, [pathname]);

6. Track what users do

const { event, attribute } = useCustomerly();

event("project_created");          // behavioural event, usable in filters and Flows
attribute("projects_count", 3);   // set or change one attribute on the fly

Events and attributes are what let you message the right users: for example, everyone who signed up but never created a project, or users on the free plan who were active this week.

Why passing user data matters

  • Every signup is captured automatically. Each user you identify is created in Customerly and appears in the New users list. No CSV imports, no separate email tool to sync.

  • Better support. Your team and Aura see who is writing, their plan and their history, so answers are specific.

  • Segments. Filter contacts by any attribute or event and save them as lists. See Discover how to filter contacts.

  • Newsletters and targeted campaigns. Send product updates to all users, onboarding emails to new signups, or win-back emails to inactive users, from the same place you chat with them. See Send newsletters and targeted emails to the users of your app.

  • Automations. Trigger Flows on events and attributes: onboarding, upsell, surveys, NPS.

All functions

useCustomerly() returns: load, update, open, close, show, hide, event, attribute, logout, showArticle, showBookMeeting, showNewMessage, sendNewMessage, registerCallback. Callbacks include onLeadGenerated, onChatOpened, onChatClosed, onNewConversation, onNewMessageReceived and more. Appearance options (accentColor, contrastColor, position, visible, visibleOnMobile, autodetectLocale, attachmentsAvailable) go in load(). Full reference: the package README on npm.

Prompt to paste into your AI coding assistant

Install the Customerly messenger in this React app using the npm package react-live-chat-customerly.
1. Wrap the app in <CustomerlyProvider appId={PROJECT_ID}> (read it from an env var; in Next.js App Router put the provider in a "use client" component).
2. Call load() once so the chat shows to every visitor.
3. When a user is logged in, call update({ user_id, email, name, attributes }) with the real user from our auth, and pass useful attributes (plan, signup date as Unix seconds, role). Call logout() only when a logged-in user signs out.
4. Call update() on every route change.
5. If identity verification is enabled, compute email_hash = HMAC-SHA256(lowercased email, CUSTOMERLY_IDENTITY_SECRET) on the server only and pass it in update().
Every identified user lands in the Customerly "New users" list, so we can later send newsletters and targeted emails to our users.

Check that it works

  1. Open your app: the chat bubble appears.

  2. Log in as a test user and send a message: in the Customerly inbox the conversation shows the user's name, email and attributes.

  3. Open Contacts: the test user is in the New users list.

Did this article help you solve your issue?