helpcab
Back to home

Docs

Identify your users

Out of the box, every chat reaches your inbox as “Visitor 42”. One global object turns that into a name, an email, and anything else your app already knows — their plan, their last order, how long they have been a customer.

Concept

How it works

The widget gives every browser a visitor id the first time it loads and keeps it in localStorage, so the same person is recognised across pages, tabs and return visits. That is enough to thread a conversation together — but not to know who they are.

You supply the “who”. Your site sets window.helpcabUser with whatever it knows about the signed-in user. The widget reads it when it boots, again a few seconds later, on every client-side route change, whenever the chat is opened, and on its background heartbeat. It only sends something when the values actually changed — so there is no ordering rule to get right, and no traffic when nothing moved.

  1. Your page sets window.helpcabUser — before or after the widget script, it makes no difference.
  2. The widget attaches those details to this browser's visitor record.
  3. Your inbox shows the person's name instead of a number — immediately, even mid-conversation.

Recommended

The one-line way

Drop this anywhere your app renders for a logged-in user. It works on every stack, and it is the only method with no load-order rules at all.

html
<script>
  // Set this wherever your app knows who is signed in.
  // Leave it unset for logged-out visitors.
  window.helpcabUser = {
    userId: "usr_123",          // your own user id
    email:  "[email protected]",
    name:   "Jane Doe",
    plan:   "pro"               // any extra key shows up in your inbox
  };
</script>
Extra keys are free. Anything beyond userId, email, name and phone — plan, company, order count, signup date — is stored as a custom attribute and shown to whoever answers the chat.

Do not set it at all for logged-out visitors. They stay anonymous, which is the correct behaviour.

Framework

React & Next.js

Set it in an effect keyed on your session so it follows sign-in, sign-out and account switches. Render the component once, high in your tree.

tsx
"use client"
import { useEffect } from "react"

// Runs again whenever the session changes — sign-in, sign-out, account switch.
export function HelpcabIdentity({ user }) {
  useEffect(() => {
    if (!user) {
      // Logged out: forget the previous person so the next one on this
      // browser doesn't open the widget onto someone else's conversation.
      window.ChatWidget?.reset()
      window.helpcabUser = undefined
      return
    }
    window.helpcabUser = {
      userId: user.id,
      email: user.email,
      name: user.name,
      plan: user.plan,
    }
  }, [user])

  return null
}

This is safe with strategy="afterInteractive", where your effect usually runs before the widget script has even downloaded. The widget reads the global when it arrives.

Framework

Server-rendered sites

Rails, Django, Laravel, WordPress, Shopify — print the object straight into the page. Always JSON-encode the values; a name containing an apostrophe will otherwise break the page.

shopify (liquid)
{% if customer %}
<script>
  window.helpcabUser = {
    userId: {{ customer.id | json }},
    email:  {{ customer.email | json }},
    name:   {{ customer.name | json }},
    orders: {{ customer.orders_count | json }}
  };
</script>
{% endif %}
php / laravel
@auth
<script>
  window.helpcabUser = @json([
    'userId' => auth()->id(),
    'email'  => auth()->user()->email,
    'name'   => auth()->user()->name,
    'plan'   => auth()->user()->plan,
  ]);
</script>
@endauth

No JavaScript

Script tag attributes

If your platform only lets you paste one tag and interpolate values into it, put the identity on the tag itself.

html
<script
  src="https://helpcab.com/chat-widget.js"
  data-widget-key="YOUR_WIDGET_KEY"
  data-user-id="usr_123"
  data-user-email="[email protected]"
  data-user-name="Jane Doe"
  data-user-attributes='{"plan":"pro","mrr":49}'
  defer></script>

These are read once, when the widget loads. For anything that can change while the page is open, prefer window.helpcabUser.

Reference

JavaScript API

js
// Safe to call at any time — before or after the widget finishes loading.
// Calls made early are queued and replayed, never dropped.
window.ChatWidget.identify({
  userId: "usr_123",
  email: "[email protected]",
  name: "Jane Doe",
  plan: "pro",
})

// On logout — starts a fresh, anonymous visitor.
window.ChatWidget.reset()
MethodWhat it does
ChatWidget.identify(user)Attach a name, email, phone, userId and any extra attributes to this visitor.
ChatWidget.reset()Forget the current visitor and start a fresh, anonymous one. Call this on logout.
ChatWidget.open()Open the chat panel — wire it to your own “Contact support” button.
ChatWidget.close()Close the chat panel.
ChatWidget.toggle()Open if closed, close if open.
ChatWidget.sendMessage(text)Send a message as the visitor.
ChatWidget.track(event, data)Record a custom event against this visitor.
ChatWidget.getVisitor()Read back the current visitor id, conversation id and identity.
Call it whenever you like. Every method exists from the moment the script tag is parsed. Calls made while the widget is still starting up are queued and replayed — they never throw, and they are never dropped.

