When to Use
-
You want to add the Cloud Chat widget to any page of your website
-
You want to automatically pass contact data (name, email, phone, attributes) without the client typing
-
You want to validate the user's identity (HMAC) to prevent impersonation
-
You want to allow multiple simultaneous conversations and access to history within the widget
-
You want to restrict the widget to specific domains (e.g., production only)
Prerequisites
-
Be logged in as admin on Cloud Chat
-
Access to the source code of the website where the widget will be installed
-
For Scenario 3 (logged-in area with HMAC): a custom backend to generate the
identifier_hashβ it cannot be done on the frontend (exposes the secret key)
About this Tutorial
This article covers the full cycle of installing the Cloud Chat Web Widget. Before following the coding steps, you need to decide which of the 3 scenarios fits your use case β they have very different requirements and complexity.
Which scenario is yours?
| Scenario | When to use | Pass customer data? | Needs HMAC? |
|---|---|---|---|
| 1. Public widget (no data) | Public site / landing page / blog. The customer enters their name and email to start the chat. | β No | β No |
| 2. Widget with data, outside logged-in area | Pages that already know the contact but do not require strong authentication (e.g., single link sent via email/CRM, post-registration form). | β Yes | β No |
| 3. Logged-in area widget (with HMAC) | Customer portal, internal dashboard, authenticated app. Any scenario where user login is required to access. | β Yes | β Mandatory |
If your case is Scenario 3 (logged-in area), you must configure HMAC. Without it, the conversation will not be created.
The contact's custom attribute must be created beforehand β see Creating custom contact and conversation fields.
Common Step β Create the Website Inbox
Before configuring any scenario, you need to create a Website-type inbox in Cloud Chat. The process is the same for all 3 scenarios.
1. Access the Inboxes Screen
In the Cloud Chat dashboard, go to Settings β Inboxes and click on the Add Inbox button (top right corner).

2. Choose the Website Channel
Select the Website card from the available channels.

3. Configure the Website Channel
Fill in the fields:
-
Site Name β name shown to the customer (e.g., "Cloud Humans")
-
Website Domain β domain where the widget will run (e.g.,
cloudhumans.com) -
Widget Color β primary color of the button and header
-
Welcome Title β initial widget title (e.g., "Hello!")
-
Welcome Message β greeting message
-
Activate Channel Greeting β whether to send an automatic message at the start of chat
Click Create Inbox.

4. Add Agents
Select the agents who will have access to this inbox. As an administrator, add yourself if you want to see all conversations.
Click Add Agents.

5. Script Configuration
On the final screen (βYour inbox is ready!β), Cloud Chat displays the basic installation script for the widget. However, other configuration options are available depending on your scenario.
Click More Settings. In this section, you'll see the three available script options for installation, which we will explain below.

Done. Now proceed to the scenario that applies to your case (1, 2, or 3 below) and follow the specific instructions for each.
Scenario 1 β Public Web Widget (no customer data passing)
Use when the widget is on a public page (landing, blog, institutional site). The customer types their name/email/phone at the start.
How to Install
Paste the script copied in the Common Step (Step 5) just before the closing </body> tag of your page's HTML:

That's it. This scenario requires nothing beyond the base script. Do not call setUser(), do not pass identifier_hash. The customer fills in their data in the widget's initial form.
Scenario 2 β Web Widget passing customer data, outside logged-in area
Use when you already know the contact but the page does not require login. Examples:
-
Unique link sent via email or WhatsApp with the
identifierin the URL -
Post-registration page (customer just filled out a form)
-
Page accessed via CRM campaign deep link
Here, you want to pre-fill name, email, phone, and custom attributes without the customer typing.
How to Install

