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:

Embedding a static question

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, defineMetabaseAuthConfig} from "@metabase/embedding-sdk-react";

const authConfig = defineMetabaseAuthConfig({...});

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>
    );
}

Embedding an interactive question

Interactive question

You can embed an interactive question using the InteractiveQuestion component.

import React from "react";
import {MetabaseProvider, InteractiveQuestion, defineMetabaseAuthConfig} from "@metabase/embedding-sdk-react";

const authConfig = defineMetabaseAuthConfig({...});

export default function App() {
    const questionId = 1; // This is the question ID you want to embed

    return (
        <MetabaseProvider authConfig={authConfig}>
            <InteractiveQuestion questionId={questionId}/>
        </MetabaseProvider>
    );
}

Question props

Prop Type Description
entityTypeFilter string array; options include “table”, “question”, “model”, “metric” (optional) An array that specifies which entity types are available in the data picker
height number or string (optional) A number or string specifying a CSS size value that specifies the height of the component
initialSqlParameters Record<string, string \| string[]> (optional) For SQL questions only. A mapping of SQL parameter names to parameter values, such as { product_id: "42"}
isSaveEnabled boolean (optional, default: true) Whether users can save the question
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
plugins { mapQuestionClickActions: Function } or null Additional mapper function to override or add drill-down menu
questionId number or 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
- new to show the notebook editor for creating new questions. isSaveEnabled must be true to allow saving the question
saveToCollection number | “root” | “personal” Deprecated: use targetCollection instead
targetCollection number | “root” | “personal” (optional) The collection to save the question to. This will hide the collection picker from the save modal. Only applicable to interactive questions
title boolean | string | ReactNode | () => ReactNode (optional) 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
withChartTypeSelector boolean (optional, default: true) Determines whether the chart type selector and corresponding settings button are shown. Only relevant when using the default layout
withResetButton boolean (optional, default: true) 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.

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={config} theme={theme}>
        <InteractiveQuestion questionId={questionId}>
          <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 />).

* signifies a required prop

InteractiveQuestion.BackButton

A navigation button that returns to the previous view. Only renders when onNavigateBack prop from InteractiveQuestion is available.

Uses Mantine ActionIcon props under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.Breakout

A set of badges for managing data groupings (breakouts).

No props. Uses question context for breakout functionality.

InteractiveQuestion.BreakoutDropdown

Dropdown button for the Breakout component.

Uses Popover props except onClose, children, and opened under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.ChartTypeDropdown

Dropdown for selecting the visualization type (bar chart, line chart, table, etc.). Automatically updates to show recommended visualization types for the current data.

Uses Mantine Menu props under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.ChartTypeSelector

Detailed chart type selection interface with recommended visualization options.

Uses Mantine Stack props under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.Editor

Advanced query editor that provides full access to question configuration. Includes filtering, aggregation, custom expressions, and joins.

Replaces deprecated InteractiveQuestion.Notebook

Prop Type Description
onApply () => void Callback function executed when changes are applied

InteractiveQuestion.EditorButton

Replaces deprecated InteractiveQuestion.NotebookButton

Toggle button for showing/hiding the Editor interface. In custom layouts, the EditorButton must have an onClick handler or the button won’t do anything when clicked.

Uses Mantine ActionIcon props under the hood, as well as:

Prop Type Description
isOpen boolean Whether the editor is currently open
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.Filter

A set of interactive filter badges that allow adding, editing, and removing filters. Displays current filters as badges with an “Add another filter” option.

Prop Type Description
withColumnItemIcon boolean Whether to show column icons in the filter interface

InteractiveQuestion.FilterDropdown

A dropdown button for the Filter component.

Prop Type Description
withColumnItemIcon boolean Whether to show column icons in the filter interface

InteractiveQuestion.QuestionSettings

Settings panel for configuring visualization options like axes, colors, and formatting.

No props. Uses question context for settings.

InteractiveQuestion.QuestionSettingsDropdown

Dropdown button that contains the QuestionSettings component.

Uses Popover props except onClose and opened under the hood, as well as:

Prop Type Description
height React.CSSProperties[“height”] Height for the dropdown menu
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.QuestionVisualization

The main visualization component that renders the question results as a chart, table, or other visualization type.

Prop Type Description
height number | string Height for visualization
width number | string Width for visualization
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.ResetButton

Button to reset question modifications. Only appears when there are unsaved changes to the question.

Uses Mantine Button props under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.SaveButton

Button for saving question changes. Only enabled when there are unsaved modifications to the question.

Note: Currently, in custom layouts, the SaveButton must have an onClick handler or the button will not do anything when clicked.

Uses Mantine Button props under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.SaveQuestionForm

Form for saving a question, including title and description. When saved:

  • For new questions: Calls onCreate prop from InteractiveQuestion
  • For existing questions: Calls onSave prop from InteractiveQuestion
  • Both callbacks receive the updated question object
  • Form can be cancelled via the onCancel prop
Prop Type Description
onCancel () => void Callback function executed when save is cancelled

InteractiveQuestion.Summarize

Interface for adding and managing data summaries (like counts, sums, averages). Displays as a set of badges.

No props. Uses question context for summarization functionality.

InteractiveQuestion.SummarizeDropdown

Dropdown button for the Summarize component.

Uses Popover props except onClose, children, and opened under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.DownloadWidget

Provides a UI widget for downloading data in different formats (CSV, XLSX, JSON, and PNG depending on the visualization).

No props

InteractiveQuestion.DownloadWidgetDropdown

Provides a button that contains a dropdown that shows the DownloadWidget.

Uses Popover props under the hood, as well as:

Prop Type Description
className string Custom CSS class name for styling the component
style React.CSSProperties Inline styles to apply to the component

InteractiveQuestion.Title

Displays a title based on the question’s state. Shows:

  • The question’s display name if it’s saved
  • An auto-generated description for ad-hoc questions (non-native queries)
  • “New question” as fallback or for new/native queries
Prop Type Description
className string Custom CSS class name for styling the component
style CSSProperties Inline styles to apply to the component

Interactive question plugins

You can use plugins to add custom functionality to your questions.

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 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 {MetabaseProvider, InteractiveQuestion} from "@metabase/embedding-sdk-react";

const authConfig = defineMetabaseAuthConfig({...});

export default function App() {
    return (
        <MetabaseProvider authConfig={authConfig}>
            <InteractiveQuestion questionId={1} isSaveEnabled={false} />
        </MetabaseProvider>
    );
}

Embedding the query builder for creating new questions

Query builder

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 {MetabaseProvider, InteractiveQuestion} from "@metabase/embedding-sdk-react";

const authConfig = defineMetabaseAuthConfig({...});

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.