Everything your product, engineering, and data teams need — SDK setup, authentication, architecture, security, and CI/CD — from kickoff to production in one place.
Select your role to highlight what's most relevant for you.
Before writing a single line of code, align your team on why you're embedding, what you'll embed first, and who is responsible for each layer.
Embedded analytics brings insights into the place your users already work — your product — making analytics part of the workflow rather than a separate destination.
| Business outcome | What users experience | So what? |
|---|---|---|
| Higher adoption | Analytics is one click away inside your app | Reduce friction, increase usage without habit change |
| Faster decisions | Users ask and answer questions without tickets | Less backlog for your data team |
| Scalable governance | Central semantic layer + permissions | Add users safely without permissions chaos |
| Differentiated product | Analytics feels native and branded | Compete on experience, not just charts |
Pick the pattern that matches your desired UX control and engineering capacity. You can start focused and expand later.
Embedded analytics succeeds when product, engineering, and data teams run in parallel. Align ownership before you build.
Establish the technical building blocks before a single embed is rendered. Rushing this phase is the #1 cause of painful late-stage bugs.
ThoughtSpot connects live to your CDW. Start with one "golden" dataset for the MVP — model for analytics (star schema) rather than mirroring OLTP complexity.
Create a dedicated service role: CREATE ROLE thoughtspot_role;
Grant USAGE on warehouse, database, and schema, plus SELECT on the target tables/schema to the service role. Also grant future table privileges so new tables are automatically accessible.
Create a service user and assign the role: CREATE USER thoughtspot_svc DEFAULT_ROLE = thoughtspot_role;
Use username/password or key-pair auth in ThoughtSpot. Set DEFAULT_WAREHOUSE on the service user to avoid connection errors.
Allowlist ThoughtSpot's IP ranges in your Snowflake network policy. → Snowflake connection docs
Create a dedicated GCP Service Account in IAM (e.g. thoughtspot-svc@your-project.iam.gserviceaccount.com).
Grant BigQuery Data Viewer + BigQuery Job User roles to the service account.
Download the JSON key: IAM → Service Accounts → Keys → Add Key → JSON.
In ThoughtSpot: upload the JSON key. BigQuery connections are project-scoped — ensure the service account has access to the correct project.
Create a dedicated DB user (e.g. thoughtspot_svc) with a strong password, and grant SELECT on the target schema and tables.
Add ThoughtSpot's IP ranges to your Redshift security group inbound rules (port 5439).
Use native auth (username/password). IAM auth is not currently supported by ThoughtSpot.
For Redshift Serverless: use the serverless endpoint URL format workgroup.account.region.redshift-serverless.amazonaws.com.
Generate a personal access token in Databricks (User Settings → Developer → Access Tokens) or use service principal OAuth for production.
Use the SQL Warehouse HTTP path (not an all-purpose cluster). Find it: SQL Warehouses → your warehouse → Connection Details.
Ensure the token/principal has CAN USE permission on the target SQL Warehouse.
Grant SELECT on the target catalog/schema to the service principal.
The semantic layer is not optional — it is what makes ThoughtSpot Search and AI work reliably for your users. It turns raw tables into a trusted, business-friendly analytics surface.
Use a star schema where possible. Avoid mirroring OLTP complexity. Define your joins in ThoughtSpot's semantic layer, not in SQL.
Rename ord_rev_usd → Revenue. Users search in natural language — your column names are the vocabulary.
Add synonyms: "sales" → Revenue, "client" → Customer. The more synonyms, the better search results Spotter delivers.
Set SUM on measures (Revenue, Quantity), COUNT on IDs. Wrong defaults cause misleading AI answers.
Apply Column-Level Security tags to PII, cost, salary, and margin columns. Restrict via group-based permissions.
Before embedding, ask 5–10 representative business questions in the Playground. Fix any surprising results before users see them.
Before any embed renders, your application domain must be registered in ThoughtSpot. This is the most common cause of blank iFrames.
Add your app's domain (e.g. https://app.yourcompany.com) to the CSP allowlist. This permits ThoughtSpot to be framed in your app. Scope as tightly as possible — avoid wildcards in production.
Add the same domain to the CORS allowlist so your frontend can make REST API calls. Use .* patterns to match subdomains where needed. → CORS docs
Add your staging/dev domain first, validate fully, then add production. Check the browser console for Refused to frame or CORS errors after each change.
Install the SDK, wire up authentication, build reusable embed components, and customize the look and feel to match your product.
https://<clustername>.thoughtspot.cloud/#/develop/playground/search) to experiment with embed components, generate code snippets, and validate auth — without touching your app.
npm install @thoughtspot/visual-embed-sdk in your project, or load the ES Module CDN bundle for non-module environments — no build tooling required. Include callPrefetch: true in your init() call to prefetch resources and reduce first-render latency. → Full SDK Quickstart docs
Trusted Authentication is the recommended pattern for all embedded deployments. It uses a short-lived token exchange — no ThoughtSpot credentials are ever exposed to end users.
Your existing IdP/SSO authenticates the user. Your app now has a verified user identity (e.g. email).
The SDK's getAuthToken callback fires. Your frontend requests a token from your own backend — never from ThoughtSpot directly.
Your backend uses the secret_key (stored server-side only, never in client code) to call POST /api/rest/2.0/auth/token/custom and get a short-lived token.
Token TTL: 300–3600 seconds. The SDK automatically calls getAuthToken again on expiry — no manual refresh needed.
The token is passed into init() via getAuthToken. ThoughtSpot authenticates the session and the embed renders.
Navigate to Develop → Customizations → Security Settings. Enable Trusted Authentication and copy the secret_key. Store it in your backend secrets manager — never in client code or environment files committed to git.
Create a server-side endpoint (e.g. POST /api/ts-token) that receives your verified app user's identity, calls POST /api/rest/2.0/auth/token/custom with the secret_key, and returns only the token to the frontend. Set auto_create: true for Just-in-Time user provisioning. Recommended TTL: 300–3600 seconds.
init() on the frontendCall init() once per session before any embed renders. Set authType to TrustedAuthTokenCookieless and provide an async getAuthToken callback that calls your backend endpoint and returns the token string. Set autoLogin: true in production to ensure automatic token refreshes without user interruption — this is strongly recommended for cookieless auth deployments.
getAuthToken callback should return the cached token unless it has expired.
TrustedAuthToken) breaks silently in modern browsers due to SameSite=Lax enforcement. Cookieless mode eliminates this dependency entirely and supports multiple concurrent sessions per browser.
Don't copy/paste embed code across pages. Build one parameterized component that handles initialization, auth, filters, events, and error states.
The component should accept liveboardId, runtimeFilters, and display config as inputs. This lets you reuse one component across every page with different content.
Pass the current user's context (tenant ID, region, account) as runtime filter values scoping the Liveboard without rebuilding the content or creating per-user duplicates.
Remove default ThoughtSpot actions that don't belong in an embedded context — typically: Download, Share, Schedule, and Edit. Configure via the hiddenActions parameter.
Subscribe to EmbedEvent.Load to measure time-to-first-render and drive UX transitions. Subscribe to EmbedEvent.Error to show a meaningful fallback state instead of a silent blank iFrame.
Control what users can do inside the embed. Suppress ThoughtSpot's default actions to keep the UX clean, or add your own custom actions that fire events back into your app.
Remove buttons like "Download", "Share", "Schedule", and "Edit" from the embedded context. Configure via hiddenActions or disabledActions in your embed component init. Validate after every SDK upgrade — hidden actions can reappear on platform updates. → Actions reference
Register callback custom actions in Develop → Customizations → Custom Actions. They appear as menu items inside ThoughtSpot content and fire EmbedEvent.CustomAction with the data payload — handle the event in your app to connect analytics to any downstream workflow. Test across all relevant Liveboards and user personas. → Custom Actions docs
Think about what operational capabilities your users need alongside the data. Custom actions let users act on insights directly — "Open in CRM", "Create a Task", "Escalate Issue" — turning analytics from passive reporting into a workflow trigger. This is one of the highest-value differentiators of an embedded deployment.
The SDK is framework-agnostic, but framework lifecycle management determines whether your embed is stable or leaks memory and sessions.
Centralise init(), auth, parameters, events, and error handling in a single component. Never scatter embed code across pages — it creates impossible-to-debug session conflicts.
Destroy the embed instance on component unmount to avoid memory leaks and duplicate sessions. In React: call embed.destroy() in your useEffect cleanup return. In Angular: call it in ngOnDestroy. Re-initialize when route-level props like liveboardId or filters change. → React integration guide
Never hardcode ThoughtSpot host URLs, Liveboard GUIDs, or feature flags. Use environment variables (.env / config service) so Dev, QA, and Prod differ only by config — not code changes.
Make ThoughtSpot feel native to your product. CSS variables are the most stable approach — they survive SDK and platform upgrades.
init() call. Use custom CSS variables for anything beyond what Theme Builder covers.
customizations.style.customCSS.variables object within your init() call — or point to a hosted CSS file via customizations.style.customCSSUrl. For advanced overrides not covered by variables, use rules_UNSTABLE sparingly and validate after each platform upgrade. → Custom CSS docs · All CSS variables reference
| Element | CSS Variable |
|---|---|
| Page background | --ts-var-root-background |
| Text color | --ts-var-root-color |
| Primary button | --ts-var-button--primary-background |
| Font family | --ts-var-font-family |
| Nav/header background | --ts-var-nav-background |
| Custom icon set | customizations.iconSpriteUrl |
| Rename UI strings | customizations.content |
A technically successful embed that nobody uses — or that leaks data — is still a failure. Validate security, performance, and UX before go-live.
If you serve multiple customers, pick your isolation model on day one. Changing it later is expensive.
One ThoughtSpot environment. Tenant isolation enforced by Row-Level Security rules tied to user attributes. Best when tenants share similar schemas.
Tenants are segmented into separate ThoughtSpot Orgs (optionally with RLS within each org). Higher isolation requirements.
Separate ThoughtSpot instances per tenant. For regulatory, contractual, or security requirements that prohibit any shared infrastructure.
tenant_id. Fail closed: if tenant context is missing or ambiguous, do not render the embed. Test "Tenant A cannot see Tenant B" across every persona before go-live.
Call init() once, not on every page navigation. Use lazy loading for embeds below the fold. Track load time with EmbedEvent.Load.
Break large Liveboards (10+ charts) into focused, tabbed sub-Liveboards. Use Liveboard snapshot API to pre-warm cache before peak windows.
Use clustering keys, pre-aggregated tables for frequently accessed metrics, and CDW auto-scaling for peak concurrency. Review ThoughtSpot's query history in CDW.
Validate CDW warehouse sizing, ThoughtSpot query queue behavior, and SDK load. Stress test before go-live, not after.
Check the browser console first. 90% of embed issues have a visible error message.
Root cause: Your application domain is not in ThoughtSpot's CSP Visual Embed Hosts allowlist.
https://app.yourcompany.com). Avoid wildcards in production.Root cause: Your application domain is not in the CORS allowlist.
.* patterns to match subdomains. See the CORS docs for full pattern syntax.Root cause: Browser enforces SameSite=Lax by default, blocking cross-origin cookies set by ThoughtSpot inside your iFrame.
AuthType.TrustedAuthToken to AuthType.TrustedAuthTokenCookieless. This eliminates the cookie dependency entirely and is the recommended production mode.Root cause: Token expired, wrong username, or Trusted Authentication is not enabled.
getAuthToken function returns a valid token string. Confirm the username in the token matches an existing (or JIT-creatable) ThoughtSpot user.Root cause: RLS rule filters out all rows for the authenticated user — often because the user attribute value doesn't match any rows.
Root cause: SDK init() was not called before the embed component was rendered, or the container element does not exist in the DOM yet.
init() is called and awaited before constructing any embed component. Confirm the container element (document.getElementById('ts-embed')) exists at the time of render.Launch is the start line, not the finish line. Use this checklist as your final Go/No-Go gate, then build for adoption.
A technically successful embed that nobody uses is still a failure. Launch is the start line — plan for adoption from day one.
| Metric | Where to find it | What it tells you |
|---|---|---|
| Weekly Active Users (WAU) | ThoughtSpot Admin → User activity | Overall adoption health |
| Most-used Liveboards | ThoughtSpot Admin → Monitoring | What content is actually valuable |
| Failed / unanswered searches | ThoughtSpot Admin → Search activity | Gaps in your Model — add synonyms or columns |
| Liveboard load time P95 | ThoughtSpot Admin → Performance + SDK EmbedEvent.Load | Performance issues before users complain |
| Auth error rate | Your backend logs + SDK EmbedEvent.Error | Token issues, session problems |
| Tenant-level usage | Custom dashboard on ThoughtSpot activity data | Which customers are engaged vs at-risk |
Create a short in-app guide or "getting started" flow for end users. Link to ThoughtSpot U. The teams with the highest adoption invest in user education, not just engineering.
Add a "Was this helpful?" widget or a "Report an issue" link inside your embedded product. Collect qualitative feedback weekly in the first 8 weeks post-launch.
Assign a named owner for: embed bugs, data model issues, user provisioning failures, and performance incidents. Unclear ownership means slow resolution and churn.
ThoughtSpot's REST API v2.0 is the backbone of scalable operations — automate user provisioning, content promotion, token management, and usage reporting programmatically.
| Capability | Key endpoint(s) | Common use case |
|---|---|---|
| Auth token generation | POST /api/rest/2.0/auth/token/custom | Backend token endpoint for Trusted Auth (create user session) |
| Auth token with variable values (ABAC) for RLS | POST /api/rest/2.0/auth/token/custom | Per-user ABAC using variable values (formula variables) in JWT. Variable values are optional — used for applying row-level security rules. → ABAC via RLS variables docs |
| User management | /api/rest/2.0/users | Create, update, deactivate users programmatically (bulk onboarding) |
| Group management | /api/rest/2.0/groups | Map tenant roles to ThoughtSpot groups; assign RLS rules |
| TML export | POST /api/rest/2.0/metadata/tml/export | Extract Models and Liveboards for version control |
| TML import | POST /api/rest/2.0/metadata/tml/import | Deploy content to QA/Prod in CI/CD pipeline |
| Search data | POST /api/rest/2.0/searchdata | Programmatic data queries — power custom UI without an iFrame |
| Liveboard snapshot | POST /api/rest/2.0/report/liveboard | Export Liveboard as PDF/PNG for scheduled email digests |
| Connection management | /api/rest/2.0/connections | Create/update CDW connections programmatically per tenant |
token/customThe token/custom endpoint is the standard way to pass per-user data context — use formula variables and variable values inside the JWT to scope data without managing RLS rules in ThoughtSpot.
Create formula variables in your ThoughtSpot Model (e.g. current_tenant, fiscal_year). These become the injection points for per-user context passed via the token.
Use the variable_values field in your POST /api/rest/2.0/auth/token/custom request to inject runtime values for each user — e.g. their tenant ID, region, or role. ThoughtSpot applies these as filters at query time.
parameter_values for worksheet parametersPass dynamic parameter values (e.g. current fiscal quarter, selected currency) to pre-populate worksheet parameters without user interaction — keeping the embed context-aware on every load.
Never use a personal admin account for automated REST API calls. Create a dedicated ThoughtSpot service account with the minimum required privileges. Store credentials in a secrets manager, not environment files committed to git.
ThoughtSpot's API enforces rate limits on high-volume operations (bulk user creates, TML imports). Implement exponential backoff with retry logic for bulk operations. Review rate limit docs before automating at scale.
Use tml/export + tml/import in your CI/CD pipeline to promote Models and Liveboards across environments. Replace environment-specific GUIDs with portable identifiers. Validate TML syntax in the lint stage before promoting.
Everything you need bookmarked in one place.
Step-by-step guide to installing and initializing the Visual Embed SDK.
⭐ Start here developers.thoughtspot.com →Experiment with all embed types, generate code snippets, and preview CSS changes live — no account needed.
⭐ Start here Open Playground →Interactive API explorer for users, groups, TML import/export, auth tokens, and search data.
REST API docs →Self-paced eLearning: Getting Started with ThoughtSpot Embedded. Free for customers.
⭐ Start here training.thoughtspot.com →Ask questions, share solutions, and connect with other ThoughtSpot developers.
community.thoughtspot.com →Full working React demo with LiveboardEmbed, auth flow, and runtime filters. Fork and adapt.
Open in CodeSandbox →Complete list of all supported ThoughtSpot CSS variables for branding and customization.
GitHub →Track SDK version history, breaking changes, and compatibility with cluster releases. Review before every upgrade.
SDK changelog → CommunityJoin the ThoughtSpot developer community on Discord. Ask questions, share solutions, and connect with other engineers building on the platform.
Join Discord → NewConnect Cursor, VS Code, or Claude Code to ThoughtSpot's MCP server for context-aware embed code generation and live SDK docs in your IDE.
SpotterCode docs →Reach your ThoughtSpot CSM or open a support ticket. New customers: your CSM is your first point of contact for licensing, access, and onboarding questions.
support.thoughtspot.com →