# Content Security Policy

> The origins to allow if your website enforces a Content Security Policy, and the iframe embed for sites that can't loosen theirs.

Most websites don't send a Content Security Policy (CSP), and the widget loads without any change. If your site enforces one, allow the Giov origins, as you would for any third-party widget.

## Giov origins

| Name | Origin | Serves |
|---|---|---|
| Widget | `https://widget.giovchat.app` | The loader, the widget script, stylesheet and font, and the iframe embed |
| API | `https://api.giovchat.app` | Widget configuration, conversations and the realtime connection; files uploaded before the media host existed |
| Media | `https://media.giovchat.app` | Avatars and attachments |

## Script embed

This is the standard install: the loader script, with the chat rendered in your page.

| Directive | Add | Why |
|---|---|---|
| `script-src` | Widget | Loader and widget bundle |
| `style-src` | Widget | Widget stylesheet |
| `font-src` | Widget | Font served with the widget |
| `connect-src` | Widget, API, and the `wss://` form of both | Configuration, conversation API and WebSocket |
| `img-src` | Media, API, Widget and `data:` | Avatars, attachments and brand assets. `data:` is for the blurred previews shown while chat images load. Add `https:` if link previews should show images. |
| `media-src` | Media, API | Voice notes and audio attachments |
| `frame-src` | Widget | Only for Giov Copilot or the iframe embed |

Example:

```text title="Content-Security-Policy"
script-src 'self' https://widget.giovchat.app;
style-src 'self' https://widget.giovchat.app;
font-src 'self' https://widget.giovchat.app;
connect-src 'self' https://widget.giovchat.app wss://widget.giovchat.app https://api.giovchat.app wss://api.giovchat.app;
img-src 'self' data: https://api.giovchat.app https://media.giovchat.app https://widget.giovchat.app;
media-src 'self' https://api.giovchat.app https://media.giovchat.app;
```

Merge these sources into your existing directives rather than replacing them.

## Voice input

If you turned on [voice input](/docs/widget/customize#voice-input), the widget streams audio to the API over a secure WebSocket and records with the visitor's microphone:

| Header | Add | Why |
|---|---|---|
| `connect-src` | `wss://api.giovchat.app`, already in the example above | The voice connection |
| `script-src` | Widget, already allowed; `blob:` is optional | The voice module, loaded on the first tap of the microphone. `blob:` lets the audio encoder run off the main thread; without it the widget encodes on the main thread. |
| `Permissions-Policy` | `microphone=(self)` | Only if your site sends this header. With `microphone=()`, visitors see a message that the microphone is blocked. |

```text title="Permissions-Policy"
Permissions-Policy: microphone=(self)
```

With the [iframe embed](#iframe-embed), give the iframe microphone access with `allow="microphone"`, and allow the widget origin in your `Permissions-Policy`: `microphone=(self "https://widget.giovchat.app")`.

> [!NOTE]
> If you allow-listed the widget before the media host was introduced, add `https://media.giovchat.app` to `img-src` and `media-src`. Otherwise avatars and attachments uploaded since then won't display.

## Identity script

If you pass a signed-in user with `window.GiovChatSettings`, that inline `<script>` must be allowed by your `script-src`, with a nonce or a hash. Sites that forbid inline scripts can set the same object from an external script file that loads before the loader. See [Identify visitors](/docs/widget/identify-visitors).

## Iframe embed

If you can't loosen your script or style policy, embed Giov's hosted chat page in an iframe instead:

```text title="Embed URL"
https://widget.giovchat.app/embed/YOUR_WORKSPACE_ID
```

Your site then needs only:

```text title="Content-Security-Policy"
frame-src https://widget.giovchat.app;
```

Everything else runs inside the iframe under Giov's own policy. Give the iframe the size you want the chat to use:

```html title="support.html"
<iframe
  src="https://widget.giovchat.app/embed/YOUR_WORKSPACE_ID"
  title="Chat with us"
  allow="microphone"
  style="width: 400px; height: 640px; border: 0"
></iframe>
```

- Once you register websites under **Settings → Chat widget → Authorizations**, only those sites can frame the embed. With no websites registered, any site can.
- The embed doesn't receive `window.GiovChatSettings`, so visitors in it are anonymous.
- `allow="microphone"` is only needed for [voice input](#voice-input).
