# ThoughtSpot and Salesforce Integration

> For the complete documentation index, see [llms.txt](https://developers.thoughtspot.com/docs/llms.txt)

Source: https://developers.thoughtspot.com/docs/sf-integration

# ThoughtSpot and Salesforce Integration

Integrating ThoughtSpot with Salesforce enables users to access analytics directly within Salesforce. By embedding ThoughtSpot content, organizations can deliver data-driven insights where their end users work, enhancing decision-making and efficiency.

This guide explores the various embedding options, including the ThoughtSpot Lightning Web Component (LWC) plugin for Salesforce, Visual Embed SDK, and non-SDK approaches, and provides key recommendations for authentication, customization/branding, and embedding in mobile apps.

## Embeddable objects

ThoughtSpot allows users to create several types of objects. You can easily embed any of the following objects into Salesforce:

-   **Search** - A self-service interface that allows users to perform searches on data and build visualizations.
    
-   **Answers** - Individual visualizations generated and saved from user search queries.
    
-   **Liveboards** - Interactive dashboards that contain one or more visualizations (Answers).
    
-   **Spotter** - An AI-powered assistant that helps users analyze data using natural language.
    
-   **Full Application** - Allows embedding the full ThoughtSpot application or the individual application pages.
    

## Embedding methods

You can embed ThoughtSpot in Salesforce using the following methods:

 
| Embedding method | Description |
| --- | --- |
| 
ThoughtSpot supported LWC Plugin

 | 

ThoughtSpot-managed Lightning Web Component (LWC) plugin for Salesforce enables seamless embedding of Liveboards and Spotter directly within Salesforce.

This is the recommended approach for most Salesforce Lightning environments.

 |
| 

Custom LWC with Visual Embed SDK

 | 

For maximum flexibility and customization, use the Visual Embed SDK within your own custom LWC. This method supports embedding all ThoughtSpot components such as Liveboards, Spotter, Search, Answers and full application experience, and allows for deep integration with Salesforce Cloud products.

 |
| 

iFrame embedding (without SDK)

 | 

For Salesforce Classic or when SDK/LWC plugin use is not possible, embed ThoughtSpot using a simple iFrame. This legacy approach is quick to implement but has limitations in authentication, event handling, and customization.

 |

## Key considerations

   
| Capability | ThoughtSpot LWC Plugin (managed package) | Custom LWC with SDK | iFrame via Visualforce/Apex |
| --- | --- | --- | --- |
| 
Setup effort

 | 

Low  

Install, drag and drop in Lightning App Builder, and configure props

 | 

Medium/High  

Build LWC, handle authentication, events, and testing

 | 

Low/Medium  

Quick to place, but manual parameter and authentication handling is required

 |
| 

Supported ThoughtSpot experiences

 | 

Liveboards and Spotter

 | 

All SDK-supported components  
(Liveboards, Spotter, Search, Answers, Full application)

 | 

Any embeddable ThoughtSpot URL

 |
| 

Record-aware context  
(for example, Account/Opportunity filters)

 | 

Built-in support  

Pass recordId/fields via properties

 | 

Yes  

Compose runtime filters from record context

 | 

Manual  

Append query parameters to iFrame URL

 |
| 

Authentication options

 | 

SSO and Cookieless Trusted authentication

 | 

All authentication methods supported, including SSO, Cookieless Trusted authentication and more)

 | 

Works with SSO only.  
Limited options

 |
| 

Salesforce Mobile app

 | 

Supported when Org authentication is configured

 | 

Recommended with Cookieless Trusted authentication

 | 

Inframe authentication limitations

 |
| 

CSP and security

 | 

Documented CSP entries; package streamlines most settings

 | 

You must manage Trusted Sites and CSP allowlists

 | 

Must allow ThoughtSpot as trusted host

 |
| 

Branding, styles, themes

 | 

Configurable via component properties  

Limited deep styling

 | 

Full control via SDK and custom CSS

 | 

Minimal  

Basic styling options for ThoughtSpot application only

 |
| 

Events and callbacks  
(For filters, drilldown, and more)

 | 

Common events exposed via component API

 | 

