If your embedded Skinny widget isn’t appearing and there are no obvious JavaScript errors, the most common cause is your site’s Content Security Policy (CSP) blocking the widget script or API calls.
CSP is a browser security policy sent by your server that limits which scripts, network requests, images, etc., are allowed to load. If a domain isn’t allowlisted in the policy, the browser will refuse the request and you’ll see an error like “Refused to load the script … because it violates the following Content Security Policy directive…”.
/faq/index.html
), and inspect Response Headers for Content-Security-Policy
.You need to allow:
https://theskinnyai.com
in script-src
(to load the widget script)https://theskinnyai.com
in connect-src
(to call the function-path endpoint)Pick one approach (both work):
[build]
publish = "public"
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://theskinnyai.com; connect-src 'self' https://theskinnyai.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'self';"
/*
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://theskinnyai.com; connect-src 'self' https://theskinnyai.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'self';
After updating, redeploy (or restart Netlify Dev) and verify the Response Headers include the new domains.
netlify dev
after changes.netlify.toml
headers are more reliable than _headers
in dev.chatbot-widget.js
into public/
and use src="/chatbot-widget.js"
.<script src="https://theskinnyai.com/chatbot-widget.js"
data-api-endpoint="https://theskinnyai.com/.netlify/functions/proxy-fns/chat-complete"
data-api-key="YOUR_PUBLIC_API_KEY"
data-tenant-id="YOUR_TENANT_ID"
data-theme="dark"
data-name="Ask Skinny"
data-fill-color="#0d6efd"
data-text-color="#ffffff"
data-position="bottom-right"></script>
Once the CSP is updated, the Skinny button should appear and network requests should succeed.