These are the docs for the Metabase master branch. Some features documented here may not yet be available in the latest release. Check out the docs for the latest version, Metabase v0.56.
Embedded analytics SDK - questions
Embedded analytics SDK is only available on Pro and Enterprise plans (both self-hosted and on Metabase Cloud). You can, however, play around with the SDK on your local machine without a license by using API keys to authenticate your embeds.
There are different ways you can embed questions:
- Static question. Embeds a chart. Clicking on the chart doesn’t do anything.
- Interactive question. Clicking on the chart gives you the drill-through menu.
- Query builder. Embeds the graphical query builder without a pre-defined query.
Embedding a question
You can embed a question using the one of the question components:
StaticQuestion
A lightweight question component. Use this component when you want to display results without letting people interact with the data.

The component has a default height, which can be customized by using the height prop. To inherit the height from the parent container, you can pass 100% to the height prop.
API Reference
Example
import React from "react";
import {
MetabaseProvider,
StaticQuestion,
defineMetabaseAuthConfig,
} from "@metabase/embedding-sdk-react";
const authConfig = defineMetabaseAuthConfig({
metabaseInstanceUrl: "https://your-metabase.example.com",
});
export default function App() {
const questionId = 1; // This is the question ID you want to embed
return (
<MetabaseProvider authConfig={authConfig}>
<StaticQuestion questionId={questionId} withChartTypeSelector={false} />
</MetabaseProvider>
);
}
Props
| Property | Type | Description |
|---|---|---|
className? |
string |
A custom class name to be added to the root element. |
height? |
Height<string | number> |
A number or string specifying a CSS size value that specifies the height of the component |
hiddenParameters? |
string[] |
A list of parameters to hide. |
initialSqlParameters? |
SqlParameterValues |
Initial values for the SQL parameters. |
questionId |
null | SdkQuestionId |
- |
style? |
CSSProperties |
A custom style object to be added to the root element. |
title? |
SdkQuestionTitleProps |
Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. Only applicable to interactive questions when using the default layout. |
width? |
Width<string | number> |
A number or string specifying a CSS size value that specifies the width of the component |
withChartTypeSelector? |
boolean |
Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. |
withDownloads? |
boolean |
Enables the ability to download results in the interactive question. |
InteractiveQuestion
Use this component when you want to allow people to explore their data and customize question layout.

