LLMs.txt: Complete documentation index for AI agents
Prerender components

Prerender components

ThoughtSpot is a web app, and like any modern web application, it requires two main things to function:

  • Assets - The static files your browser needs to display and run the application, such as JavaScript files, CSS files, fonts, and images.

  • API Calls: These are network requests made from the browser to the ThoughtSpot backend to fetch:

    • Data (the actual analytics, tables, charts, and more)

    • Metadata (information about users, tables, permissions, and more)

web app

When you embed ThoughtSpot into your application, the browser must first download all required assets. Once these assets are loaded, the application executes its JavaScript code, which then initiates API calls to fetch the data and metadata necessary to render analytics for the user.

How ThoughtSpot optimizes asset and API loadingđź”—

ThoughtSpot internally optimizes the loading process by splitting assets and API calls, so that only the files and data needed for a specific component are loaded when required. This means:

  • For embed components such as Search, Liveboard, and Spotter, only the assets and API calls required for that component are loaded.

  • There are a few common assets such as fonts, shared JavaScript, CSS, and common API calls to fetch user information, that are always loaded, as they are used across all embed types.

  • In addition to these common resources, each component (for example, Liveboard) will load its own specific JavaScript and CSS, and make only the API calls needed for that component.

asset split

For example, if you are embedding a Liveboard:

  1. The browser first loads the common assets and makes common API calls for resources such as fonts and user information.

  2. Then, it loads the Liveboard-specific JavaScript and CSS files, and makes the necessary API calls to fetch Liveboard data.

  3. Assets and API calls for other components, such as Search or Spotter, are not loaded unless those components are used.

This approach ensures that the embed is efficient, loading only what is necessary for the user’s current experience, and helps improve performance by reducing unnecessary downloads and network requests.

Before getting started with pre-rendering, let’s understand the essential first step in embedding ThoughtSpot.

init callđź”—

In ThoughtSpot embedding, init is the first essential step. Before you can render any ThoughtSpot embed component, you must call the init method from the Visual Embed SDK. This function initializes the SDK and sets up the connection to your ThoughtSpot instance. It is the required starting point for any embedding scenario.

When should you call init?đź”—

Call init as early as possible in your application lifecycle, ideally on your app’s initial load, landing page, or loading screen.

The init call is very lightweight; it does not trigger heavy asset downloads or make many API calls. Therefore, there is no downside to calling it early, and it ensures that subsequent embed loads are as fast as possible.

init flow
Note

Always call init before rendering any embed component, and do so as soon as your app loads.

Pre-rendering overviewđź”—

Now that you know how ThoughtSpot loads assets and data, let’s explore how you can make the experience even faster for your users.

Consider the scenario, where you have an app with a landing screen where users spend some time before navigating to the embedded ThoughtSpot page. In the current setup, ThoughtSpot only starts loading when the user visits the analytics page. What if you could start loading some of ThoughtSpot’s essential files and data while users are still on the landing screen, before they reach the analytics page?

That’s exactly what pre-rendering does! By starting the load process early, you can make the analytics appear much faster when the user finally navigates to that page.

pre rendering basic

Terminology used in this guideđź”—

Keeping the above in mind, let’s define a few key terms that we’ll use later in this guide:

  • Common asset download: The shared JavaScript and CSS files that every embed needs

  • Common API calls: The basic API requests made for things like user info, used by all embed types

  • Embed level asset download: The specific files (like JS and CSS) needed only for the embed type you’re using (for example, Liveboard or Search)

  • Embed API calls: The API requests made to fetch the actual data and content for the specific embed (like loading a Liveboard’s data)

  • Host app: This is your web application (the main app your users interact with)

  • Analytics page: This is a page in your web app where ThoughtSpot is embedded

How to use pre-rendering?đź”—

Based on your use case, you can choose to pre-render the embed in one of the following ways:

Pre-render with Liveboard IDđź”—

In this approach, you load everything all at once. When the user navigates to the analytics page, the embed is already loaded and ready to show.

  • Fully loads the embed iframe, including all assets and Liveboard data, as soon as the component is rendered.

  • Fastest experience for a specific Liveboard.

  • Maximum resource usage if the end user never views the embed.

dig3 pre with livid

Implementationđź”—

In your application’s home page, loading page, or landing page, you need to pre-render the embed with the Liveboard ID.

// React
<PreRenderedLiveboardEmbed
  liveboardId="e40c0727-01e6-49db-bb2f-5aa19661477b"
  preRenderConfig={{
    id: 'pre-render-with-liveboard-id',
  }}
/>

OR

// JavaScript
import { LiveboardEmbed } from '@thoughtspot/visual-embed-sdk';

const embed = new LiveboardEmbed({
  liveboardId: 'e40c0727-01e6-49db-bb2f-5aa19661477b',
  preRenderConfig: {
    id: 'pre-render-with-liveboard-id',
  },
});

