The widget
Content Security Policy (CSP)
The exact sources to allow for the widget on a site with a strict Content-Security-Policy, nonces for its styles, pinning a version with Subresource Integrity, and loading it on click.
If your site sends a Content-Security-Policy header, allow the sources below. The widget needs nothing else.
Sources to allow
| Directive | Source | Needed for |
|---|---|---|
script-src | https://widget.iperchat.ai (or your nonce on the script tag) | The widget script |
connect-src | https://api.iperchat.ai | Settings, conversations and streamed replies |
connect-src | https://identitytoolkit.googleapis.com, https://securetoken.googleapis.com | Visitor sign-in. Not needed with Anonymous-only mode (in “My Tenant”) |
style-src | Your nonce, or 'unsafe-inline' | The widget’s stylesheet (see below) |
img-src | The hosts of your logo and header image URLs | As set in “Agent Configurations” |
img-src | https://storage.googleapis.com | Knowledge-base images shown in replies |
media-src | blob:, data: | Voice replies, only if voice playback is on |
The widget opens no frames and loads no web fonts, so it needs no frame-src or font-src entries. It uses Inter when your page provides it, otherwise the system font.
A complete example, with {NONCE} standing for the random value your server generates for each response:
Content-Security-Policy:
script-src 'self' https://widget.iperchat.ai 'nonce-{NONCE}';
style-src 'self' 'nonce-{NONCE}';
connect-src 'self' https://api.iperchat.ai https://identitytoolkit.googleapis.com https://securetoken.googleapis.com;
img-src 'self' https://storage.googleapis.com;
frame-src 'none'
Styles: a nonce or 'unsafe-inline'
The widget adds its stylesheet as <style> elements: one inside its own shadow root, one in <head> for CSS custom properties, and one for the launcher placeholder while the page loads. A strict style-src blocks them unless you either:
- use a nonce (recommended). Put your page’s nonce on the widget’s script tag. The widget copies it onto its
<style>elements. When you start the widget from JavaScript, it uses the nonce of the script tag that loaded it, or the one you pass toIperChat.init({ nonce }). - or allow
'unsafe-inline'instyle-src.
<script
src="https://widget.iperchat.ai/iperchat.iife.js"
nonce="{NONCE}"
data-iperchat-auto-init
data-tenant-id="YOUR_TENANT_ID"
></script>
The widget also sets some styles directly from JavaScript. CSP allows those without a nonce.
Pin a version with Subresource Integrity
https://widget.iperchat.ai/iperchat.iife.js always serves the latest widget, so it can change with any IperChat release. To load a build that never changes, use a versioned URL with its integrity hash:
<script
src="https://widget.iperchat.ai/v/1.0.0/iperchat.iife.js"
integrity="sha384-…"
crossorigin="anonymous"
data-iperchat-auto-init
data-tenant-id="YOUR_TENANT_ID"
></script>
A versioned file never changes and stays available. https://widget.iperchat.ai/v/manifest.json lists every version with its integrity value. A pinned version doesn’t receive fixes or new features, so move to a newer version when you’re ready.
Load the widget only on click
This loader fetches nothing from IperChat until the visitor clicks your button. With a strict script-src, serve it as a file from your own site and give its script tag your nonce; it passes the nonce on to the widget script:
// chat-loader.js
var nonce = document.currentScript.nonce
document.getElementById('open-chat').addEventListener('click', function () {
if (window.IperChat) {
window.IperChat.open()
return
}
var script = document.createElement('script')
script.src = 'https://widget.iperchat.ai/iperchat.iife.js'
script.nonce = nonce
script.onload = function () {
window.IperChat.init({ tenant_id: 'YOUR_TENANT_ID', language: 'en' })
window.IperChat.open()
}
document.body.appendChild(script)
})
<button id="open-chat" type="button">Chat with us</button>
<script src="/chat-loader.js" nonce="{NONCE}"></script>