API Reference
Example
import React from "react";
import {
InteractiveQuestion,
MetabaseProvider,
defineMetabaseAuthConfig,
} from "@metabase/embedding-sdk-react";
const authConfig = defineMetabaseAuthConfig({
metabaseInstanceUrl: "https://your-metabase.example.com",
});
export default function App() {
const questionId = 1; // This is the question ID you want to embed
return (
<MetabaseProvider authConfig={authConfig}>
<InteractiveQuestion questionId={questionId} />
</MetabaseProvider>
);
}
Props
| Property | Type | Description |
|---|---|---|
className? |
string |
A custom class name to be added to the root element. |
entityTypes? |
EmbeddingEntityType[] |
An array that specifies which entity types are available in the data picker |
height? |
Height<string | number> |
A number or string specifying a CSS size value that specifies the height of the component |
hiddenParameters? |
string[] |
A list of parameters to hide. |
initialSqlParameters? |
SqlParameterValues |
Initial values for the SQL parameters. |
isSaveEnabled? |
boolean |
Whether to show the save button. |
onBeforeSave? |
(question: undefined | MetabaseQuestion, context: { isNewQuestion: boolean; }) => Promise<void> |
A callback function that triggers before saving. Only relevant when isSaveEnabled = true |
onNavigateBack? |
() => void |
A callback function that triggers when a user clicks the back button. |
onRun? |
(question: undefined | MetabaseQuestion) => void |
A callback function that triggers when a question is updated, including when a user clicks the Visualize button in the question editor |
onSave? |
(question: MetabaseQuestion, context: { dashboardTabId?: number; isNewQuestion: boolean; }) => void |
A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true |
onVisualizationChange? |
(display: | "object" | "table" | "bar" | "line" | "pie" | "scalar" | "row" | "area" | "combo" | "pivot" | "smartscalar" | "gauge" | "progress" | "funnel" | "map" | "scatter" | "waterfall" | "sankey" | "list") => void |
A callback function that triggers when the visualization type changes. |
plugins? |
MetabasePluginsConfig |
- |
questionId |
null | SdkQuestionId |
- |
style? |
CSSProperties |
A custom style object to be added to the root element. |
targetCollection? |
SdkCollectionId |
The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions. |
title? |
SdkQuestionTitleProps |
Determines whether the question title is displayed, and allows a custom title to be displayed instead of the default question title. Shown by default. Only applicable to interactive questions when using the default layout. |
width? |
Width<string | number> |
A number or string specifying a CSS size value that specifies the width of the component |
withChartTypeSelector? |
boolean |
Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout. |
withDownloads? |
boolean |
Enables the ability to download results in the interactive question. |
withResetButton? |
boolean |
Determines whether a reset button is displayed. Only relevant when using the default layout. |
Pass SQL parameters to SQL questions with initialSqlParameters
You can pass parameter values to questions defined with SQL via the initialSqlParameters prop, in the format of {parameter_name: parameter_value}. Learn more about SQL parameters.
<StaticQuestion
questionId={questionId}
initialSqlParameters={{ product_id: 50 }}
/>
initialSqlParameters can’t be used with questions built using the query builder.
Questions with natural language
See AI chat.
Customizing interactive questions
By default, the Embedded analytics SDK provides a default layout for interactive questions that allows you to view your questions, apply filters and aggregations, and access functionality within the query builder.
Here’s an example of using the InteractiveQuestion component with its default layout:
<InteractiveQuestion questionId={95} />
To customize the layout, use namespaced components within the InteractiveQuestion component. For example:
<div
className="App"
style={{
width: "100%",
maxWidth: "1600px",
height: "800px",
margin: "0 auto",
}}
>
<MetabaseProvider authConfig={authConfig} theme={theme}>
<InteractiveQuestion questionId={95}>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
width: "100%",
}}
>
<div style={{ display: "grid", placeItems: "center", width: "100%" }}>
<InteractiveQuestion.Title />
<InteractiveQuestion.ResetButton />
</div>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
overflow: "hidden",
width: "100%",
}}
>
<div style={{ width: "100%" }}>
<InteractiveQuestion.QuestionVisualization />
</div>
<div style={{ display: "flex", flex: 1, overflow: "scroll" }}>
<InteractiveQuestion.Summarize />
</div>
</div>
<div
style={{ display: "flex", flexDirection: "column", width: "100%" }}
>
<InteractiveQuestion.Filter />
</div>
</div>
</InteractiveQuestion>
</MetabaseProvider>
</div>
Interactive question components
These components are available via the InteractiveQuestion namespace (e.g., <InteractiveQuestion.Filter />).
API Reference:
- InteractiveQuestion.BackButton
- InteractiveQuestion.Breakout
- InteractiveQuestion.BreakoutDropdown
- InteractiveQuestion.ChartTypeDropdown
- InteractiveQuestion.ChartTypeSelector
- InteractiveQuestion.Editor
- InteractiveQuestion.EditorButton
- InteractiveQuestion.Filter
- InteractiveQuestion.FilterDropdown
- InteractiveQuestion.QuestionSettings
- InteractiveQuestion.QuestionSettingsDropdown
- InteractiveQuestion.QuestionVisualization
- InteractiveQuestion.ResetButton
- InteractiveQuestion.SaveButton
- InteractiveQuestion.SaveQuestionForm
- InteractiveQuestion.Summarize
- InteractiveQuestion.SummarizeDropdown
- InteractiveQuestion.DownloadWidget
- InteractiveQuestion.DownloadWidgetDropdown
- InteractiveQuestion.Title
Interactive question plugins
You can use plugins to add custom functionality to your questions.
mapQuestionClickActions
When people click on a data point in the embedded interactive chart, Metabase shows them a menu of actions by default. The plugin mapQuestionClickActions allows you to customize this behavior. You can choose to:
- Open the default Metabase menu.
- Add custom actions to that click-through menu.
- Perform immediate action without opening a menu.
Use mapQuestionClickActions globally at the provider level, or on individual InteractiveQuestion or InteractiveDashboard components. For more on provider scope, see Plugins
The example below shows all the options for click action behavior. This example will:
- Open a menu with custom actions when “Last Name” column is clicked.
- Perform an immediate action (show an alert) when the “Plan” column is clicked.
- Shows the default menu (available as
clickActions) in all other cases.
The behavior is determined by what mapQuestionClickActions returns: array of actions to open a menu, or a single action to trigger an immediate action.
<MetabaseProvider
authConfig={authConfig}
pluginsConfig={{
mapQuestionClickActions: (clickActions, clicked) => {
if (clicked?.column?.display_name === "Last Name") {
// This adds a custom action to the menu when clicked on on "Last Name" column
return [
...clickActions,
{
buttonType: "horizontal",
name: "custom",
title: "This is the Last Name column",
onClick: () => alert("You clicked the Last Name column!"),
},
];
}
if (clicked?.column?.display_name === "Plan") {
// This performs an immediate action on "Plan" column instead of opening the menu
return {
onClick: () => alert("You clicked the Plan column!"),
};
}
// default behavior (open Metabase's default click menu) on other columns
return clickActions;
},
}}
>
<InteractiveQuestion questionId={1} />
</MetabaseProvider>
);
You can also customize the appearance of custom actions in the click menu. The example below shows an example of a click menu with default actions, a custom action, and a custom action with customized appearance:
// You can provide a custom action with your own `onClick` logic.
const createCustomAction = clicked => ({
buttonType: "horizontal",
name: "client-custom-action",
section: "custom",
type: "custom",
icon: "chevronright",
title: "Hello from the click app!!!",
onClick: ({ closePopover }) => {
alert(`Clicked ${clicked.column?.name}: ${clicked.value}`);
closePopover();
},
});
// Or customize the appearance of the custom action to suit your need.
const createCustomActionWithView = clicked => ({
name: "client-custom-action-2",
section: "custom",
type: "custom",
view: ({ closePopover }) => (
<button
className="tw-text-base tw-text-yellow-900 tw-bg-slate-400 tw-rounded-lg"
onClick={() => {
alert(`Clicked ${clicked.column?.name}: ${clicked.value}`);
closePopover();
}}
>
Custom element
</button>
),
});
const plugins = {
/**
* You will have access to default `clickActions` that Metabase renders by default.
* So you could decide if you want to add custom actions, remove certain actions, etc.
*/
mapQuestionClickActions: (clickActions, clicked) => {
return [
...clickActions,
createCustomAction(clicked),
createCustomActionWithView(clicked),
];
},
};
const questionId = 1; // This is the question ID you want to embed
return (
<MetabaseProvider authConfig={authConfig} pluginsConfig={plugins}>
<InteractiveQuestion questionId={questionId} />
</MetabaseProvider>
);
Prevent people from saving changes to an InteractiveQuestion
To prevent people from saving changes to an interactive question, or from saving changes as a new question, you can set isSaveEnabled={false}:
import React from "react";
import {
InteractiveQuestion,
MetabaseProvider,
defineMetabaseAuthConfig,
} from "@metabase/embedding-sdk-react";
const authConfig = defineMetabaseAuthConfig({
metabaseInstanceUrl: "https://your-metabase.example.com",
});
export default function App() {
return (
<MetabaseProvider authConfig={authConfig}>
<InteractiveQuestion questionId={1} isSaveEnabled={false} />
</MetabaseProvider>
);
}
Embedding the query builder for creating new questions

You can embed the query builder for creating new questions by passing the questionId="new" prop to the InteractiveQuestion component. You can use the children prop to customize the layout for creating new questions.
import React from "react";
import {
InteractiveQuestion,
MetabaseProvider,
defineMetabaseAuthConfig,
} from "@metabase/embedding-sdk-react";
const authConfig = defineMetabaseAuthConfig({
metabaseInstanceUrl: "https://your-metabase.example.com",
});
export default function App() {
return (
<MetabaseProvider authConfig={authConfig}>
<InteractiveQuestion questionId="new" />
</MetabaseProvider>
);
}
To customize the question editor’s layout, use the InteractiveQuestion component directly with a custom children prop.
Read docs for other versions of Metabase.