Embedded analytics SDK - questions
⚠️ This feature is in beta. Feel free to play around with it, but be aware that things might change (and may not work as expected).
Embedded analytics SDK is only available on Pro and Enterprise plans (both self-hosted and on Metabase Cloud).
There are different ways you can embed questions:
StaticQuestion
. Embeds a chart. Clicking on the chart doesn’t do anything.InteractiveQuestion
. Clicking on the chart gives you the drill-through menu.CreateQuestion
ModifyQuestion
. Embeds the interactive question and the query builder.
Embedding a static question
You can embed a static question using the StaticQuestion
component.
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.
import React from "react";
import {MetabaseProvider, StaticQuestion} from "@metabase/embedding-sdk-react";
const config = {...}
export default function App() {
const questionId = 1; // This is the question ID you want to embed
return (
<MetabaseProvider config={config}>
<StaticQuestion questionId={questionId} showVisualizationSelector={false}/>
</MetabaseProvider>
);
}
You can pass parameter values to questions defined with SQL via parameterValues
prop, in the format of {parameter_name: parameter_value}
. Learn more about SQL parameters.
<StaticQuestion questionId={questionId} parameterValues={{ product_id: 50 }} />
Embedding an interactive question
You can embed an interactive question using the InteractiveQuestion
component.
import React from "react";
import {MetabaseProvider, InteractiveQuestion} from "@metabase/embedding-sdk-react";
const config = {...}
export default function App() {
const questionId = 1; // This is the question ID you want to embed
return (
<MetabaseProvider config={config}>
<InteractiveQuestion questionId={questionId}/>
</MetabaseProvider>
);
}
Question props
Prop | Type | Description |
---|---|---|
questionId | number \| string |
(required) The ID of the question. This is either: - The numerical ID when accessing a question link, e.g., http://localhost:3000/question/1-my-question where the ID is 1 .- The entity_id key of the question object. You can find a question’s entity ID in the info panel when viewing a question. |
plugins | { mapQuestionClickActions: Function } \| null |
Additional mapper function to override or add drill-down menu. |
height | number \| string |
(optional) A number or string specifying a CSS size value that specifies the height of the component |
entityTypeFilter | ("table" \| "question" \| "model" \| "metric")[] |
(optional) An array that specifies which entity types are available in the data picker |
isSaveEnabled | boolean |
(optional) Whether people can save the question. |
withResetButton | boolean |
(optional, default: true ) Determines whether a reset button is displayed. Only relevant when using the default layout |
withTitle | boolean |
(optional, default: false ) Determines whether the question title is displayed. Only relevant when using the default layout. |
customTitle | string \| undefined |
(optional) Allows a custom title to be displayed instead of the default question title. Only relevant when using the default layout. |
onBeforeSave | () => void |
(optional) A callback function that triggers before saving. Only relevant when isSaveEnabled = true . |
onSave | () => void |
(optional) A callback function that triggers when a user saves the question. Only relevant when isSaveEnabled = true . |
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:
<InteractiveQuestion questionId={95}>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<div style={{ display: "grid", placeItems: "center" }}>
<InteractiveQuestion.Title />
<InteractiveQuestion.ResetButton />
</div>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
overflow: "hidden",
}}
>
<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" }}>
<InteractiveQuestion.Filter />
</div>
</div>
</InteractiveQuestion>
Interactive question components
These components are available via the InteractiveQuestion
namespace (e.g., <InteractiveQuestion.Filter />
).
Component | Info |
---|---|
BackButton |
The back button, which provides back functionality for the InteractiveDashboard |
FilterBar |
The row of badges that contains the current filters that are applied to the question |
Filter |
The Filter pane containing all possible filters |
FilterButton |
The button used in the default layout to open the Filter pane. You can replace this button with your own implementation. |
ResetButton |
The button used to reset the question after the question has been modified with filters/aggregations/etc |
Title |
The question’s title |
SaveButton |
Button for saving the question. |
Summarize |
The Summarize pane containing all possible aggregations |
SummarizeButton |
The button used in the default layout to open the Summarize pane. You can replace this button with your own implementation. |
Notebook |
The Notebook editor that allows for more filter, aggregation, and custom steps |
NotebookButton |
The button used in the default layout to open the Notebook editor. You can replace this button with your own implementation. |
QuestionVisualization |
The chart visualization for the question |
Interactive question plugins
mapQuestionClickActions
This plugin allows you to add custom actions to the click-through menu of an interactive question. You can add and customize the appearance and behavior of the custom actions.
// 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 config={config} pluginsConfig={plugins}>
<InteractiveQuestion questionId={questionId} />
</MetabaseProvider>
);
Creating a question
With the CreateQuestion
component, you can create a new question from scratch with Metabase’s query builder.
import React from "react";
import {MetabaseProvider, CreateQuestion} from "@metabase/embedding-sdk-react";
const config = {...}
export default function App() {
return (
<MetabaseProvider config={config}>
<CreateQuestion/>
</MetabaseProvider>
);
}
Embedding an editable question
With the ModifyQuestion
component, you can edit an existing question using the query builder by passing the question’s ID.
import React from "react";
import {MetabaseProvider, ModifyQuestion} from "@metabase/embedding-sdk-react";
const config = {...}
export default function App() {
return (
<MetabaseProvider config={config}>
<ModifyQuestion questionId={1}/>
</MetabaseProvider>
);
}
Read docs for other versions of Metabase.