diff --git a/frontend/src/metabase/visualizations/components/FunnelNormal.jsx b/frontend/src/metabase/visualizations/components/FunnelNormal.jsx
index 766179f678e069c100ac2c948a5d531d928f8111..c4d800f8ce715728db6572a50f566bed707254df 100644
--- a/frontend/src/metabase/visualizations/components/FunnelNormal.jsx
+++ b/frontend/src/metabase/visualizations/components/FunnelNormal.jsx
@@ -26,7 +26,11 @@ export default class FunnelNormal extends Component {
     const dimensionIndex = 0;
     const metricIndex = 1;
     const cols = series[0].data.cols;
-    const rows = series.map(s => s.data.rows[0]);
+    const rows = settings["funnel.rows"]
+      ? settings["funnel.rows"]
+          .filter(fr => fr.enabled)
+          .map(fr => series[fr.rowIndex].data.rows[0])
+      : series.map(s => s.data.rows[0]);
 
     const isNarrow = gridSize && gridSize.width < 7;
     const isShort = gridSize && gridSize.height <= 5;
diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedColumns.jsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedColumns.jsx
index acfa6f174577a077bee89656838e6adad4ad6063..9cda8046034d3835956e045dcd93043562cfecde 100644
--- a/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedColumns.jsx
+++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedColumns.jsx
@@ -3,45 +3,13 @@ import React, { Component } from "react";
 import { t } from "ttag";
 import _ from "underscore";
 
-import {
-  SortableContainer,
-  SortableElement,
-} from "metabase/components/sortable";
 import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery";
 import { keyForColumn, findColumnForColumnSetting } from "metabase/lib/dataset";
 import { getFriendlyName } from "metabase/visualizations/lib/utils";
 
 import ColumnItem from "./ColumnItem";
 
-const SortableColumn = SortableElement(
-  ({ columnSetting, getColumnName, onEdit, onRemove }) => (
-    <ColumnItem
-      title={getColumnName(columnSetting)}
-      onEdit={onEdit ? () => onEdit(columnSetting) : null}
-      onRemove={onRemove ? () => onRemove(columnSetting) : null}
-      draggable
-    />
-  ),
-);
-
-const SortableColumnList = SortableContainer(
-  ({ columnSettings, getColumnName, onEdit, onRemove }) => {
-    return (
-      <div>
-        {columnSettings.map((columnSetting, index) => (
-          <SortableColumn
-            key={`item-${index}`}
-            index={columnSetting.index}
-            columnSetting={columnSetting}
-            getColumnName={getColumnName}
-            onEdit={onEdit}
-            onRemove={onRemove}
-          />
-        ))}
-      </div>
-    );
-  },
-);
+import { ChartSettingOrderedItems } from "./ChartSettingOrderedItems";
 
 export default class ChartSettingOrderedColumns extends Component {
   handleEnable = columnSetting => {
@@ -117,9 +85,9 @@ export default class ChartSettingOrderedColumns extends Component {
     return (
       <div className="list">
         {enabledColumns.length > 0 ? (
-          <SortableColumnList
-            columnSettings={enabledColumns}
-            getColumnName={this.getColumnName}
+          <ChartSettingOrderedItems
+            items={enabledColumns}
+            getItemName={this.getColumnName}
             onEdit={this.handleEdit}
             onRemove={this.handleDisable}
             onSortEnd={this.handleSortEnd}
diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedItems.tsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedItems.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0089a30cd531cf753fad7e58e5501cb75bfb0ead
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedItems.tsx
@@ -0,0 +1,125 @@
+import React, { ReactElement } from "react";
+
+import {
+  SortableContainer,
+  SortableElement,
+} from "metabase/components/sortable";
+
+import type { SortableElementProps } from "react-sortable-hoc";
+
+import ColumnItem from "./ColumnItem";
+
+interface SortableItem {
+  enabled: boolean;
+}
+
+interface SortableColumnFunctions<T> {
+  onRemove?: (item: T) => void;
+  onEdit?: (item: T) => void;
+  onClick?: (item: T) => void;
+  onAdd?: (item: T) => void;
+  onEnable?: (item: T) => void;
+  getItemName: (item: T) => string;
+}
+
+interface SortableColumnProps<T> extends SortableColumnFunctions<T> {
+  item: T;
+}
+
+const SortableColumn = SortableElement(function SortableColumn<
+  T extends SortableItem,
+>({
+  item,
+  getItemName,
+  onEdit,
+  onRemove,
+  onClick,
+  onAdd,
+  onEnable,
+}: SortableColumnProps<T>) {
+  return (
+    <ColumnItem
+      title={getItemName(item)}
+      onEdit={onEdit ? () => onEdit(item) : null}
+      onRemove={onRemove && item.enabled ? () => onRemove(item) : null}
+      onClick={onClick ? () => onClick(item) : null}
+      onAdd={onAdd ? () => onAdd(item) : null}
+      onEnable={onEnable && !item.enabled ? () => onEnable(item) : null}
+      draggable
+    />
+  );
+}) as unknown as <T extends SortableItem>(
+  props: SortableColumnProps<T> & SortableElementProps,
+) => ReactElement;
+
+interface SortableColumnListProps<T extends SortableItem>
+  extends SortableColumnFunctions<T> {
+  items: T[];
+}
+
+const SortableColumnList = SortableContainer(function SortableColumnList<
+  T extends SortableItem,
+>({
+  items,
+  getItemName,
+  onEdit,
+  onRemove,
+  onEnable,
+  onAdd,
+}: SortableColumnListProps<T>) {
+  return (
+    <div>
+      {items.map((item, index: number) => (
+        <SortableColumn
+          key={`item-${index}`}
+          index={index}
+          item={item}
+          getItemName={getItemName}
+          onEdit={onEdit}
+          onRemove={onRemove}
+          onEnable={onEnable}
+          onAdd={onAdd}
+        />
+      ))}
+    </div>
+  );
+});
+
+interface ChartSettingOrderedItemsProps<T extends SortableItem>
+  extends SortableColumnFunctions<T> {
+  onSortEnd: ({
+    oldIndex,
+    newIndex,
+  }: {
+    oldIndex: number;
+    newIndex: number;
+  }) => void;
+  items: T[];
+  distance: number;
+}
+
+export function ChartSettingOrderedItems<T extends SortableItem>({
+  onRemove,
+  onSortEnd,
+  onEdit,
+  onAdd,
+  onEnable,
+  onClick,
+  getItemName,
+  items,
+}: ChartSettingOrderedItemsProps<T>) {
+  return (
+    <SortableColumnList
+      helperClass="dragging"
+      items={items}
+      getItemName={getItemName}
+      onEdit={onEdit}
+      onRemove={onRemove}
+      onAdd={onAdd}
+      onEnable={onEnable}
+      onClick={onClick}
+      onSortEnd={onSortEnd}
+      distance={5}
+    />
+  );
+}
diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedRows.styled.tsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedRows.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a3ba39815dc0034b126cc6655a7b2ae756b30ee5
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedRows.styled.tsx
@@ -0,0 +1,18 @@
+import styled from "@emotion/styled";
+import { color } from "metabase/lib/colors";
+
+export const ChartSettingOrderedRowsRoot = styled.div`
+  margin-left: 0.5rem;
+`;
+
+export const ChartSettingMessage = styled.div`
+  margin: 1rem 0;
+  padding: 1rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: ${color("bg-light")};
+  color: ${color("text-light")};
+  font-weight: 700;
+  border-radius: 0.5rem;
+`;
diff --git a/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedRows.tsx b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedRows.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f572a148b27af6a8902ac544f91ad2139926922a
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/settings/ChartSettingOrderedRows.tsx
@@ -0,0 +1,71 @@
+import { updateIn } from "icepick";
+import React from "react";
+import { t } from "ttag";
+
+import { ChartSettingOrderedItems } from "./ChartSettingOrderedItems";
+
+import {
+  ChartSettingMessage,
+  ChartSettingOrderedRowsRoot,
+} from "./ChartSettingOrderedRows.styled";
+
+interface Row {
+  enabled: boolean;
+  rowIndex: number;
+  name: string;
+}
+
+interface ChartSettingOrderedRowsProps {
+  onChange: (rows: Row[]) => void;
+  rows: Row[];
+  value: Row[];
+}
+
+export const ChartSettingOrderedRows = ({
+  onChange,
+  rows,
+  value: orderedRows,
+}: ChartSettingOrderedRowsProps) => {
+  const handleDisable = (row: Row) => {
+    const index = orderedRows.findIndex(r => r.rowIndex === row.rowIndex);
+    onChange(
+      updateIn(orderedRows, [index], row => ({
+        ...row,
+        enabled: !row.enabled,
+      })),
+    );
+  };
+
+  const handleSortEnd = ({
+    oldIndex,
+    newIndex,
+  }: {
+    oldIndex: number;
+    newIndex: number;
+  }) => {
+    const rowsCopy = [...orderedRows];
+    rowsCopy.splice(newIndex, 0, rowsCopy.splice(oldIndex, 1)[0]);
+    onChange(rowsCopy);
+  };
+
+  const getRowTitle = (row: Row) => {
+    return rows.find(r => r.rowIndex === row.rowIndex)?.name || "Unknown";
+  };
+
+  return (
+    <ChartSettingOrderedRowsRoot>
+      {orderedRows.length > 0 ? (
+        <ChartSettingOrderedItems
+          items={orderedRows}
+          getItemName={getRowTitle}
+          onRemove={handleDisable}
+          onEnable={handleDisable}
+          onSortEnd={handleSortEnd}
+          distance={5}
+        />
+      ) : (
+        <ChartSettingMessage>{t`Nothing to order`}</ChartSettingMessage>
+      )}
+    </ChartSettingOrderedRowsRoot>
+  );
+};
diff --git a/frontend/src/metabase/visualizations/components/settings/ColumnItem.jsx b/frontend/src/metabase/visualizations/components/settings/ColumnItem.jsx
index 2dd9d42414486fdee36a74aad95b3c8403d9191f..448d7d9b1036fed66dee373e64f8b3994e136126 100644
--- a/frontend/src/metabase/visualizations/components/settings/ColumnItem.jsx
+++ b/frontend/src/metabase/visualizations/components/settings/ColumnItem.jsx
@@ -20,7 +20,15 @@ const ActionIcon = ({ icon, onClick }) => (
   />
 );
 
-const ColumnItem = ({ title, onAdd, onRemove, onClick, onEdit, draggable }) => (
+const ColumnItem = ({
+  title,
+  onAdd,
+  onRemove,
+  onClick,
+  onEdit,
+  onEnable,
+  draggable,
+}) => (
   <ColumnItemRoot draggable={draggable} onClick={onClick}>
     <ColumnItemContainer>
       {draggable && <ColumnItemDragHandle name="grabber2" />}
@@ -29,6 +37,7 @@ const ColumnItem = ({ title, onAdd, onRemove, onClick, onEdit, draggable }) => (
         {onEdit && <ActionIcon icon="ellipsis" onClick={onEdit} />}
         {onAdd && <ActionIcon icon="add" onClick={onAdd} />}
         {onRemove && <ActionIcon icon="eye_filled" onClick={onRemove} />}
+        {onEnable && <ActionIcon icon="eye_crossed_out" onClick={onEnable} />}
       </ColumnItemContent>
     </ColumnItemContainer>
   </ColumnItemRoot>
diff --git a/frontend/src/metabase/visualizations/components/settings/ColumnItem.styled.tsx b/frontend/src/metabase/visualizations/components/settings/ColumnItem.styled.tsx
index 693db2ecdd590dcea1858e39b54c767483b7db61..46579b6a2a34366e8bf1216a7d97dde4bf210b0f 100644
--- a/frontend/src/metabase/visualizations/components/settings/ColumnItem.styled.tsx
+++ b/frontend/src/metabase/visualizations/components/settings/ColumnItem.styled.tsx
@@ -12,6 +12,11 @@ export const ColumnItemRoot = styled.div`
   border-radius: 0.5rem;
   background: ${color("white")};
 
+  &.dragging {
+    cursor: grabbing;
+    pointer-events: auto !important;
+  }
+
   ${props =>
     props.draggable &&
     `
diff --git a/frontend/src/metabase/visualizations/visualizations/Funnel.jsx b/frontend/src/metabase/visualizations/visualizations/Funnel.jsx
index c7c5d7e01e18d83844d65009494ab2c950e4be5b..661fd58fc6c6fbc3e0de04ec39b56523401f2e82 100644
--- a/frontend/src/metabase/visualizations/visualizations/Funnel.jsx
+++ b/frontend/src/metabase/visualizations/visualizations/Funnel.jsx
@@ -26,6 +26,7 @@ import _ from "underscore";
 import cx from "classnames";
 
 import ChartCaption from "metabase/visualizations/components/ChartCaption";
+import { ChartSettingOrderedRows } from "metabase/visualizations/components/settings/ChartSettingOrderedRows";
 
 const propTypes = {
   headerIcon: PropTypes.shape(iconPropTypes),
@@ -109,6 +110,36 @@ export default class Funnel extends Component {
       useRawSeries: true,
       showColumnSetting: true,
     }),
+    "funnel.rows": {
+      section: t`Data`,
+      widget: ChartSettingOrderedRows,
+      isValid: (series, settings) => {
+        const funnelRows = settings["funnel.rows"];
+
+        if (!funnelRows || !_.isArray(funnelRows)) {
+          return false;
+        }
+        if (!funnelRows.every(setting => setting.rowIndex !== undefined)) {
+          return false;
+        }
+
+        return (
+          funnelRows.every(setting => series[setting.rowIndex]) &&
+          funnelRows.length === series.length
+        );
+      },
+
+      getDefault: transformedSeries => {
+        return transformedSeries.map(s => ({
+          name: s.card.name,
+          rowIndex: s.card.rowIndex,
+          enabled: true,
+        }));
+      },
+      getProps: transformedSeries => ({
+        rows: transformedSeries.map(s => s.card),
+      }),
+    },
     ...metricSetting("funnel.metric", {
       section: t`Data`,
       title: t`Measure`,
@@ -158,12 +189,13 @@ export default class Funnel extends Component {
       dimensionIndex >= 0 &&
       metricIndex >= 0
     ) {
-      return rows.map(row => ({
+      return rows.map((row, index) => ({
         card: {
           ...card,
           name: formatValue(row[dimensionIndex], {
             column: cols[dimensionIndex],
           }),
+          rowIndex: index,
           _transformed: true,
         },
         data: {