embed.preRender();

When you want to show the Liveboard, call this component:

// React
<LiveboardEmbed
  liveboardId="e40c0727-01e6-49db-bb2f-5aa19661477b"
  preRenderConfig={{
    id: 'pre-render-with-liveboard-id',
  }}
/>

OR

// JavaScript
import { LiveboardEmbed } from '@thoughtspot/visual-embed-sdk';

const embed = new LiveboardEmbed({
  liveboardId: 'e40c0727-01e6-49db-bb2f-5aa19661477b',
  preRenderConfig: {
    id: 'pre-render-with-liveboard-id',
  },
});

embed.render();
Note

Starting from Visual Embed SDK 1.52.0, the top-level pre-render properties are deprecated. Use the preRenderConfig object instead:

  • preRenderId → preRenderConfig.id

  • preRenderContainer → preRenderConfig.containerSelector

  • doNotTrackPreRenderSize → preRenderConfig.doNotTrackSize

This approach is the fastest way to load the embed, but it is also the most resource-intensive. The SDK makes calls to the ThoughtSpot API to fetch the Liveboard data and metadata, which might be unwanted if the end user never views the embed.

Mount the pre-rendered embed in a specific containerđź”—

By default, the SDK attaches pre-rendered iframes as child components of the document body. The containerSelector property in preRenderConfig tells the SDK which element on your page to mount the pre-rendered embed inside instead.

This is useful when the browser window itself does not scroll, but an inner container does. Mounting the pre-rendered embed inside the scrolling container ensures the embed positions and sizes itself correctly within your application’s layout.

For example, if the window does not scroll, #app-scroll does, and the embed element sits inside it:

<div id="app-scroll">
  <div id="tsEmbed"></div>
</div>

Set containerSelector to the scrolling container:

const embed = new LiveboardEmbed('#tsEmbed', {
  liveboardId: '<liveboard-guid>',
  preRenderConfig: {
    id: 'my-liveboard',
    containerSelector: '#app-scroll',
  },
});

// Warm the Liveboard up front, for example on your landing page.
await embed.preRender();

// Reveal it when the user navigates to the page that shows it.
embed.showPreRender();

In React, set containerSelector on the PreRendered component, the component that creates the pre-render:

<PreRenderedLiveboardEmbed
  liveboardId="<liveboard-guid>"
  preRenderConfig={{ id: 'my-liveboard', containerSelector: '#app-scroll' }}
/>

Pre-render without the Liveboard IDđź”—

In this approach, you load the common assets and common API calls early, but you defer the Liveboard-specific data/API calls until needed.

  • Loads common assets and bootstrap logic early.

  • Defers Liveboard-specific data/API calls until needed.

  • Keeps the app ready, making the first Liveboard load faster.

  • Still loads some assets even if the end user never opens the embed.

dig4 wo livid

To use this strategy, place the following component on your application’s home page, loading page, or landing page (before the end user navigates to the analytics):

<PreRenderedLiveboardEmbed
  preRenderConfig={{
    id: 'pre-render-without-liveboard-id',
  }}
/>

OR

// JavaScript
import { LiveboardEmbed } from '@thoughtspot/visual-embed-sdk';

const embed = new LiveboardEmbed({
  preRenderConfig: {
    id: 'pre-render-without-liveboard-id',
  },
});

embed.preRender();

When you want to show the Liveboard, call this component:

<LiveboardEmbed
  preRenderConfig={{
    id: 'pre-render-without-liveboard-id',
  }}
  liveboardId="e40c0727-01e6-49db-bb2f-5aa19661477b"
/>

OR

// JavaScript
import { LiveboardEmbed } from '@thoughtspot/visual-embed-sdk';

const embed = new LiveboardEmbed({
  preRenderConfig: {
    id: 'pre-render-without-liveboard-id',
  },
  liveboardId: 'e40c0727-01e6-49db-bb2f-5aa19661477b',
});

embed.render();

This approach is more efficient than the previous one, but it does not load the Liveboard data and metadata until the end user navigates to the analytics page. So users might see a loading state for a few seconds before the Liveboard is loaded.

Pre-render on demandđź”—

If you do not want your host app to fetch any ThoughtSpot resources during its initial load, pre-rendering on demand is ideal.

In this mode, nothing is fetched until you render the embed. On the first render, all required assets and data are loaded. The iframe is then kept alive in the browser, so subsequent renders with the same prerender ID are instant because the existing iframe is reused.

  • Loads nothing up front; the embed is created only when the end user navigates to it.

  • First visit loads normally; subsequent visits with the same prerender ID reuse the iframe and appear instantly.

  • Most resource‑efficient; loads only if needed and avoids repeated work by reusing the iframe.

  • Performance benefit is realized only when the user navigates back to the analytics page; the first visit behaves like a normal render.

