Analytics Embedding SDK

Use the Analytics Embedding SDK to embed Tableau Next analytical components in any web page. This SDK supports typescript, javascript and HTML formats. This version of the SDK is compatible with Salesforce API v65.0 and above.

Install 

1npm install @salesforce/analytics-embedding-sdk --save

Usage 

Note: The orgUrl parameter must be the Lightning URL (e.g., https://yourorg.lightning.force.com), not the my.salesforce.com domain URL.

TypeScript 

1import {AnalyticsDashboard, initializeAnalyticsSdk, type AnalyticsSdkConfig} from '@salesforce/analytics-embedding-sdk';
2
3const config: AnalyticsSdkConfig = {
4   authCredential: "<%- auth-credential %>",
5   orgUrl: "<%- org_url %>" // Must be Lightning URL
6};
7await initializeAnalyticsSdk(config);
8
9// parentIdOrElement is the target container (ID or element) and idOrApiName is the identifier or API name of the component to embed.
10const dashboard: AnalyticsDashboard = new AnalyticsDashboard({parentIdOrElement: 'embed-here', idOrApiName: 'My_Sales_Dashboard'});
11dashboard.render();

JavaScript 

1import {initializeAnalyticsSdk, AnalyticsDashboard} from '@salesforce/analytics-embedding-sdk';
2
3const config = {
4   authCredential: "<%- auth-credential %>",
5   orgUrl: "<%- org_url %>" // Must be Lightning URL
6};
7await initializeAnalyticsSdk(config);
8
9// parentIdOrElement is the target container (ID or element) and idOrApiName is the identifier or API name of the component to embed.
10const dashboard = new AnalyticsDashboard({parentIdOrElement: 'embed-here', idOrApiName: 'My_Sales_Dashboard'});
11dashboard.render();

HTML 

1<!DOCTYPE html>
2<html>
3<head>
4    <script type="module">
5        import {initializeAnalyticsSdk} from '@salesforce/analytics-embedding-sdk';
6
7        const config = {
8            authCredential: "<%- auth-credential %>",
9            orgUrl: "<%- org_url %>" // Must be Lightning URL
10        };
11
12        await initializeAnalyticsSdk({
13            authCredential: "<%- auth-credential %>",
14            orgUrl: "<%- org_url %>", // Must be Lightning URL
15        });
16    </script>
17</head>
18<body>
19    <analytics-dashboard id-or-api-name="My_Sales_Dashboard" height="500px">
20    </analytics-dashboard>
21</body>
22</html>

AnalyticsDashboard: custom views and dashboard actions 

Custom view ID (customViewId) 

You can pass an optional custom view ID so the embedded dashboard opens with the same saved filter state (custom view) as in Tableau Next. This aligns with share links that include a customViewId query parameter, and helps preserve dashboard interactivity when embedding in other surfaces (for example Slack).

TypeScript / JavaScript — set customViewId on the dashboard props (or assign dashboard.customViewId after construction):

1const dashboard = new AnalyticsDashboard({
2  parentIdOrElement: "embed-here",
3  idOrApiName: "My_Sales_Dashboard",
4  customViewId: "f5f0e1234aabcde67890",
5});
6await dashboard.render();

HTML — use the custom-view-id attribute on <analytics-dashboard>:

1<analytics-dashboard
2  id-or-api-name="My_Sales_Dashboard"
3  custom-view-id="f5f0e1234aabcde67890"
4  height="500px"
5></analytics-dashboard>

If your app parses a dashboard URL, read the customViewId query parameter and pass it through as shown above.

Dashboard button actions 

Configure actions on the dashboard in Tableau Next using Salesforce Help: add actions to a dashboard.

Dashboard actions (buttons configured on the dashboard) are supported in third-party embedding. That includes actions such as Salesforce Flows, page navigation, and URL navigation, consistent with the embedded dashboard experience in Tableau Next.

Filter Simplification 

The SDK provides two ways to apply filters: a simplified API that automatically constructs filter objects from individual parameters, and the original API that accepts pre-built filter objects.

Simplified applyFilters API (Recommended) 

The simplified API eliminates manual filter object construction by accepting Field and DataSource objects directly. It automatically constructs fieldName from Field objects (retrieved via getFields()) and accepts DataSource objects (from getDataSources()).

TypeScript / JavaScript:

1import {
2  AnalyticsDashboard,
3  FilterOperator,
4  SimplifiedFilter,
5} from "@salesforce/analytics-embedding-sdk";
6
7const dashboard = new AnalyticsDashboard({
8  parentIdOrElement: "embed",
9  idOrApiName: "My_Dashboard",
10});
11await dashboard.render();
12
13// Get fields and data sources from the component
14const fieldsMap = await dashboard.getFields();
15const fields = fieldsMap.get("SalesData");
16const accountField = fields.find((f) => f.apiName === "Name" && f.objectName === "Account");
17const stageField = fields.find((f) => f.apiName === "Stage" && f.objectName === "Opportunity");
18
19const dataSources = await dashboard.getDataSources();
20const salesDataSource = dataSources.find((ds) => ds.apiName === "SalesData");
21
22// Apply filters using SimplifiedFilter array format
23const filters: SimplifiedFilter[] = [
24  {
25    field: accountField, // Field object from getFields()
26    operator: FilterOperator.Equals, // FilterOperator enum
27    values: ["Acme Corp"], // Values as array
28    dataSource: salesDataSource, // DataSource object from getDataSources() (for dashboards)
29  },
30  {
31    field: stageField,
32    operator: FilterOperator.In, // FilterOperator enum
33    values: ["Prospecting", "Negotiation"],
34    dataSource: salesDataSource, // Can reuse the same DataSource object
35  },
36];
37
38await dashboard.applyFilters(filters);

For metrics and visualizations, omit the dataSource property:

1import {
2  AnalyticsMetric,
3  FilterOperator,
4  SimplifiedFilter,
5} from "@salesforce/analytics-embedding-sdk";
6
7const metric = new AnalyticsMetric({ parentIdOrElement: "embed", idOrApiName: "My_Metric" });
8await metric.render();
9
10const fieldsMap = await metric.getFields();
11const fields = Array.from(fieldsMap.values())[0]; // Single data source
12const regionField = fields.find((f) => f.apiName === "Region");
13
14// No dataSource needed for metrics/visualizations
15const filters: SimplifiedFilter[] = [
16  {
17    field: regionField,
18    operator: FilterOperator.Equals,
19    values: ["West"],
20  },
21];
22
23await metric.applyFilters(filters);

Original applyFilters API (Still Supported) 

Use the SDK to build valid filters. The SDK provides metadata you can use to assemble a UnifiedFilterJson object. See the applyFilters method and the filters property in the component classes. Filter validation informs you what you can filter on, not the final JSON object. Follow these rules to combine datasources, fields, operators, and values into a filter that passes validation.

What Each Method Provides 

Data Sources 

Supported for dashboards only.

Methods: getDataSources(), getInteractionDetails().dataSources

Returns which semantic model a row belongs to. On dashboards with multiple data sources, set dataSource on each filter to the API name that matches the map key for that field. With a single data source, dataSource is optional in the type; setting it anyway avoids ambiguity.

Fields 

Methods: getFields(), getInteractionDetails().fields — use filterFields from getInteractionDetails() when you only need columns that support filtering.

Each field includes dataType, fieldType, apiName, and optional objectName.

Filter Operators 

Enum: FilterOperator — choose a value that is valid for the field’s data type, for example, range operators for numbers, relative-date operators for dates. The SDK returns dataType on each field, not a list of allowed operators. Mapping data type → operator, and any extra rules, is up to your app unless your product supplies a separate list.

Operators that don’t take operands, such as IsNull, should omit values or use an empty array as required. Others, for example relative date operators, may require specific values. Follow the operator’s contract.

Field Values 

Method: getFilterFieldValues(fieldApiName, fieldObjectName?, searchTerm?)

Use for discrete lists or typeahead. Pass fieldObjectName when getFields() / getInteractionDetails() include objectName on that field; otherwise omit it.

How to Combine Method Values into One Valid Filter 

  1. Wait until the component is ready — Call filter helpers after render() resolves and the asset has loaded. For example after EventName.COMPONENT_LOADED or EventName.RECEIVED_DATASOURCES on dashboards when you rely on datasource lists.
  2. Pick scope — Dashboard: choose a dataSource API name from getDataSources() or getInteractionDetails().dataSources. It must match the map key for the field you use. Metric or visualization: there is a single implicit context; don’t set dataSource on the filter object.
  3. Pick a field — Use the field list for that data source’s key in the map for a dashboard. Iterate getFields() / getInteractionDetails() maps for metrics and visualizations, which often have one key. Build fieldName as objectName + "." + apiName when objectName is present; otherwise use the field’s apiName alone, consistent with how filters are shown in the embedding API examples.
  4. Pick an operator — Must match the field’s data type and your product’s allowed set. Metric note: Equals and DoesNotEquals are translated to In and NotIn in current behavior.
  5. Pick values — Use getFilterFieldValues when the user needs actual members. All entries in values must share the same type (all strings, all numbers, and so on). Omit values when the operator doesn’t need them.
  6. Apply — Pass an array to applyFilters. Dashboards and metrics replace the filter set. Visualizations add to existing filters. When applying filters repeatedly, plan getFilters() / clearFilters() accordingly.

Minimal dashboard example:

1import { AnalyticsDashboard, FilterOperator } from "@salesforce/analytics-embedding-sdk";
2
3const dashboard = new AnalyticsDashboard({
4  parentIdOrElement: "embed",
5  idOrApiName: "My_Dashboard",
6});
7await dashboard.render();
8
9const { dataSources, filterFields } = await dashboard.getInteractionDetails();
10// Assumes at least one data source and a filterable Account.Name field on that source.
11const ds = dataSources![0].apiName;
12const field = filterFields
13  .get(ds)!
14  .find((f) => f.apiName === "Name" && f.objectName === "Account")!;
15
16const filters = [
17  {
18    dataSource: ds,
19    fieldName: `${field.objectName}.${field.apiName}`,
20    operator: FilterOperator.Equals,
21    values: ["Acme Corp"],
22  },
23];
24await dashboard.applyFilters(filters);

For metrics and visualizations, the same fieldName / operator / values rules apply; omit dataSource.

Invalid or mismatched combinations, such as wrong data source for the field, bad fieldName shape, operator incompatible with type, or mixed-type values, can cause an ERROR event and the filter isn’t applied. Validate inputs before calling applyFilters.

AnalyticsAgent 

The AnalyticsAgent component embeds your Analytics and Visualization agent powered by Agentforce. It helps users understand data through natural language insights, visualizations, and proactive alerts.

The agent supports two operating modes:

  • Single-context mode — Provide contextConfig to bind the agent to a specific dashboard, metric, or semantic model.
  • Multi-component mode — Omit contextConfig to automatically track all embedded AnalyticsDashboard and AnalyticsMetric components on the page.

TypeScript 

1import {
2	AnalyticsAgent,
3	AgentContextType,
4	initializeAnalyticsSdk,
5	analyticsEventTarget,
6	EventName,
7	type AgentProps,
8	type AnalyticsSdkConfig
9} from '@salesforce/analytics-embedding-sdk';
10
11const config: AnalyticsSdkConfig = {
12	authCredential: '<%- auth-credential %>',
13	orgUrl: '<%- org_url %>' // Must be Lightning URL
14};
15await initializeAnalyticsSdk(config);
16
17// Single-context mode: bind the agent to a specific dashboard
18const agentProps: AgentProps = {
19	parentIdOrElement: 'agent-container',
20	idOrApiName: '<%- agent-id %>',
21	contextConfig: {
22		contextType: AgentContextType.DASHBOARD,
23		contextTypeIdOrApiName: 'My_Sales_Dashboard'
24	},
25	showHeader: true,
26	showHeaderActions: true,
27	agentName: 'Sales Insights',
28	welcomeText: 'Ask me anything about your sales data.'
29};
30
31const agent: AnalyticsAgent = new AnalyticsAgent(agentProps);
32agent.render();

JavaScript 

1import {
2  initializeAnalyticsSdk,
3  AnalyticsAgent,
4  AgentContextType,
5} from "@salesforce/analytics-embedding-sdk";
6
7const config = {
8  authCredential: "<%- auth-credential %>",
9  orgUrl: "<%- org_url %>", // Must be Lightning URL
10};
11await initializeAnalyticsSdk(config);
12
13// Multi-component mode: omit contextConfig to track all embedded components automatically
14const agent = new AnalyticsAgent({
15  parentIdOrElement: "agent-container",
16  idOrApiName: "<%- agent-id %>",
17  showHeader: true,
18  showHeaderActions: true,
19  agentName: "Sales Insights",
20  welcomeText: "Ask me anything about your sales data.",
21});
22agent.render();

HTML 

1<!DOCTYPE html>
2<html>
3  <head>
4    <script type="module">
5      import { initializeAnalyticsSdk } from "@salesforce/analytics-embedding-sdk";
6
7      await initializeAnalyticsSdk({
8        authCredential: "<%- auth-credential %>",
9        orgUrl: "<%- org_url %>", // Must be Lightning URL
10      });
11    </script>
12  </head>
13  <body>
14    <analytics-agent
15      id-or-api-name="<%- agent-id %>"
16      context-type="dashboard"
17      context-type-id-or-api-name="My_Sales_Dashboard"
18      show-header="true"
19      show-header-actions="true"
20      agent-name="Sales Insights"
21      welcome-text="Ask me anything about your sales data."
22      height="600px"
23    ></analytics-agent>
24  </body>
25</html>

AgentContextType 

The AgentContextType enum specifies the type of analytics asset to bind the agent to:

ValueDescription
AgentContextType.DASHBOARDDashboard context
AgentContextType.METRICMetric context
AgentContextType.SDMSemantic Model context

Styling with AgentStyleTokens 

Use the styleTokens property to theme the agent UI:

1const agent = new AnalyticsAgent({
2  parentIdOrElement: "agent-container",
3  idOrApiName: "<%- agent-id %>",
4  styleTokens: {
5    containerBackground: "#faf5ff",
6    headerBackground: "#ede9fe",
7    headerBlockTextColor: "#5b21b6",
8    messageBlockInboundBackgroundColor: "#ede9fe",
9    messageBlockOutboundBackgroundColor: "#7c3aed",
10    messageBlockOutboundTextColor: "#ffffff",
11    messageInputFooterSendButton: "#ec4899",
12  },
13});
14agent.render();

Restarting the Agent Session 

Call startNewAgentSession() to programmatically restart the conversation:

1await agent.startNewAgentSession();

Multi-org Support 

The SDK supports embedding components from multiple Salesforce orgs in a single application. Use orgConfigs instead of a single orgUrl and authCredential:

1import {
2  initializeAnalyticsSdk,
3  AnalyticsDashboard,
4  AnalyticsVisualization,
5  AnalyticsAgent,
6  AgentContextType,
7} from "@salesforce/analytics-embedding-sdk";
8
9// Initialize with multiple orgs
10const initPayload = {
11  orgConfigs: [
12    {
13      orgUrl: "https://org1.lightning.force.com", // Lightning URL required
14      authCredential: "https://org1-frontdoor.salesforce.com/...",
15    },
16    {
17      orgUrl: "https://org2.lightning.force.com", // Lightning URL required
18      authCredential: "https://org2-frontdoor.salesforce.com/...",
19    },
20  ],
21};
22
23const response = await initializeAnalyticsSdk(initPayload);
24
25// Embed components from different orgs - always specify orgUrl
26const dashboard = new AnalyticsDashboard({
27  parentIdOrElement: "container1",
28  idOrApiName: "Dashboard1",
29  orgUrl: "https://org1.lightning.force.com", // Required for multi-org
30});
31dashboard.render();
32
33const visualization = new AnalyticsVisualization({
34  parentIdOrElement: "container2",
35  idOrApiName: "Viz2",
36  orgUrl: "https://org2.lightning.force.com", // Different org
37});
38visualization.render();
39
40const agent = new AnalyticsAgent({
41  parentIdOrElement: "container3",
42  idOrApiName: "Agent1",
43  contextConfig: {
44    contextType: AgentContextType.DASHBOARD,
45    contextTypeIdOrApiName: "Dashboard1",
46  },
47  orgUrl: "https://org1.lightning.force.com", // Required for multi-org
48});
49agent.render();

Note:

  • The orgUrl is required when creating components in a multi-org scenario, to ensure your component connects to the correct org.

Adding Orgs Dynamically 

You can add new orgs or retry failed orgs after initial SDK initialization using retryOrAddOrgs:

1import { retryOrAddOrgs } from "@salesforce/analytics-embedding-sdk";
2
3const newOrgs = [
4  {
5    orgUrl: "https://org3.lightning.force.com", // Lightning URL required
6    authCredential: "https://org3-frontdoor.salesforce.com/...",
7  },
8  {
9    orgUrl: "https://org4.lightning.force.com", // Lightning URL required
10    authCredential: "https://org4-frontdoor.salesforce.com/...",
11  },
12];
13const response = await retryOrAddOrgs(newOrgs);
14console.log(response.status); // Check if orgs were added successfully

The retryOrAddOrgs function returns the same BootstrapResponse format as initializeAnalyticsSdk.

Response 

The initializeAnalyticsSdk function returns a BootstrapResponse object:

1const response = await initializeAnalyticsSdk(config);
2
3// Response structure:
4{
5    "message": "Sdk Initialize Complete",
6    "status": "Success",
7    "orgStates": {
8        "https://org1.lightning.force.com": {
9            "state": "INITIALIZATION_SUCCESS",
10            "reason": ""
11        },
12        "https://org2.lightning.force.com": {
13            "state": "INITIALIZATION_SUCCESS",
14            "reason": ""
15        }
16    }
17}
18
19console.log(response.status);  // Check initialization status
20console.log(response.message); // Get detailed message
21
22// For multi-org scenarios, check individual org states:
23if (response.orgStates) {
24    response.orgStates.forEach((state, orgUrl) => {
25        console.log(`Org ${orgUrl}: ${state.state}`);
26    });
27}

Sample response:

1{
2  "message": "Sdk Initialize Complete",
3  "status": "Success",
4  "orgStates": {
5    "https://org1.lightning.force.com": {
6      "state": "INITIALIZATION_SUCCESS",
7      "reason": ""
8    },
9    "https://org2.lightning.force.com": {
10      "state": "INITIALIZATION_SUCCESS",
11      "reason": ""
12    }
13  }
14}

Status values:

  • Status.SUCCESS - All orgs initialized successfully
  • Status.PARTIAL_SUCCESS - Some orgs initialized successfully (multi-org only)
  • Status.FAILURE - Initialization failed

MFA and password reset (auth redirect) 

For a single org or multiple orgs, Salesforce may require an extra step before the session is valid—such as multi-factor authentication (MFA) or a forced password reset. In that case initializeAnalyticsSdk can return a non-success overall status while the affected org appears in response.orgStates with:

  • state: AUTH_REDIRECT (see OrgStates.AUTH_REDIRECT when importing the enum)
  • redirectUrl: org-provided path (often relative)
  • redirectOrigin: origin to combine with redirectUrl

What to do

  1. For each org entry in AUTH_REDIRECT, send the user to the challenge UI, typically by opening ${redirectOrigin}${redirectUrl} in a new window or tab (popups may be blocked; fall back to a full tab).
  2. After the user finishes MFA or password reset and the browser session is established for that org, resume the SDK by calling retryOrAddOrgs for that org.

Credentials when retrying

  • Normal retry: pass a fresh frontdoor URL (or equivalent session credential) as authCredential together with the same Lightning orgUrl.
  • After MFA / password reset: once the session exists in the browser, you can retry with the Lightning org URL as the credential: { orgUrl, authCredential: orgUrl }, without generating a new frontdoor URL first. If that retry does not succeed, obtain a new frontdoor URL and retry with it.

The retryOrAddOrgs response uses the same BootstrapResponse shape as initializeAnalyticsSdk, so you can inspect orgStates again for any remaining AUTH_REDIRECT or errors.

Logout 

The SDK provides a logout function to log out from Salesforce orgs. The function returns a LogoutResponse with the same structure as BootstrapResponse.

1import { logout } from "@salesforce/analytics-embedding-sdk";
2
3// Logout from all orgs
4const response = await logout();
5
6// Logout from specific orgs
7const response = await logout([
8  "https://org1.lightning.force.com",
9  "https://org2.lightning.force.com",
10]);
11
12console.log(response.status); // 'Success', 'Partial Success', or 'Failure'
13console.log(response.message); // Detailed logout message

Sample response:

1{
2  "message": "Log out for all orgs complete",
3  "status": "Success",
4  "orgStates": {
5    "https://org1.lightning.force.com": {
6      "state": "LOGGED_OUT",
7      "reason": ""
8    },
9    "https://org2.lightning.force.com": {
10      "state": "LOGGED_OUT",
11      "reason": ""
12    }
13  }
14}

Need Help 

Supported Desktop and Laptop Browsers 

The SDK supports all browsers supported in Salesforce Lightning Experience.