Full event surface; wire to Apex/Flow

 | 

None

 |
| 

Custom Actions

 | 

None

 | 

Supported

 | 

None

 |
| 

Access to ThoughtSpot REST APIs  
(Object export, metadata, Answer Service, and so on)

 | 

Limited

 | 

Available  

SDK and REST APIs supported

 | 

None

 |
| 

Time-to-production

 | 

Fastest

 | 

Moderate

 | 

Fast

 |
| 

Maintainability and upgrades

 | 

Vendor-maintained; update by package version

 | 

You own app lifecycle and SDK versioning

 | 

You own app lifecycle

 |
| 

Granular UX control

 | 

Medium

 | 

High

 | 

Low

 |

## High-level implementation steps

To embed ThoughtSpot content, complete the steps described in the following sections:

-   [Embed using ThoughtSpot supported LWC plugin]({{navprefix}}/{{sf-integration}}#_embed_spotter_or_a_liveboard_using_lwc_plugin)
    
-   [Custom LWC with Visual Embed SDK]({{navprefix}}/{{sf-integration}}#_embed_with_visual_embed_sdk)
    
-   [Use iFrame to embed]({{navprefix}}/{{sf-integration}}#_use_iframe_to_embed)
    

### Embed using ThoughtSpot LWC plugin

For information about the LWC plug-in installation and setup, see [Integration Guide](https://docs.thoughtspot.com/cloud/latest/salesforce-plugin).

### Custom LWC with Visual Embed SDK

The Salesforce lightning platform moved developers away from Visualforce to **Lightning Web Components (LWC)**. If you are considering using the SDK, we will assume your Salesforce instance is running on Lightning.

> **NOTE:** To simplify development, we recommend using the Salesforce extensions pack in Visual Studio Code.

You have a couple of options:

LWC from scratch

> **NOTE:** This guide does not cover LWC development. We will assume you have experience developing in Salesforce. If not, contact your ThoughtSpot Sales representative for details.

Any LWC you develop in Salesforce will contain an html, js, and meta.xml file. Let’s walk through a simple Liveboard embed component.

**meta.xml**  
Defines the metadata values for the component. Specifically, where you want to embed in Salesforce (Record Pages, Experience Cloud, Homepage, and more), and any configurable parameters for your ThoughtSpot objects (type of object to embed, Cluster URL, Org, and more).

```xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>63.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>ThoughtSpot Embed Template</masterLabel>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage,lightning__AppPage,lightning__HomePage,lightningCommunity__Default">
            <property label="What are you embedding?" name="embedType" type="String" datasource="Liveboard, Spotter" default="Liveboard"/>
                <property
                    name="tsURL"
                    type="String"
                    label="ThoughtSpot URL"
                    required="false"
                    description="The full URL to your ThoughtSpot host"
                    default=""
                />
                <property
                    name="tsOrg"
                    type="String"
                    label="TS Org ID - leave empty if not using orgs"
                    required="false"
                    description="ThoughtSpot Organization Identifier"
                    default=""
                />
                <property
                    name="tsObjectId"
                    type="String"
                    label="Liveboard or Datasource GUID"
                    required="false"
                    description="ThoughtSpot Content GUID"
                    default=""
                />
                <property
                    name="hideLiveboardHeader"
                    type="Boolean"
                    default="false"
                    label="Hide Liveboard Header?"
                />
                <property
                    name="showLiveboardTitle"
                    type="Boolean"
                    default="false"
                    label="Show Liveboard Title?"
                />
                <property
                    name="fullHeight"
                    type="Boolean"
                    default="false"
                    label="Full Height Liveboard?"
                />
            </targetConfig>
        </targetConfigs>
    </LightningComponentBundle>
```

**html**  
This page defines the div where your ThoughtSpot object will be embedded.

```html
<template>
    <div class="container" data-id="myContainer">
        <div class="thoughtspotObject" data-id="thoughtspotObject" id="thoughtspotObject" lwc:dom="manual"></div>
    </div>
</template>
```

**javascript**  

-   The js file will communicate with your ThoughtSpot cluster and use the Visual Embed SDK to embed your objects.
    
-   Variables set in the `meta.xml` will be tracked and applied in the SDK initialization.
    
-   You must import the Visual Embed SDK as a static resource in Salesforce. Get the latest NPM version [here](https://cdn.jsdelivr.net/npm/@thoughtspot/visual-embed-sdk/dist/tsembed.js).
    
-   Add Salesforce URL to CORS allowed-domains in ThoughtSpot.
    
-   Update CORS and CSP settings in Salesforce with your ThoughtSpot cluster URL.
    

```javascript
///////////////////////////////////////
//Prototype for TS Liveboard Embed
//
// High-level steps:
//   : Update CCORS whitelisted domains settings in ThoughtSpot (Developer -> Security). Add your Salesforce url(s)
//   : Update CORS and CSP settings in Salesforce with your thoughtspot cluster url
//   : Upload the ThoughtSpot SDK into SF as Static Resource. Make sure name matches thoughtSpotSDK import below
//   : Set values for your ThoughtSpot username & password below.
//
// Notes:
//   : Basic Auth used in this LWC, no SSO.
//   : Do not use in production
//
///////////////////////////////////////
import { LightningElement, api, track } from 'lwc';
import thoughtSpotSDK from '@salesforce/resourceUrl/thoughtSpotSDK';
import { loadScript } from 'lightning/platformResourceLoader';

export default class TsEmbedTemplate extends LightningElement {

    @api objectApiName; /** Object API name - automatically passed when in a record page */
    @api recordId;      /** Object record ID - automatically passed when in a record page */

    //track variables set in meta.xml
    @api embedType;
    @api tsObjectId;
    @api tsURL;
    @api tsOrg;
    @api hideLiveboardHeader;
    @api showLiveboardTitle;
    @api fullHeight;

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    // Basic Auth testing - use your ThoughtSpot credentials
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    myTestUser   = '';
    myTestPW     = '';
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    async connectedCallback() {
        console.log("### Loading the ThoughtSpotSDK...");
        this.loadTSSDK();
    }

    loadTSSDK() {
        loadScript(this, thoughtSpotSDK)
            .then(() => {
                // ThoughtSpot library loaded successfully
                console.log("### SDK successfully loaded...initializing embed");
                this.initSDKEmbed();
            })
            .catch(error => {
                // Error occurred while loading the ThoughtSpot library
                this.handleError(error);
            });
    }

    async initSDKEmbed() {
        const containerDiv = this.template.querySelector(
            'div.thoughtspotObject'
        );

        try {
            this.embedInit = tsembed.init({
                thoughtSpotHost: this.tsURL,
                authType: tsembed.AuthType.Basic,
                username: this.myTestUser,
                password: this.myTestPW,
                org_id: this.tsOrg,
                customizations: {
                    style: {
                        customCSSUrl: "https://cdn.jsdelivr.net/gh/thoughtspot/custom-css-demo/css-variables.css", // location of your style sheet

                        // To apply overrides for your style sheet in this init, provide variable values below
                        customCSS: {
                            variables: {
                                "--ts-var-button--secondary-background": "#9da7c2",
                                "--ts-var-button--secondary--hover-background": "#cacad5",
                                "--ts-var-button--primary--hover-background":"#cacad5",
                                "--ts-var-button--primary-background": "#9da7c2",
                                "ts-var-button--primary-color": "#9da7c2",

                                "--ts-var-root-background": "#b0c4df",
                                "--ts-var-viz-border-radius": "22px",
                                "--ts-var-viz-title-font-family": "Helvetica",
                                "--ts-var-viz-background": "#ffffff",

                                "--ts-var-menu--hover-background": "#c9c9c9",
                                "--ts-var-menu-font-family": "Helvetica",

                                "--ts-var-chip-border-radius": "8px",
                                "--ts-var-chip--active-color": "#CF112C",
                                "--ts-var-chip--active-background": "#57a3fd",
                                "--ts-var-chip--hover-color": "white",
                                "--ts-var-chip--hover-background": "#A4A4A3",
                                "--ts-var-chip-color": "#F9F6EE",
                            },
                        },
                    },
                    },
            });

            if( this.embedType === "Liveboard" ) {

                console.log('### Configuring ' + this.embedType + ' embed');
                console.log("### RECORD ID: ", this.recordId);

                this.embedObj = new tsembed.LiveboardEmbed(containerDiv, {
                    frameParams: {
                    },
                    fullHeight: this.fullHeight,
                    hideLiveboardHeader: this.hideLiveboardHeader,
                    showLiveboardTitle: this.showLiveboardTitle,
                    liveboardId: this.tsObjectId,
                });
            }
            else if(this.embedType === "Spotter") {

                console.log('### Configuring ' + this.embedType + ' embed');

                this.embedObj = new tsembed.SpotterEmbed(containerDiv, {
                    frameParams: {
                        height: 800,
                    },
                    worksheetId: this.tsObjectId,
                });
            } else {
                console.log("###ERROR: No embed type selected in meta xml");
            }

            this.embedObj.render();

            }
            catch (error) {
                console.error('Error:', error);
            }
    }

    handleError(error) {
        console.error('Error loading TS library:', error.message || error);
    }
}
```

LWC Git repository

We can provide all the code needed to get you started. Contact your ThoughtSpot Sales representative for access to our Git repositories.

### iFrame embedding

If you have configured ThoughtSpot to use the same SAML provider as your Salesforce instance, you can create a simple Visualforce page that can seamlessly embed a ThoughtSpot Object.

To create a new Visualforce page in Salesforce, go to **Setup** > **Visualforce Pages** > **New**.

The following code example can be used for the new page. It defines the iFrame, with the ThoughtSpot Liveboard URL using a runtime filter to personalize the results to the Salesforce user:

> **NOTE:** Use this code only if embedding into Salesforce Classic.

```xml
<apex:page standardController="Account" tabStyle="Account">
  <apex:pageBlock title="ThoughtSpot">
    <apex:iframe src="https://{thoughtspot-server}/?embedApp=true&p&col1={field_name}&op1=EQ&val1={!Account.Id}&OrgID={org_id}#/embed/viz/{liveboard_guid}
" scrolling="true" height="800">
    </apex:iframe>
  </apex:pageBlock>
</apex:page>
```

> **NOTE:** Variable substitution required {thoughtspot-server}. Your ThoughtSpot host URL. {field\_name} represents the column from your ThoughtSpot model to be filtered. {!account.Id} is a Salesforce APEX variable, the value is automatically known based on the record page you are embedding into. The filter values you can pass are based on the standardController= you set when configuring the apex page. {org\_id}. If using Orgs in ThoughtSpot, provide your Org identifier. If not using Orgs, set the ID to 0. {liveboard\_guid}. Your Liveboard identifier.

## SSO Options

Authentication is a critical component of embedding ThoughtSpot in Salesforce. The two primary options for this integration are:

SAML-based SSO

-   Allows users to authenticate via Salesforce’s Identity Provider (IdP).
    
-   Provides a seamless login experience without requiring additional credentials.
    
-   Requires ThoughtSpot to be configured as a service provider (SP).
    

Trusted authentication

-   Uses a secure token-based approach for authentication.
    
-   Provides more control over user access and permissions.
    
-   Ideal for embedding within customized Salesforce experiences.
    
-   Seamless embedding within the Salesforce mobile app.
    
-   Is supported in ThoughtSpot SDK embed only.
    

## Customization and branding with the SDK

The Visual Embed SDK allows extensive customization, including the following:

-   Styling the embedded Liveboards to match Salesforce’s look and feel.
    
-   Implementing filters and interactive elements.
    
-   Controlling user experience via ThoughtSpot’s developer-friendly APIs.
    

## Conclusion

Embedding ThoughtSpot into Salesforce enhances analytics accessibility, enabling users to gain insights without leaving their CRM. Whether using the ThoughtSpot LWC plugin, Visual Embed SDK or iframe-based approaches, choosing the right authentication and embedding method is essential. By leveraging LWC and customizing ThoughtSpot’s appearance, organizations can create a seamless and powerful analytics experience within Salesforce.