β οΈ The first argument of setUser(...) is the identifier β it must be unique per user (internal ID, database UUID, etc). If you leave the identifier fixed (hardcoded, placeholder, copy-paste example), Cloud Chat will merge all accesses as the same contact β merging tickets from different people and irreversibly breaking history.
Before deploying to production, confirm with your engineering team that the identifier is being dynamically populated with the actual user ID.
You must pass at least email or phone β these are the identifiers Cloud Chat uses to match contacts.
Scenario 3 β Logged-in Web Widget (with HMAC + optional multiple conversations)
Use when the widget is inside a logged-in area (client portal, dashboard, authenticated app). HMAC is mandatory here.
This scenario is also the only one where enabling multiple conversations + history makes sense.
3.1 β How HMAC Works
Validation uses HMAC SHA-256: a code generated from the user's identifier combined with a secret key (token) of the inbox.
The generation of identifier_hash is the client's responsibility. It needs to happen on the backend (server), never in the browser. If the secret key leaks in the frontend, protection ceases to exist. Cloud Humans provides the token per inbox; implementing the hash calculation and passing it to the widget is the client's technical team's responsibility.
3.2 β Copy the inbox token
In Settings β Inboxes β (your Website inbox) β Advanced Settings β User Identity Validation β Copy.
This token is secret β store it only in your backend, never in the frontend.
3.3 β Calculate identifier_hash on backend
When the user authenticates in your system, the backend calculates:
identifier_hash = HMAC_SHA256(inbox_token, identifier)
Where identifier is the user's unique ID (internal UUID, corporate email, etc).
Server-side examples:
// Node.js
const crypto = require('crypto');
const hash = crypto
.createHmac('sha256', '<inbox-token>')
.update('<identifier>')
.digest('hex');
# Python
import hashlib, hmac
hash = hmac.new(b'<inbox-token>', b'<identifier>', hashlib.sha256).hexdigest()
// PHP
$identifier_hash = hash_hmac('sha256', '<identifier>', '<inbox-token>');
3.4 β Send the hash to the widget via setUser
<script>
(function(d,t) {
var BASE_URL="https://cloudchat2.cloudhumans.com";
var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=BASE_URL+"/packs/js/sdk.js";
g.defer = true;
g.async = true;
s.parentNode.insertBefore(g,s);
g.onload=function(){
window.cloudchatSDK.run({
websiteToken: 'YOUR_TOKEN_HERE',
baseUrl: BASE_URL
});
window.addEventListener('cloudchat:ready', function() {
window.$cloudchat.setUser('<user-identifier>', {
identifier_hash: '<hash-generated-backend>',
email: '[email protected]',
name: 'JoΓ£o da Silva',
phone_number: '+5511999999999'
});
});
}
})(document,"script");
</script>
3.5 β Force validation in the inbox
In Advanced Settings, enable "Force user identity validation". Requests without a valid identifier_hash are rejected.
Activate "Force validation" only after your backend is sending the correct identifier_hash. If activated prematurely, conversations without the hash will be rejected and the chat will stop working. Test first in a test inbox.
Best practices:
-
Use a stable
identifierβ never change the ID of an existing user -
Do not expose the HMAC token in the frontend
-
Generate the hash always on backend and send only during widget initialization
-
Regenerate the
identifier_hashevery time the widget loads for an authenticated user
3.6 β (Optional) Enable multiple conversations and history
With HMAC enabled, you can activate the feature of multiple conversations + history: the same user can have several open conversations simultaneously and see the history of closed conversations within the widget.
Useful for SaaS, B2B, or e-commerce with high repurchase/retargeting.
How the user sees: the widget will now display two tabs β Active Conversations (open) and Conversation History (closed, with date range and ticket ID search; loads 5 at a time).
Demonstrative videos:
How to enable:
-
In Cloud Chat dashboard, go to Inboxes β (your Website inbox) β Settings
-
Enable the Multiple conversations per user flag
-
Copy the new script displayed after activation β it already includes
user_idandidentifier_hashin the correct format -
Replace the current page script with the new one
The multiple conversations and history feature depends on HMAC being active and working. Do not enable it on public widget (Scenario 1) or non-logged-in widget (Scenario 2) β without identity validation, anyone can access another user's history.
Domain Validation (optional, all scenarios)
Configure the domains where the widget can operate β useful to prevent usage outside authorized domains (staging, unauthorized third parties).
In Inboxes β (your inbox) β Settings, under the Domain Validation section:

| Setting | Behavior |
|---|---|
| Empty field | No restrictions β works on any domain |
example.com |
Allows use only on this domain |
*.example.com |
Allows use on all subdomains (e.g., app.example.com, login.example.com) |
How to Test
-
Open the page with the widget installed
-
Check if the widget appears at the corner of the screen
-
Scenarios 2 and 3: verify that name, email, phone, and attributes already appear pre-filled without customer input
-
Scenarios 2 and 3: test with at least 2 different users β open the widget with one, then with another, and check if they appear as separate contacts (not merged into one). If they appear merged, the
identifieris fixed β fix it before deploying to production -
Scenario 3: test with an invalid
identifier_hashand verify that the widget rejects the request when "Force validation" is enabled -
Scenario 3 with multiple conversations: open two tickets in parallel and check that they appear as separate conversations inside the widget
Frequently Asked Questions
What happens if there is already previous contact information?
The new data sent via script overwrites the old data. The most recent information prevails.
What if I make a mistake in a custom field name?
No error is thrown. The incorrect field is silently ignored. Only existing fields are updated.
Can I pass conversation attributes as well?
Not at the moment. Passing custom conversation attributes has not been released in version 0 due to technical limitations. Use the initial conversation form as an alternative.
What formatting does the widget accept?
The Widget accepts most Markdown formats:
-
Bold / Strikethrough / Italic
-
Code block
-
Links
-
Images
-
Bullet points

Can I use HMAC without enabling multiple conversations?
Yes. HMAC is an independent security layer β you can enable only HMAC (Scenario 3, steps 3.1 to 3.5) without enabling multiple conversations (step 3.6). The reverse is not recommended.
Can I use this in mobile apps?
Yes, via WebView. See How to integrate the Web Widget into mobile apps.
Notes
-
To share the widget session across browser tabs: How to share the Web Widget session between browser tabs
-
To use the widget in mobile apps via WebView: How to integrate the Web Widget into mobile applications
-
To create custom attributes before passing via script: How to create custom contact and conversation fields
-
To enable conversation continuity via email: How to enable conversation continuity via email
-
To activate the widget in the Help Portal: How to activate the Web Widget in the Help Portal