dig5 ondemand

Since we are not preloading any assets or data, this strategy does not require any pre-render component. Simply pass a prerender ID in the preRenderConfig object of your normal component render.

<LiveboardEmbed
  preRenderConfig={{
    id: 'pre-render-on-demand',
  }}
  liveboardId="e40c0727-01e6-49db-bb2f-5aa19661477b"
/>
// JavaScript
import { LiveboardEmbed } from '@thoughtspot/visual-embed-sdk';

const embed = new LiveboardEmbed({
  preRenderConfig: {
    id: 'pre-render-on-demand',
  },
  liveboardId: 'e40c0727-01e6-49db-bb2f-5aa19661477b',
});

embed.render();

The value of prerender ID can be any string, but it must match the id you use when rendering the actual embed later.

Normal renderđź”—

  • Default behavior. Loads the embed only when the component is rendered.

  • On every visit, the iframe is recreated and the embed loads from scratch.

  • Efficient if the embed is rarely used, but slow for the end user every time.

dig2
<LiveboardEmbed liveboardId="some-liveboard-id" />
// JavaScript
import { LiveboardEmbed } from '@thoughtspot/visual-embed-sdk';

const embed = new LiveboardEmbed({
  liveboardId: 'some-liveboard-id',
});

embed.render();

Prefetch assetsđź”—

  • Loads a few common JS/CSS assets in parallel with your app.

  • No Liveboard data or API calls are made.

  • Minimal benefit. As modern browsers already cache static assets efficiently, using prefetch may not provide a significant performance gain.

  • Wastes bandwidth if the end user never opens the embed.

dig6 prefetch
import {
   prefetch,
   PrefetchFeatures
} from '@thoughtspot/visual-embed-sdk';

prefetch("https://<hostname>:<port>", [
  PrefetchFeatures.LiveboardEmbed,
  PrefetchFeatures.VizEmbed
]);

Strategy comparison tableđź”—

StrategyLoads in ParallelLoads Data If Not UsedLoads Assets If Not UsedReuses IframePerceived Load SpeedNotes

Normal render

❌

âś… No

âś… No

❌

❌ Slowest

No reuse; re-renders every time

Prefetch

âś… (few assets)

âś… No

⚠️ Yes (small assets)

❌

⚠️ Slight improvement

Browser cache often makes it redundant

Pre-render + ID

âś…

❌ Yes

❌ Yes

âś…

âś…âś…âś… Fastest

Best UX, worst resource efficiency

Pre-render w/o ID

âś…

âś… No

⚠️ Yes (partial assets)

âś…

⚠️ Moderate

Trade-off between prep and efficiency

On Demand

❌

âś… No

âś… No

âś…

✅ (on revisit), ❌ (first visit)

Best balance of performance and efficiency

Best practicesđź”—

When you pre-render a Liveboard with PreRenderedLiveboardEmbed, pass the same configuration you intend to use on the real LiveboardEmbed, including the liveboardId and any flags that change the Liveboard’s layout or behavior, such as isLiveboardCompactHeaderEnabled or isLiveboardMasterpiecesEnabled.

These settings alter the rendered UI and the API calls ThoughtSpot makes to build the Liveboard. If a flag is set on LiveboardEmbed but was missing from the pre-rendered instance, the pre-rendered app cannot be reused as-is: it has to reload and re-fetch the Liveboard, which cancels the benefit of pre-rendering and reintroduces exactly the delay you were trying to avoid.

As a best practice, pre-render with the exact configuration you intend to display, the same liveboardId, and settings. When the pre-rendered configuration matches, the SDK reuses the existing instance directly, resulting in a near-instant load.

// Pre-render early (hidden), with the full config
<PreRenderedLiveboardEmbed
  preRenderConfig={{ id: 'lb-preview' }}
  liveboardId="<liveboard-guid>"
  isLiveboardCompactHeaderEnabled={true}
  isLiveboardMasterpiecesEnabled={true}
/>

// Later, show it — identical configuration settings, so the pre-rendered instance is reused
<LiveboardEmbed
  preRenderConfig={{ id: 'lb-preview' }}
  liveboardId="<liveboard-guid>"
  isLiveboardCompactHeaderEnabled={true}
  isLiveboardMasterpiecesEnabled={true}
/>

Troubleshootingđź”—

  • If the pre-rendered component does not appear, check that the container is visible and the coordinates are set.

  • The iframes are saved as child components to the body, and not in the given target element. To mount the pre-rendered iframe inside a specific element instead, use preRenderConfig.containerSelector. For more information, see Mount the pre-rendered embed in a specific container.

© 2026 ThoughtSpot Inc. All Rights Reserved.