Important

Logout & account switching

A visitor record lives in the browser, not in your session. On a shared computer — a family laptop, a support desk, a kiosk — that means the next person can open the widget onto the previous person's conversation unless you say otherwise.

js
window.ChatWidget.reset()

If a different email or user id turns up without a reset — a straight account switch — the widget notices and resets itself. Calling reset() on logout is still the right thing to do, because a logged-out browser has no new identity to compare against.

Result

What your team sees

Once identity is flowing, every conversation carries:

  • The person's name and email in the conversation list, the chat header and the profile panel — no more “Visitor 42”.
  • Their phone number, if you passed one.
  • Every extra key under “Details from your app” in the profile panel, next to their location, device and page history.
  • All of their devices as one conversation — see One person, many devices.

All of it is available over the API too, at GET /api/v1/visitors.

Result

One person, many devices

A visitor record is a browser, not a person. The same customer on a laptop, a phone and an incognito window is three records — which is why, in every live chat tool, one person turns into three unrelated conversations and nobody can follow the story.

Identity fixes it. Once two browsers report the same email (or the same userId), Helpcab links them and your inbox shows one row for the person, marked 2 chats. Opening it gives you every message they have ever sent you, in order, with a divider where a new session began. Your reply goes to the device they used last, so it reaches them where they actually are.

You do not have to do anything for this beyond passing the email. It applies to conversations you already have, too.

The visitor's side is deliberately not merged. Their laptop keeps showing only the laptop's messages. Restoring a full history to any browser that claims an address is a support-thread takeover — type someone's email, read their tickets. Every tool that offers cross-device continuity to the visitor gates it behind a secret your server signs, and until we ship that, merging stays on the agent side where it cannot leak anything.

Shortcut

Let AI do it

Paste this into whatever coding assistant you already use — Claude, Cursor, Lovable, ChatGPT, Bolt, Replit. It wires the identity into your existing auth code rather than inventing a new user object.

ai prompt
My site already has the Helpcab chat widget installed:

<script src="https://helpcab.com/chat-widget.js" data-widget-key="YOUR_WIDGET_KEY" defer></script>

Right now every chat reaches my support inbox as an anonymous "Visitor 42". Change that: make the site tell Helpcab who the logged-in user is.

What to do:

Set a global object called window.helpcabUser wherever my app knows the current user — the root layout, the auth provider, or the server-rendered page template. Load order does not matter; the widget reads it before and after it loads, and picks up changes.

window.helpcabUser = {
  userId: "<my app's user id>",
  email:  "<the user's email>",
  name:   "<the user's full name>",
  plan:   "<optional: any extra detail a support agent would want>",
}

In React or Next.js, use an effect keyed on the session so it updates on sign-in and sign-out:

useEffect(() => {
  if (!user) {
    window.ChatWidget?.reset()   // logout: don't leak the last user's chat
    window.helpcabUser = undefined
    return
  }
  window.helpcabUser = { userId: user.id, email: user.email, name: user.name }
}, [user])

Rules:
- Wire it into my EXISTING auth/session code — do not invent a new user object or hardcode an example email
- Do not set window.helpcabUser for logged-out visitors
- Call window.ChatWidget?.reset() on logout
- Add 2 or 3 extra keys that would genuinely help a support agent (plan, company, signup date) — every extra key shows up in the inbox
- Never pass passwords, tokens, API keys or payment details

Then tell me which files you changed and how I can verify it worked.

Replace YOUR_WIDGET_KEY with the key from your dashboard — it is in the install snippet you already pasted:

install snippet
<script src="https://helpcab.com/chat-widget.js" data-widget-key="YOUR_WIDGET_KEY" defer></script>

Reference

Limits & security

  • Up to 40 custom attributes per visitor, 500 characters per value. Objects and arrays are stored as JSON.
  • Emails are lowercased and validated; an address that is not one is ignored rather than stored.
  • Identity sticks to the visitor record, so a returning customer is still recognised on their next visit.
This runs in the browser, so treat it as a label, not as proof. Anything your page can send, a determined visitor can also send from their own console. It is exactly right for “who am I talking to?” — and wrong as the basis for releasing account details, resetting a password or issuing a refund. Verify those the way you always would. Never pass passwords, session tokens, API keys or card numbers.

Help

Troubleshooting

Still seeing “Visitor 42”?

  • Open your site and type window.helpcabUser in the browser console. If it is undefined, your app is not setting it on that page — check that you are logged in and that the code runs on the client, not only on the server.
  • Check the object has a real email or name. An object of only optional extras has nothing to identify.
  • Run window.ChatWidget.getVisitor() — it returns what the widget currently believes about this person.
  • Conversations that started before you added identity keep the name they had. Start a new chat to see the change.

Still stuck? Open the chat in the corner of this page — we answer it ourselves.

Identify your users — Helpcab docs