Если на сайте уже есть CSP, браузер запретит всё, чего нет в списке. Виджет грузит скрипт с https://staging-cdn.sapportly.pro, ходит в API https://staging-api.sapportly.pro, открывает WebSocket wss://staging-ws.sapportly.pro и скачивает WASM с CDN. Без этих источников чат не откроется: в консоли — Refused to load the script / connect-src.
На проде Sapportly это https://cdn.sapportly.pro, https://api.sapportly.pro и wss://ws.sapportly.pro. Сниппет в панели собран из ваших текущих URL.
Минимум директив
script-src — JS-шелл. 'wasm-unsafe-eval' — ядро WASM после открытия чата. connect-src — bootstrap, живой канал и fetch .wasm с CDN. Site ID (wgt_…) публичный, ключ API в браузер не кладётся.
Content-Security-Policy: script-src 'self' https://staging-cdn.sapportly.pro 'wasm-unsafe-eval'; connect-src 'self' https://staging-api.sapportly.pro wss://staging-ws.sapportly.pro https://staging-cdn.sapportly.pro; frame-ancestors 'self'
Referrer-Policy: strict-origin-when-cross-originКак поставить на фреймворк
<head>
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self' https://staging-cdn.sapportly.pro 'wasm-unsafe-eval'; connect-src 'self' https://staging-api.sapportly.pro wss://staging-ws.sapportly.pro https://staging-cdn.sapportly.pro; frame-ancestors 'self'"
/>
</head>/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "Content-Security-Policy",
value: "script-src 'self' https://staging-cdn.sapportly.pro 'wasm-unsafe-eval'; connect-src 'self' https://staging-api.sapportly.pro wss://staging-ws.sapportly.pro https://staging-cdn.sapportly.pro; frame-ancestors 'self'",
},
],
},
];
},
};
module.exports = nextConfig;add_header Content-Security-Policy "script-src 'self' https://staging-cdn.sapportly.pro 'wasm-unsafe-eval'; connect-src 'self' https://staging-api.sapportly.pro wss://staging-ws.sapportly.pro https://staging-cdn.sapportly.pro; frame-ancestors 'self'" always;header Content-Security-Policy "script-src 'self' https://staging-cdn.sapportly.pro 'wasm-unsafe-eval'; connect-src 'self' https://staging-api.sapportly.pro wss://staging-ws.sapportly.pro https://staging-cdn.sapportly.pro; frame-ancestors 'self'"Cloudflare
Rules → Transform / HTTP Response Header Modification: добавьте заголовок Content-Security-Policy. Если правило перезаписывает существующий CSP, сначала скопируйте текущий и допишите источники Sapportly. Готовый «Security Headers» шаблон часто ломает виджет.
Vite и любые SPA
Dev-сервер Vite CSP не отдаёт. На проде заголовок ставит хостинг: Nginx, Caddy, Cloudflare Pages, Vercel (headers в vercel.json). Meta в index.html — запасной путь, если нет доступа к HTTP-заголовкам.
Vue / Nuxt / SvelteKit
- Nuxt:
nuxt.config→routeRules/nitro.routeRules, заголовокContent-Security-Policy. - SvelteKit:
hooks.server.ts—event.setHeadersс тем же значением, либо заголовок на адаптере/платформе.
Конструкторы
Tilda: Настройки сайта → ещё → HTML-код для head — meta CSP, либо заголовок на Cloudflare/прокси перед Tilda. Сниппет виджета — перед </body> или через блок HTML.
WordPress: плагин HTTP-заголовков / Security, либо директива сервера (Header set Content-Security-Policy / Nginx add_header). Тема CSP сама не подключает. Сниппет — в footer или через плагин вставок.
Telegram, Tilda и WordPress как готовые каналы — в панели раздел Интеграции, не через CSP.
Проверка
- DevTools → Console: нет ошибок CSP на
sapportly.widget.jsи bootstrap. - Network:
POST …/v1/widget/bootstrapне 403 из‑за Origin (это allowlist в панели, не CSP). - Панель → Виджет → Подключение: чипы «Сайт» / «Скрипт» после сохранения origin.
Разрешённые origins в панели CSP не заменяют: нужны оба. Установка виджета — гайд по виджету.