Customization and security
What to configure in Kustomer versus in code, custom launchers, language and right-to-left support, domain restrictions, Content Security Policy with nonces, and privacy considerations for web chat.
Web chat is configured in two places. Admins set the brand's look and behavior in Kustomer, and every SDK (web, iOS, Android) picks it up. Your code controls where and how the widget sits on your page.
Configured in Kustomer
These come from the brand's chat settings and apply to every platform at once, with no deploy:
The Core API returns all of these from init, so a custom UI can honor them.
Configured in code
See Start options for the full list.
Use your own launcher
Hide Kustomer's button and drive the widget from yours, with an unread badge:
<button id="help" type="button">Help <span id="help-badge" hidden></span></button>
<script>
window.addEventListener('kustomerLoaded', function () {
Kustomer.start({ brandId: 'YOUR_BRAND_ID', hideChatIcon: true }, function () {
var badge = document.getElementById('help-badge')
Kustomer.addListener('onUnread', function (res) {
badge.hidden = !res.total
badge.textContent = res.total
})
document.getElementById('help').addEventListener('click', function () {
Kustomer.open()
})
})
})
</script>If chat can be hidden outside business hours, hide your button too: check Kustomer.isChatAvailable().availability when the page loads.
Language
The widget follows the visitor's browser language unless you set lang. It ships translations for more than 50 languages, including en_us, es, fr, de, it, pt, pt_br, nl, sv, da, no, fi, pl, cs, tr, ru, uk, ja, ko, zh_cn, zh_tw, th, vi, id, hi, ar and he.
- Codes are matched case-insensitively, and
pt-BRis treated aspt_br. - A regional code without its own translation falls back to the base language, so
fr_causesfr. arandheswitch the widget to right-to-left layout.
Text you control in Kustomer (greeting, assistant dialogs, knowledge base articles) is translated separately in Kustomer.
Restrict where chat runs
Admins can limit chat to pages whose URL matches rules in the brand's chat settings. The widget hides itself on pages that don't match, and checks again whenever the URL changes, so it works with client-side routing: you can load the script on every page and let the rules decide.
Headless UIs apply the same rules with KustomerCore.isUrlAllowed({ url: location.href }), which returns { allowed }.
These rules control where chat is shown. They aren't an access control: the chat key itself still works anywhere, which is safe because of what the org.tracking role allows.
Content Security Policy
The widget runs in iframes created from your page, so your page's Content Security Policy applies to it.
Use a nonce
If your policy uses nonces, put the nonce on the script tag:
<script
src="https://cdn.kustomerapp.com/chat-web/widget.js"
data-kustomer-api-key="YOUR_CHAT_KEY"
nonce="r4nd0m-per-request"
></script>The SDK reads the nonce from the tag with data-kustomer-api-key and adds it to the scripts it loads, but only to inline scripts and scripts from Kustomer's CDN (https://cdn.kustomerapp.com). Scripts from any other origin never get your nonce. The same works for core.js.
Directives
Chat needs to load scripts from the CDN, call Kustomer's API, hold a realtime connection, and show images and attachments. Start from this policy, which is known to work, in Content-Security-Policy-Report-Only mode, then tighten connect-src, img-src and media-src using the violations your browser reports:
script-src 'nonce-r4nd0m-per-request';
style-src * 'unsafe-inline';
img-src * data: blob: https:;
media-src *;
connect-src *;
object-src 'none';style-src 'unsafe-inline' is required: the widget sets inline styles for positioning and theming.
Privacy
- Chat keys are public. Anyone can read them from your page. That's expected: the
org.trackingrole can only act as the chat customer on that browser. Never put any other kind of API key in a web page. - Anonymous by default. Until you call
login, Kustomer only knows the browser. Don't usedescribeCustomerto attach an email or phone you haven't verified; useloginwith a signed token instead. - Log out on shared devices. Call
Kustomer.logout()when your user signs out, so the next person on the device doesn't see their conversations. - Browser storage. The SDK stores the session in the browser so conversations survive reloads.
logout()clears it.