If the console says an ancestor violates frame-ancestors, the analytics service doesn't list your app's domain as allowed to frame it. In ThoughtSpot, add the domain to CSP visual embed hosts and CORS whitelisted domains under Develop > Customizations > Security settings, then reload. You need admin or developer privileges, and from ThoughtSpot Cloud 26.2.0.cl you can script both lists with the REST API.
For SaaS applications using an embedded analytics tool, configuring these security settings correctly helps ensure that customer-facing analytics experiences remain accessible without compromising application security.
Checked against the ThoughtSpot Cloud 26.10.0.cl documentation and Chromium 141, October 2026.
Content Security Policy (CSP) frame-ancestors tells the browser which sites may show a page in an iframe, and CORS controls which sites may call its APIs from the browser. ThoughtSpot keeps an allowlist for each, CSP visual embed hosts and CORS whitelisted domains, under Develop > Customizations > Security settings.
What should you check when you compare tools?
ThoughtSpot sends a frame-ancestors header, which "specifies valid parents that may embed a page" (MDN). Admins and developers control which domains can frame ThoughtSpot and call its APIs, CORS can differ per Org (ThoughtSpot's term for a tenant), and both lists can be set through the REST API.
Ask any vendor:
Who decides which domains can frame the analytics, and can I script it?
Can each customer's tenant have its own API allowlist?
What, if anything, do I change in my own app's Content Security Policy?
What does the error look like?
The iframe stays blank, and Chrome's console shows:
Refused to frame 'https://<your-instance>.thoughtspot.cloud/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors ...".ThoughtSpot's troubleshooting page lists a shortened form of this error. If the CORS list is the gap, ThoughtSpot API calls from your page fail instead, with a console error that includes "has been blocked by CORS policy".
Why does it happen?
Every embed is an iframe pointed at your ThoughtSpot instance. Two allowlists control it:
|
Setting |
What it controls |
If your domain is missing |
|
CSP visual embed hosts |
Which sites may frame ThoughtSpot (the frame-ancestors header) |
"Refused to frame" |
|
CORS whitelisted domains |
Which origins may call ThoughtSpot's APIs |
CORS errors on API calls |
You usually need both: the iframe needs the CSP list, and the Visual Embed SDK's calls to ThoughtSpot's APIs need the CORS list.
How do I fix it?
1. Open the settings. Go to Develop > Customizations > Security settings and click Edit. You need admin or developer privileges. ThoughtSpot adds: "Only users with a valid embed license can add Visual Embed hosts." With Orgs, use the All Orgs tab: CSP is set for the whole instance.
2. Add your domain to both lists, then save. The formats differ (format rules):
|
You want |
CSP visual embed hosts |
CORS whitelisted domains |
|
One HTTPS domain |
app.example.com |
app.example.com |
|
Every subdomain |
*.example.com |
.*\.example.com (escape the dot) |
|
A non-standard port |
app.example.com:8080 |
app.example.com:8080 |
|
Local development |
https://localhost:3000 |
https://localhost:3000 |
Use a subdomain wildcard only if you control every subdomain. Separate entries with commas. Remove localhost in production.
3. Or script it (ThoughtSpot Cloud 26.2.0.cl+). Save the current settings, then write back the complete lists with your domain added:
# 1. Save the current settings
curl -X POST 'https://<TS_HOST>/api/rest/2.0/system/security-settings/search' \
-H 'Authorization: Bearer <ADMIN_TOKEN>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
--data-raw '{ "scope": "CLUSTER" }' > security-settings-backup.json
# 2. Write back the full lists: every existing entry, plus your domain
curl -X POST 'https://<TS_HOST>/api/rest/2.0/system/security-settings/configure' \
-H 'Authorization: Bearer <ADMIN_TOKEN>' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
--data-raw '{
"cluster_preferences": {
"cors_whitelisted_urls": ["<EXISTING_ENTRY_1>", "<EXISTING_ENTRY_2>", "app.example.com"],
"csp_settings": {
"visual_embed_hosts": ["<EXISTING_HOST_1>", "<EXISTING_HOST_2>", "app.example.com"]
}
}
}'In JSON, escape the backslash in a CORS pattern: ".*\\.example.com". SpotterCode in your IDE, on the authenticated endpoint, can also add the domain for you. It acts as the signed-in user, who needs the same admin or developer privileges.
How do I check it worked?
Reload with DevTools open and the cache disabled. The error is gone, the dashboard renders, and the Network tab shows no CORS errors. In the Network tab, the iframe's Content-Security-Policy response header should list your domain under frame-ancestors.
Still failing?
CORS errors on API calls. The domain is on the CSP list only, or you used *.example.com in CORS. Use .*\.example.com there.
Works in one Org, not another. Org settings win: "When security settings are defined at both levels, the Org-level settings take precedence" (security settings for Orgs). Add the domain to that Org's CORS list, in the UI or with org_preferences in the configure call.
The message says "it violates", not "an ancestor violates". Your own app's Content Security Policy is blocking ThoughtSpot. Chrome names the directive: frame-src, or default-src if frame-src isn't set. Add your ThoughtSpot host to frame-src.
The embed works in Chrome but not in Safari. That's third-party cookies, not CSP: "Many web browsers block third-party cookies (Safari, Edge, mobile browsers)" (trusted auth in the SDK). Use cookieless trusted authentication.
When evaluating an iframe alternative, also consider whether the solution provides flexible domain allowlisting and secure embedding capabilities for applications that need to deliver analytics directly to their users.
How do I explain this to my team?
|
Who |
What they'll ask |
What you can tell them |
|
Security |
Can another site frame our analytics? |
No. ThoughtSpot only allows framing from domains on our allowlist, and only users with admin or developer privileges can change it. |
|
Engineering lead |
Can this go in our deployment scripts? |
Yes (ThoughtSpot Cloud 26.2.0.cl+). A script reads the current settings and writes back both lists. |
As the embedded analytics market evolves, configurable security controls and domain-level access management are important considerations when scaling analytics across customer applications.
How can I try this before I commit?
Start a free ThoughtSpot Embedded trial.




