If your help center runs on Zendesk Guide and customers sign in to it through your own product, you can pass each signed-in customer's identity to the Assembled chat widget. The chat agent can then personalize answers, keep conversations linked to the right person across visits, and pass the customer's details along when a chat is handed off to your team.
This article walks through the full setup. For a general introduction to installing the widget, see AI Chat installation - quick setup.
How it works
The chat widget identifies users with a JSON Web Token (JWT). This is a short, signed piece of text that contains the user's ID and, optionally, their name, email, and other details.
- A customer signs in to your help center.
- A script in your help center theme asks your server for a token.
- Your server confirms who the customer is from its own login session. It then creates a token signed with a secret key that only your server and Assembled know.
- The script passes the token to the chat widget.
- Assembled checks the token's signature with every message. If anyone changes the token, the signature no longer matches and Assembled ignores it.
Zendesk hosts your help center pages, so the token has to come from your own server. Never create the token in the browser or add your secret to your help center theme. Visitors can read and change anything that runs in their browser.
Before you begin
You'll need:
- Admin access to your chat agent settings in Assembled.
- Guide Professional or Guide Enterprise, so you can edit your help center theme's code.
- Help center sign-in that goes through your own product, for example single sign-on from your product to Zendesk. This is how your server knows who is signed in.
- A developer who can add an endpoint to your product's backend.
We recommend hosting your help center on your own domain (for example, help.yourcompany.com) rather than yourcompany.zendesk.com. Zendesk calls this host mapping. When your help center and your product share a domain, browsers send your product's login cookie along with the token request. When the help center is on a zendesk.com address, many browsers block that cookie, including Safari.
Note: If customers sign in to your help center with Zendesk accounts that aren't connected to your product, your server can't confirm who they are, so secure authentication isn't possible. See "If your help center doesn't use your product's sign-in" below.
Step 1: Create your JWT secret
- Visit the Chat agent page in Assembled and select the Setup tab.
- In the User data authentication section, select Manage JWT Secret.
- Select Create JWT secret.
- Copy the secret and store it somewhere secure, like a password manager.
Important: The secret is shown only once. If you lose it, you'll need to generate a new one, and a new secret immediately stops the old one from working.
One secret covers every chat profile in your account. Share it with your developer through a password manager rather than email or chat.
Step 2: Create a token endpoint on your server
Add an endpoint to your product's backend that your help center can call, for example:
GET https://app.yourcompany.com/api/assembled-chat-token
The endpoint should:
- Check the visitor's login session in your product.
- Return a
401status if the visitor isn't signed in. - If the visitor is signed in, return a token signed with your JWT secret using the HS256 algorithm, in the format
{ "token": "YOUR_JWT" }.
Token contents
| Field | Type | Required | Description |
|---|---|---|---|
user_id |
string or number | Yes | User's unique identifier |
email |
string | No | User's email address. Used to identify the user when a chat is handed off to your team. |
name |
string | No | User's display name |
metadata |
Record<string, unknown> | No | Additional user data as key-value pairs, such as plan or account type |
Example token generation (Node.js):
const jwt = require('jsonwebtoken');
app.get('/api/assembled-chat-token', requireLogin, (req, res) => {
const token = jwt.sign(
{
user_id: req.user.id,
email: req.user.email,
name: req.user.name,
metadata: { plan: req.user.plan },
},
process.env.ASSEMBLED_CHAT_JWT_SECRET,
{ algorithm: 'HS256', expiresIn: '12h' }
);
res.json({ token });
});Important: Your endpoint must identify the user from its own login session. Never accept a user ID or email from the request and sign it. Otherwise anyone could sign in to the chat as someone else.
Token expiration
Setting an expiration (the exp claim) is optional. Assembled checks the token with every message, so if you do set one, choose a lifetime that covers a full conversation. We recommend several hours. You can also pass a new token at any time by calling window.assembled.authenticateUser() again.
Allow your help center to call the endpoint
Your help center and your backend are on different domains, so the endpoint must allow requests from your help center (CORS). Set these response headers:
Access-Control-Allow-Origin: https://help.yourcompany.com Access-Control-Allow-Credentials: true
Use your help center's exact address, not *. Browsers reject responses to requests that include cookies when the endpoint allows all origins.
If your help center isn't on your own domain, your login cookie must also be set with SameSite=None and Secure for browsers to send it, and some browsers will block it anyway.
Step 3: Add the chat widget and authentication script to your theme
- Go to the administrative portal for your Zendesk Guide settings:
https://[YOUR ZENDESK DOMAIN].zendesk.com/knowledge - Select the Customize design icon on the navigation bar.
- Select the theme you'd like to edit (usually your live theme) and select Customize.
- Select Edit code.
- Open
document_head.hbsand add the following to the bottom of the file:
<script
src="https://cal.assembledhq.com/static/js/public-chat.js"
data-company-id="YOUR_COMPANY_ID"
></script>
<script>
(async function () {
try {
const response = await fetch('https://app.yourcompany.com/api/assembled-chat-token', {
credentials: 'include',
});
if (!response.ok) return;
const { token } = await response.json();
await window.assembled.authenticateUser(token);
} catch (error) {
console.warn('[Assembled] Chat sign-in skipped', error);
}
})();
</script>- Replace
YOUR_COMPANY_IDand the endpoint URL with your own values. Copy the first script tag from the Installation section of the Setup tab to get the correct company ID, plus your profile ID if you use more than one chat profile. - Select Publish.
The first script loads the chat widget. The second asks your server for a token and passes it to the widget. If the visitor isn't signed in, your endpoint returns a 401, the script stops, and the chat works anonymously.
Note: Don't add async or defer to the first script tag. The authentication script needs the widget to load first.
Step 4: End the chat session when users sign out
The chat widget keeps a user's conversations in their browser. Ending the chat session at sign-out keeps the next person on that browser from seeing the previous person's conversations.
Add this script to document_head.hbs, below the scripts from step 3:
<script>
document.addEventListener('click', function (event) {
const signOutLink = event.target.closest('a[href*="/access/logout"]');
if (!signOutLink || !window.assembled) return;
event.preventDefault();
window.assembled.teardown({ clearSession: true }).finally(function () {
window.location.href = signOutLink.href;
});
});
</script>The script ends the chat session before the sign-out continues, which takes at most 2 seconds.
Note: The sign-out link in Zendesk's standard themes points to /access/logout. If your theme uses a different sign-out link, update the selector to match. For more detail, see "Logging out and switching users" in AI Chat installation - advanced setup.
Step 5: Test your setup
Tip: While testing, add data-debug="true" to the chat widget's script tag to see [Assembled] messages in the browser console. Remove it before going live.
| Test | Expected result |
|---|---|
| Sign in to your help center and open the chat | In your browser's developer tools (Network tab), the request to your token endpoint returns 200. The chat opens normally. |
| Send a message, then open the conversation in Assembled | The conversation shows the user's details. |
| Visit your help center while signed out | The token request returns 401, and the chat works anonymously. |
| Sign out, then open the chat again | The previous conversation no longer appears. |
| Sign in as a different user | None of the first user's conversations appear. |
Step 6: Map user data to smart fields
To use user details in your chat agent's answers and routing, map them to smart fields:
- Go to Configure > Smart fields.
- Create smart fields for the user data you want to use, if they don't already exist.
- Head to AI support > Chat agent > Setup.
- Select the attribute from the JSON path and map each user attribute to a smart field.
Step 7: Require verified user data
Once testing passes, turn on verification so the chat only accepts user details that come from a signed token:
- Visit the Chat agent page and select the Setup tab.
- In the User data authentication section, select Only accept user data that has been securely verified through a signed token.
- Save your changes.
With this on, the chat ignores user details passed any other way, such as with setUserData(). Visitors who aren't signed in can still use the chat anonymously.
If your help center doesn't use your product's sign-in
If customers sign in to your help center with Zendesk accounts that aren't connected to your product, you can still pass user details with setUserData(). These details aren't verified, so visitors could change them.
await window.assembled.setUserData({
user_id: 'usr_1234',
name: 'John Smith',
email: 'john@example.com',
});If you use this approach, leave the setting from step 7 off. Otherwise these details are ignored.
Troubleshooting
Users always appear anonymous:
- Check the request to your token endpoint in your browser's Network tab.
- A CORS error in the console means the headers from step 2 are missing or don't match your help center's address.
- A
401response while signed in means your login cookie isn't reaching your server. Check that your help center is on your own domain.
Authentication stops working partway through a conversation:
- Your token's expiration is too short. Increase it, or call
authenticateUser()with a new token before the old one expires.
Authentication stopped working for all users at once:
- A new JWT secret may have been generated in Assembled, which replaces the old one. Update your server with the new secret.
The token is rejected:
- Make sure it's signed with HS256 using your current secret, and that it includes a
user_id.
The chat widget doesn't appear:
- Check your activation settings. See "Manage activation and rollout" in AI Chat installation - quick setup.
Comments
0 comments
Please sign in to leave a comment.