diff --git a/enterprise/frontend/src/metabase-enterprise/settings/selectors.ts b/enterprise/frontend/src/metabase-enterprise/settings/selectors.ts
index a8d316413d16088eab465503cedd77a1b2967cf7..523466cdbc7ab3cfff74c85dcae3ff3217b02b82 100644
--- a/enterprise/frontend/src/metabase-enterprise/settings/selectors.ts
+++ b/enterprise/frontend/src/metabase-enterprise/settings/selectors.ts
@@ -25,3 +25,7 @@ export const getIsWhiteLabeling = (state: EnterpriseState) =>
 export function getApplicationName(state: EnterpriseState) {
   return getSetting(state, "application-name");
 }
+
+export function getShowMetabaseLinks(state: EnterpriseState) {
+  return getSetting(state, "show-metabase-links");
+}
diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/MetabaseLinksToggleDescription.tsx b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/MetabaseLinksToggleDescription.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c982516bbb42bcfd930f4ca0e36ba3108a4335ee
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/MetabaseLinksToggleDescription.tsx
@@ -0,0 +1,27 @@
+import { t, jt } from "ttag";
+import { Anchor, Popover, Stack, Text } from "metabase/ui";
+
+export function MetabaseLinksToggleDescription() {
+  return jt`Control the visibility of links to Metabase documentation and Metabase references in your instance. ${(
+    <Popover key="popover" position="top-start">
+      <Popover.Target>
+        <Anchor style={{ userSelect: "none", cursor: "pointer" }}>
+          {t`Learn more`}
+        </Anchor>
+      </Popover.Target>
+      <Popover.Dropdown>
+        <Stack p="md" spacing="sm" maw={420}>
+          <Text size="sm">
+            {t`This affects all links in the product experience (outside of the admin panel) that point to Metabase.com URLs.`}
+          </Text>
+          <Text size="sm">
+            {t`When hidden, your users will lose the ability to troubleshoot and learn how to use features such as the Query and SQL Editors, among others.`}
+          </Text>
+          <Text size="sm">
+            {t`You might also want to customize the Application Name setting.`}
+          </Text>
+        </Stack>
+      </Popover.Dropdown>
+    </Popover>
+  )}`;
+}
diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/MetabaseLinksToggleWidget.tsx b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/MetabaseLinksToggleWidget.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2334c66c403fea2f33551b586ddcaa7f645f3be1
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/MetabaseLinksToggleWidget.tsx
@@ -0,0 +1,28 @@
+import { t } from "ttag";
+
+import { Switch } from "metabase/ui";
+
+interface MetabaseLinksToggleSetting {
+  value: boolean | null;
+  default: boolean;
+}
+
+interface MetabaseLinksToggleWidgetProps {
+  setting: MetabaseLinksToggleSetting;
+  onChange: (value: boolean) => void;
+}
+
+export function MetabaseLinksToggleWidget({
+  setting,
+  onChange,
+}: MetabaseLinksToggleWidgetProps) {
+  return (
+    <Switch
+      checked={setting.value ?? setting.default}
+      onChange={e => onChange(e.target.checked)}
+      labelPosition="left"
+      label={t`Show links and references`}
+      size="sm"
+    />
+  );
+}
diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/index.ts b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3f0d19f43c17ef2bf2587df5c43e1a050a23c83c
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/MetabaseLinksToggleWidget/index.ts
@@ -0,0 +1,2 @@
+export { MetabaseLinksToggleWidget } from "./MetabaseLinksToggleWidget";
+export { MetabaseLinksToggleDescription } from "./MetabaseLinksToggleDescription";
diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/index.js b/enterprise/frontend/src/metabase-enterprise/whitelabel/index.js
index a74dc901775fbcaac51120ef5e43bec8d9f500b7..8c3cb865fe5a7d2e84fab1818b6d841c87bc0109 100644
--- a/enterprise/frontend/src/metabase-enterprise/whitelabel/index.js
+++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/index.js
@@ -12,6 +12,7 @@ import {
   getApplicationName,
   getIsWhiteLabeling,
   getLoadingMessage,
+  getShowMetabaseLinks,
 } from "metabase-enterprise/settings/selectors";
 import MetabaseSettings from "metabase/lib/settings";
 
@@ -27,6 +28,10 @@ import LogoIcon from "./components/LogoIcon";
 import { updateColors } from "./lib/whitelabel";
 import { getLoadingMessageOptions } from "./lib/loading-message";
 import { HelpLinkSettings } from "./components/HelpLinkSettings";
+import {
+  MetabaseLinksToggleDescription,
+  MetabaseLinksToggleWidget,
+} from "./components/MetabaseLinksToggleWidget";
 
 if (hasPremiumFeature("whitelabel")) {
   PLUGIN_LANDING_PAGE.push(() => MetabaseSettings.get("landing-page"));
@@ -108,6 +113,12 @@ if (hasPremiumFeature("whitelabel")) {
           widget: LighthouseToggleWidget,
           defaultValue: true,
         },
+        {
+          key: "show-metabase-links",
+          display_name: t`Documentation and references`,
+          description: <MetabaseLinksToggleDescription />,
+          widget: MetabaseLinksToggleWidget,
+        },
       ],
     },
     ...sections,
@@ -125,4 +136,5 @@ if (hasPremiumFeature("whitelabel")) {
   PLUGIN_SELECTORS.getLoadingMessage = getLoadingMessage;
   PLUGIN_SELECTORS.getIsWhiteLabeling = getIsWhiteLabeling;
   PLUGIN_SELECTORS.getApplicationName = getApplicationName;
+  PLUGIN_SELECTORS.getShowMetabaseLinks = getShowMetabaseLinks;
 }
diff --git a/frontend/src/metabase-types/api/mocks/settings.ts b/frontend/src/metabase-types/api/mocks/settings.ts
index 10f42f32accf9bea9f44d074d900837babac155b..ecd5b75012caea99874168bdd63e1fbd54f4f0fe 100644
--- a/frontend/src/metabase-types/api/mocks/settings.ts
+++ b/frontend/src/metabase-types/api/mocks/settings.ts
@@ -200,6 +200,7 @@ export const createMockSettings = (
   "show-homepage-pin-message": false,
   "show-homepage-xrays": false,
   "show-lighthouse-illustration": true,
+  "show-metabase-links": true,
   "show-metabot": true,
   "site-locale": "en",
   "site-url": "http://localhost:3000",
diff --git a/frontend/src/metabase-types/api/settings.ts b/frontend/src/metabase-types/api/settings.ts
index 1f1b394fc34ce64d319685e5b12572e3fe7ffc8c..a358cf69002b5434fb83fedab2c85e0627e581f4 100644
--- a/frontend/src/metabase-types/api/settings.ts
+++ b/frontend/src/metabase-types/api/settings.ts
@@ -258,6 +258,7 @@ export interface Settings {
   "show-homepage-pin-message": boolean;
   "show-homepage-xrays": boolean;
   "show-lighthouse-illustration": boolean;
+  "show-metabase-links": boolean;
   "show-metabot": boolean;
   "site-locale": string;
   "site-uuid": string;
diff --git a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.styled.tsx b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.styled.tsx
index 2630b02d1e76bbeed787e249dae08e439ddd500b..02244169ff063da2a35eccaece5e7c028caa01fc 100644
--- a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.styled.tsx
+++ b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.styled.tsx
@@ -3,8 +3,6 @@ import styled from "@emotion/styled";
 import { space } from "metabase/styled-components/theme";
 import { color } from "metabase/lib/colors";
 
-import ExternalLink from "metabase/core/components/ExternalLink";
-
 export const ActionSettingsWrapper = styled.div`
   display: flex;
   height: 80vh;
@@ -81,15 +79,3 @@ export const ModalActions = styled.div`
   padding: 1rem;
   border-top: 1px solid ${color("border")};
 `;
-
-export const ExplainerText = styled.p`
-  margin-left: ${space(3)};
-  margin-right: ${space(3)};
-
-  color: ${color("text-medium")};
-`;
-
-export const BrandLinkWithLeftMargin = styled(ExternalLink)`
-  margin-left: ${space(1)};
-  color: ${color("brand")};
-`;
diff --git a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx
index ff394f4544724ba961caf99d0bf986bfdcbb35fc..8629dba0306fb037a765d8ccf5647fa4cc2cafd2 100644
--- a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx
+++ b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx
@@ -5,8 +5,6 @@ import { useMemo } from "react";
 import Button from "metabase/core/components/Button";
 import EmptyState from "metabase/components/EmptyState";
 
-import MetabaseSettings from "metabase/lib/settings";
-
 import { ConnectedActionPicker } from "metabase/actions/containers/ActionPicker";
 import { setActionForDashcard } from "metabase/dashboard/actions";
 
@@ -27,14 +25,13 @@ import {
   ActionSettingsLeft,
   ActionSettingsRight,
   ModalActions,
-  ExplainerText,
-  BrandLinkWithLeftMargin,
 } from "./ActionDashcardSettings.styled";
 import {
   getParameterDefaultValue,
   isParameterHidden,
   isParameterRequired,
 } from "./utils";
+import { ExplainerText } from "./ExplainerText";
 
 const mapDispatchToProps = {
   setActionForDashcard,
@@ -101,14 +98,7 @@ export function ActionDashcardSettings({
                 <ActionSettingsHeader>
                   {t`Where should the values for '${action.name}' come from?`}
                 </ActionSettingsHeader>
-                <ExplainerText>
-                  {t`You can either ask users to enter values, or use the value of a dashboard filter.`}
-                  <BrandLinkWithLeftMargin
-                    href={MetabaseSettings.docsUrl("dashboards/actions")}
-                  >
-                    {t`Learn more.`}
-                  </BrandLinkWithLeftMargin>
-                </ExplainerText>
+                <ExplainerText />
               </>
             )}
             <ParameterMapperContainer>
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/ExplainerText.styled.tsx b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/ExplainerText.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..663bb9c702a232829cb5964148c8bc9a6ae27421
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/ExplainerText.styled.tsx
@@ -0,0 +1,18 @@
+import styled from "@emotion/styled";
+
+import { space } from "metabase/styled-components/theme";
+import { color } from "metabase/lib/colors";
+
+import ExternalLink from "metabase/core/components/ExternalLink";
+
+export const ExplainerTextContainer = styled.p`
+  margin-left: ${space(3)};
+  margin-right: ${space(3)};
+
+  color: ${color("text-medium")};
+`;
+
+export const BrandLinkWithLeftMargin = styled(ExternalLink)`
+  margin-left: ${space(1)};
+  color: ${color("brand")};
+`;
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/ExplainerText.tsx b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/ExplainerText.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..39084ad8419a118a0e224c3f7e31d044beb055f9
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/ExplainerText.tsx
@@ -0,0 +1,25 @@
+import { t } from "ttag";
+import MetabaseSettings from "metabase/lib/settings";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+
+import {
+  ExplainerTextContainer,
+  BrandLinkWithLeftMargin,
+} from "./ExplainerText.styled";
+
+export function ExplainerText() {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+  return (
+    <ExplainerTextContainer>
+      {t`You can either ask users to enter values, or use the value of a dashboard filter.`}
+      {showMetabaseLinks && (
+        <BrandLinkWithLeftMargin
+          href={MetabaseSettings.docsUrl("dashboards/actions")}
+        >
+          {t`Learn more.`}
+        </BrandLinkWithLeftMargin>
+      )}
+    </ExplainerTextContainer>
+  );
+}
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/index.ts b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b2ac86a030087432e6dcb6ef5df5ed1c031a129e
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/index.ts
@@ -0,0 +1 @@
+export { ExplainerText } from "./ExplainerText";
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/common.unit.spec.ts b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df5c131bb25a99c3a0d8a34a9b54f580e69e5e3a
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/common.unit.spec.ts
@@ -0,0 +1,26 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("ExplainerText (OSS)", () => {
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "You can either ask users to enter values, or use the value of a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "You can either ask users to enter values, or use the value of a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/enterprise.unit.spec.ts b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..15ad40b1cebf23a17d9f1ed4a079f663767ef43f
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/enterprise.unit.spec.ts
@@ -0,0 +1,31 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("ExplainerText (EE without token)", () => {
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "You can either ask users to enter values, or use the value of a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "You can either ask users to enter values, or use the value of a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/premium.unit.spec.ts b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..49997db8083e66d9d86dd9d1890dcb6ca2f0d06f
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/premium.unit.spec.ts
@@ -0,0 +1,35 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("ExplainerText (EE with token)", () => {
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "You can either ask users to enter values, or use the value of a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+
+  it("should not render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "You can either ask users to enter values, or use the value of a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.queryByText("Learn more.")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/setup.tsx b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..999b37c32bbc9e94242d3c904fa56dea7aa1e286
--- /dev/null
+++ b/frontend/src/metabase/actions/components/ActionViz/ExplainerText/tests/setup.tsx
@@ -0,0 +1,32 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { ExplainerText } from "../ExplainerText";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<ExplainerText />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/Description.styled.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/Description.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c36bd51112abce70ebff3a2d12e7aeceb4f79593
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/Description.styled.tsx
@@ -0,0 +1,7 @@
+import styled from "@emotion/styled";
+
+import { color } from "metabase/lib/colors";
+
+export const InfoText = styled.div`
+  color: ${color("text-medium")};
+`;
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/Description.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/Description.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bd284eb846438832fc5ecdfd4c4adb6bb980f07a
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/Description.tsx
@@ -0,0 +1,28 @@
+import { jt, t } from "ttag";
+import ExternalLink from "metabase/core/components/ExternalLink";
+import { useSelector } from "metabase/lib/redux";
+import { getDocsUrl } from "metabase/selectors/settings";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { InfoText } from "./Description.styled";
+
+export function Description() {
+  const docsLink = useSelector(state =>
+    getDocsUrl(state, { page: "actions/custom" }),
+  );
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
+  return (
+    <InfoText>
+      {jt`Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.`}
+      {showMetabaseLinks && (
+        <>
+          {" "}
+          <ExternalLink
+            key="learn-more"
+            href={docsLink}
+          >{t`Learn more`}</ExternalLink>
+        </>
+      )}
+    </InfoText>
+  );
+}
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/index.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..48db91ad85a31d07b20f422f971b930a2d92550c
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/index.ts
@@ -0,0 +1 @@
+export { Description } from "./Description";
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/common.unit.spec.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6220e4cef6b7a2cfd6b45f38ce52843d13db3be4
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/common.unit.spec.ts
@@ -0,0 +1,26 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("FormCerator > Description (OSS)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/enterprise.unit.spec.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1de6c1b2f7992f48cb47b65a4cd491f8e5b9ae5d
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/enterprise.unit.spec.ts
@@ -0,0 +1,34 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  return baseSetup({
+    hasEnterprisePlugins: true,
+    ...opts,
+  });
+}
+
+describe("FormCerator > Description (EE without token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/premium.unit.spec.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4e6a549dd15a60cfed50fef4c03d57a02de53eed
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/premium.unit.spec.ts
@@ -0,0 +1,35 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  return baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("FormCerator > Description (EE with token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more")).toBeInTheDocument();
+  });
+
+  it("should not show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.queryByText("Learn more")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/setup.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..300a959e806c59402b77e979116c8c406b242e44
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/Description/test/setup.tsx
@@ -0,0 +1,32 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { Description } from "../Description";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<Description />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder.tsx
deleted file mode 100644
index 4b005b8a9858a3f61c25123ee4f6af4bf22ec84f..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { t } from "ttag";
-
-import { Icon } from "metabase/ui";
-
-import MetabaseSettings from "metabase/lib/settings";
-
-import {
-  EmptyFormPlaceholderWrapper,
-  ExplainerTitle,
-  ExplainerText,
-  ExplainerList,
-  ExplainerLink,
-  IconContainer,
-  TopRightIcon,
-} from "./FormCreator.styled";
-
-export const EmptyFormPlaceholder = () => (
-  <EmptyFormPlaceholderWrapper>
-    <IconContainer>
-      <Icon name="sql" size={62} />
-      <TopRightIcon name="insight" size={24} />
-    </IconContainer>
-    <ExplainerTitle>{t`Build custom forms and business logic.`}</ExplainerTitle>
-    <ExplainerText>
-      {t`Actions let you write parameterized SQL that writes back to your database. Actions can be attached to buttons on dashboards to create custom workflows. You can even publicly share the parameterized forms they generate to collect data.`}
-    </ExplainerText>
-    <ExplainerText>
-      {t`Here are a few ideas for what you can do with actions`}
-      <ExplainerList>
-        <li>{t`Create a customer feedback form and embed it on your website.`}</li>
-        <li>{t`Mark the customer you’re viewing in a dashboard as a VIP.`}</li>
-        <li>{t`Let team members remove redundant data.`}</li>
-      </ExplainerList>
-    </ExplainerText>
-    <ExplainerLink
-      href={MetabaseSettings.docsUrl("actions/custom")}
-    >{t`See an example`}</ExplainerLink>
-  </EmptyFormPlaceholderWrapper>
-);
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/EmptyFormPlaceholder.styled.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/EmptyFormPlaceholder.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..203cca7f3a8d1e35164914807883e838f2609c29
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/EmptyFormPlaceholder.styled.tsx
@@ -0,0 +1,62 @@
+import styled from "@emotion/styled";
+import { Icon } from "metabase/ui";
+import ExternalLink from "metabase/core/components/ExternalLink";
+
+import { color, lighten } from "metabase/lib/colors";
+import { space } from "metabase/styled-components/theme";
+
+export const EmptyFormPlaceholderWrapper = styled.div`
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  height: 100%;
+  padding: 3rem;
+`;
+
+export const ExplainerTitle = styled.h3`
+  margin-bottom: ${space(1)};
+`;
+
+export const ExplainerText = styled.div`
+  font-weight: 400;
+  line-height: 1.5rem;
+  color: ${color("text-medium")};
+  margin: ${space(1)} 0 0 0;
+`;
+
+export const ExplainerList = styled.ul`
+  list-style-type: disc;
+  margin-left: 1.5rem;
+
+  li {
+    font-weight: 400;
+    line-height: 24px;
+    color: ${color("text-medium")};
+    margin: 0;
+  }
+`;
+
+export const ExplainerLink = styled(ExternalLink)`
+  font-weight: 700;
+  margin-top: ${space(2)};
+
+  color: ${color("brand")};
+
+  &:hover {
+    color: ${lighten("brand", 0.1)};
+  }
+`;
+
+export const IconContainer = styled.div`
+  display: inline-block;
+  padding: 1.25rem;
+  position: relative;
+  color: ${color("brand")};
+  align-self: center;
+`;
+
+export const TopRightIcon = styled(Icon)`
+  position: absolute;
+  top: 0;
+  right: 0;
+`;
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/EmptyFormPlaceholder.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/EmptyFormPlaceholder.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e612e52c193fe4b0ddd840c3b07e0491c9692faf
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/EmptyFormPlaceholder.tsx
@@ -0,0 +1,46 @@
+import { t } from "ttag";
+
+import { Icon } from "metabase/ui";
+import MetabaseSettings from "metabase/lib/settings";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { useSelector } from "metabase/lib/redux";
+
+import {
+  EmptyFormPlaceholderWrapper,
+  ExplainerTitle,
+  ExplainerText,
+  ExplainerList,
+  ExplainerLink,
+  IconContainer,
+  TopRightIcon,
+} from "./EmptyFormPlaceholder.styled";
+
+export const EmptyFormPlaceholder = () => {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
+  return (
+    <EmptyFormPlaceholderWrapper>
+      <IconContainer>
+        <Icon name="sql" size={62} />
+        <TopRightIcon name="insight" size={24} />
+      </IconContainer>
+      <ExplainerTitle>{t`Build custom forms and business logic.`}</ExplainerTitle>
+      <ExplainerText>
+        {t`Actions let you write parameterized SQL that writes back to your database. Actions can be attached to buttons on dashboards to create custom workflows. You can even publicly share the parameterized forms they generate to collect data.`}
+      </ExplainerText>
+      <ExplainerText>
+        {t`Here are a few ideas for what you can do with actions`}
+        <ExplainerList>
+          <li>{t`Create a customer feedback form and embed it on your website.`}</li>
+          <li>{t`Mark the customer you’re viewing in a dashboard as a VIP.`}</li>
+          <li>{t`Let team members remove redundant data.`}</li>
+        </ExplainerList>
+      </ExplainerText>
+      {showMetabaseLinks && (
+        <ExplainerLink
+          href={MetabaseSettings.docsUrl("actions/custom")}
+        >{t`See an example`}</ExplainerLink>
+      )}
+    </EmptyFormPlaceholderWrapper>
+  );
+};
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/index.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e845489954472513928b52a351f7b91205ab18d2
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/index.ts
@@ -0,0 +1 @@
+export { EmptyFormPlaceholder } from "./EmptyFormPlaceholder";
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/common.unit.spec.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..020d21316c7dff4789699caefc0fe88f33c625af
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/common.unit.spec.ts
@@ -0,0 +1,20 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("EmptyFormPlaceholder (OSS)", () => {
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+    expect(
+      screen.getByText("Build custom forms and business logic."),
+    ).toBeInTheDocument();
+    expect(screen.getByText("See an example")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+    expect(
+      screen.getByText("Build custom forms and business logic."),
+    ).toBeInTheDocument();
+    expect(screen.getByText("See an example")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/enterprise.unit.spec.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..412afc57015baa618b5e31ea72a4bb3b7969c106
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/enterprise.unit.spec.ts
@@ -0,0 +1,28 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    ...opts,
+  });
+}
+
+describe("EmptyFormPlaceholder (EE without token)", () => {
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+    expect(
+      screen.getByText("Build custom forms and business logic."),
+    ).toBeInTheDocument();
+    expect(screen.getByText("See an example")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+    expect(
+      screen.getByText("Build custom forms and business logic."),
+    ).toBeInTheDocument();
+    expect(screen.getByText("See an example")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/premium.unit.spec.ts b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b886f6f8f7172f9d3c65b096bc872a38dff822b5
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/premium.unit.spec.ts
@@ -0,0 +1,31 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: {
+      whitelabel: true,
+    },
+    ...opts,
+  });
+}
+
+describe("EmptyFormPlaceholder (EE with token)", () => {
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+    expect(
+      screen.getByText("Build custom forms and business logic."),
+    ).toBeInTheDocument();
+    expect(screen.getByText("See an example")).toBeInTheDocument();
+  });
+
+  it("should not render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+    expect(
+      screen.getByText("Build custom forms and business logic."),
+    ).toBeInTheDocument();
+    expect(screen.queryByText("See an example")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/setup.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4fbdcdf381909125f7f8a1745dff4b81430b0b0e
--- /dev/null
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/EmptyFormPlaceholder/tests/setup.tsx
@@ -0,0 +1,33 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { EmptyFormPlaceholder } from "../EmptyFormPlaceholder";
+
+export interface SetupOpts {
+  applicationName?: string;
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<EmptyFormPlaceholder />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.styled.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.styled.tsx
index de0fdcbad2d86de3e0c31ae9959e55e31aa19e06..7241217f96703c84c5676e59ad5bd192500ae24b 100644
--- a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.styled.tsx
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.styled.tsx
@@ -1,8 +1,6 @@
 import styled from "@emotion/styled";
-import { Icon } from "metabase/ui";
-import ExternalLink from "metabase/core/components/ExternalLink";
 
-import { color, lighten, alpha } from "metabase/lib/colors";
+import { color, alpha } from "metabase/lib/colors";
 import { space } from "metabase/styled-components/theme";
 
 export const FormContainer = styled.div`
@@ -18,72 +16,12 @@ export const FormFieldEditorDragContainer = styled.div`
   margin-bottom: ${space(1)};
 `;
 
-export const InfoText = styled.div`
-  color: ${color("text-medium")};
-`;
-
 export const FieldSettingsButtonsContainer = styled.div`
   display: flex;
   align-items: center;
   gap: ${space(1)};
 `;
 
-export const EmptyFormPlaceholderWrapper = styled.div`
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  height: 100%;
-  padding: 3rem;
-`;
-
-export const ExplainerTitle = styled.h3`
-  margin-bottom: ${space(1)};
-`;
-
-export const ExplainerText = styled.div`
-  font-weight: 400;
-  line-height: 1.5rem;
-  color: ${color("text-medium")};
-  margin: ${space(1)} 0 0 0;
-`;
-
-export const ExplainerList = styled.ul`
-  list-style-type: disc;
-  margin-left: 1.5rem;
-
-  li {
-    font-weight: 400;
-    line-height: 24px;
-    color: ${color("text-medium")};
-    margin: 0;
-  }
-`;
-
-export const ExplainerLink = styled(ExternalLink)`
-  font-weight: 700;
-  margin-top: ${space(2)};
-
-  color: ${color("brand")};
-
-  &:hover {
-    color: ${lighten("brand", 0.1)};
-  }
-`;
-
-export const IconContainer = styled.div`
-  display: inline-block;
-  padding: 1.25rem;
-  position: relative;
-  color: ${color("brand")};
-  align-self: center;
-`;
-
-export const TopRightIcon = styled(Icon)`
-  position: absolute;
-  top: 0;
-  right: 0;
-`;
-
 export const WarningBanner = styled.div`
   padding: ${space(2)};
   border: 1px solid ${color("warning")};
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.tsx
index 8e6498b2847a4886b5082c0bec688ff546a08381..04da8e5ff695fbe1015994aec2310e20ed61ce02 100644
--- a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.tsx
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.tsx
@@ -1,5 +1,5 @@
 import { useEffect, useCallback, useMemo, useState } from "react";
-import { jt, t } from "ttag";
+import { t } from "ttag";
 import _ from "underscore";
 import { Droppable, Draggable } from "react-beautiful-dnd";
 
@@ -10,11 +10,8 @@ import type {
 } from "react-beautiful-dnd";
 
 import { DragDropContext } from "metabase/core/components/DragDropContext";
-import ExternalLink from "metabase/core/components/ExternalLink";
 import { Form, FormProvider } from "metabase/forms";
 
-import MetabaseSettings from "metabase/lib/settings";
-
 import SidebarContent from "metabase/query_builder/components/SidebarContent";
 
 import type {
@@ -37,9 +34,9 @@ import FormFieldEditor from "./FormFieldEditor";
 import {
   FormContainer,
   FormFieldEditorDragContainer,
-  InfoText,
   WarningBanner,
 } from "./FormCreator.styled";
+import { Description } from "./Description";
 
 // FormEditor's can't be submitted as it serves as a form preview
 const ON_SUBMIT_NOOP = _.noop;
@@ -142,13 +139,6 @@ export function FormCreator({
 
   const fieldSettings = formSettings.fields || {};
 
-  const docsLink = (
-    <ExternalLink
-      key="learn-more"
-      href={MetabaseSettings.docsUrl("actions/custom")}
-    >{t`Learn more`}</ExternalLink>
-  );
-
   const showWarning = form.fields.some(field => {
     const settings = fieldSettings[field.name];
 
@@ -172,9 +162,7 @@ export function FormCreator({
   return (
     <SidebarContent title={t`Action parameters`}>
       <FormContainer>
-        <InfoText>
-          {jt`Configure your parameters' types and properties here. The values for these parameters can come from user input, or from a dashboard filter. ${docsLink}`}
-        </InfoText>
+        <Description />
         {showWarning && (
           <WarningBanner>
             <b>{t`Heads up.`}</b>{" "}
diff --git a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.unit.spec.tsx b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.unit.spec.tsx
index 137565f3049177ee68d66a6145074c6c64b62e78..d5cc5871d1fd7f55af433af8fd4f8aa9f74bb5c8 100644
--- a/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.unit.spec.tsx
+++ b/frontend/src/metabase/actions/containers/ActionCreator/FormCreator/FormCreator.unit.spec.tsx
@@ -1,6 +1,6 @@
-import { render, screen } from "@testing-library/react";
 import userEvent from "@testing-library/user-event";
 
+import { renderWithProviders, screen } from "__support__/ui";
 import type {
   ActionFormSettings,
   FieldSettings,
@@ -50,7 +50,7 @@ type SetupOpts = {
 const setup = ({ parameters, formSettings, actionType }: SetupOpts) => {
   const onChange = jest.fn();
 
-  render(
+  renderWithProviders(
     <FormCreator
       parameters={parameters}
       formSettings={formSettings}
diff --git a/frontend/src/metabase/components/ErrorMessage/ErrorMessage.jsx b/frontend/src/metabase/components/ErrorMessage/ErrorMessage.tsx
similarity index 56%
rename from frontend/src/metabase/components/ErrorMessage/ErrorMessage.jsx
rename to frontend/src/metabase/components/ErrorMessage/ErrorMessage.tsx
index 33336be3b335d82bb48bf6f070d61d15d6675594..f7b692e113876e8a7c4637946a66ef576f9202c1 100644
--- a/frontend/src/metabase/components/ErrorMessage/ErrorMessage.jsx
+++ b/frontend/src/metabase/components/ErrorMessage/ErrorMessage.tsx
@@ -1,12 +1,22 @@
-/* eslint "react/prop-types": "warn" */
-
-import PropTypes from "prop-types";
-
 import cx from "classnames";
+import type { ReactNode } from "react";
 
-// NOTE: currently relies on .QueryError CSS selectors residing in query_builder.css
+interface ErrorMessageProps {
+  title: string;
+  type: string;
+  message: string;
+  action: ReactNode;
+  className?: string;
+}
 
-const ErrorMessage = ({ title, type, message, action, className }) => {
+// NOTE: currently relies on .QueryError CSS selectors residing in query_builder.css
+export const ErrorMessage = ({
+  title,
+  type,
+  message,
+  action,
+  className,
+}: ErrorMessageProps) => {
   return (
     <div className={cx(className, "QueryError flex align-center")}>
       <div className={`QueryError-image QueryError-image--${type}`} />
@@ -18,13 +28,3 @@ const ErrorMessage = ({ title, type, message, action, className }) => {
     </div>
   );
 };
-
-ErrorMessage.propTypes = {
-  title: PropTypes.string.isRequired,
-  type: PropTypes.string.isRequired,
-  message: PropTypes.string.isRequired,
-  action: PropTypes.node,
-  className: PropTypes.string,
-};
-
-export default ErrorMessage;
diff --git a/frontend/src/metabase/components/ErrorMessage/index.jsx b/frontend/src/metabase/components/ErrorMessage/index.jsx
index 3b2ac0c7fbc5eb9dde8b957844ec67a577b5d327..f93a084d069f9ac2b5d543839f271375787f8897 100644
--- a/frontend/src/metabase/components/ErrorMessage/index.jsx
+++ b/frontend/src/metabase/components/ErrorMessage/index.jsx
@@ -1 +1 @@
-export { default } from "./ErrorMessage";
+export { ErrorMessage } from "./ErrorMessage";
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.jsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.jsx
index 0aed25820778ad4eb42fba5ef647f3afc5070295..95c890608639ce1c56dd52647c9eb9561cefeb97 100644
--- a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.jsx
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.jsx
@@ -13,12 +13,10 @@ import { Icon } from "metabase/ui";
 import Tooltip from "metabase/core/components/Tooltip";
 import TippyPopover from "metabase/components/Popover/TippyPopover";
 
-import MetabaseSettings from "metabase/lib/settings";
 import { getMetadata } from "metabase/selectors/metadata";
 
 import ParameterTargetList from "metabase/parameters/components/ParameterTargetList";
 import {
-  getNativeDashCardEmptyMappingText,
   isNativeDashCard,
   isVirtualDashCard,
   getVirtualCardType,
@@ -50,11 +48,8 @@ import {
   ChevrondownIcon,
   KeyIcon,
   Warning,
-  NativeCardDefault,
-  NativeCardIcon,
-  NativeCardText,
-  NativeCardLink,
 } from "./DashCardCardParameterMapper.styled";
+import { DisabledNativeCardHelpText } from "./DisabledNativeCardHelpText";
 
 function formatSelected({ name, sectionName }) {
   if (sectionName == null) {
@@ -234,17 +229,7 @@ export function DashCardCardParameterMapper({
           </TextCardDefault>
         )
       ) : isNative && isDisabled ? (
-        <NativeCardDefault>
-          <NativeCardIcon name="info" />
-          <NativeCardText>
-            {getNativeDashCardEmptyMappingText(editingParameter)}
-          </NativeCardText>
-          <NativeCardLink
-            href={MetabaseSettings.docsUrl(
-              "questions/native-editor/sql-parameters",
-            )}
-          >{t`Learn how`}</NativeCardLink>
-        </NativeCardDefault>
+        <DisabledNativeCardHelpText parameter={editingParameter} />
       ) : (
         <>
           {headerContent && (
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.styled.tsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.styled.tsx
index db01b29a164a7fbee9bb782ccec947b52d716443..3bc54f9a9610278cd55b0d0918f78c98e0866c97 100644
--- a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.styled.tsx
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.styled.tsx
@@ -5,7 +5,6 @@ import { space } from "metabase/styled-components/theme";
 import { alpha, color } from "metabase/lib/colors";
 import { Icon } from "metabase/ui";
 import Button from "metabase/core/components/Button";
-import ExternalLink from "metabase/core/components/ExternalLink";
 
 export const Container = styled.div<{ isSmall: boolean }>`
   margin: ${({ isSmall }) => (isSmall ? 0 : space(1))} 0;
@@ -25,32 +24,6 @@ export const TextCardDefault = styled.div`
   line-height: 1.5rem;
 `;
 
-export const NativeCardDefault = styled.div`
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-`;
-
-export const NativeCardIcon = styled(Icon)`
-  color: ${color("text-medium")};
-  margin-bottom: 0.5rem;
-  width: 1.25rem;
-  height: 1.25rem;
-`;
-
-export const NativeCardText = styled.div`
-  color: ${color("text-dark")};
-  max-width: 15rem;
-  text-align: center;
-  line-height: 1.5rem;
-`;
-
-export const NativeCardLink = styled(ExternalLink)`
-  color: ${color("brand")};
-  font-weight: bold;
-  margin-top: 0.5rem;
-`;
-
 export const CardLabel = styled.div`
   font-size: 0.83em;
   margin-bottom: ${space(1)};
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.unit.spec.jsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.unit.spec.jsx
index b7b3c3a1b6a62d3e0265d7de91ac94a3a095aee1..04c3191dc5355e64995283e98369cffa5411b886 100644
--- a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.unit.spec.jsx
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DashCardCardParameterMapper.unit.spec.jsx
@@ -1,5 +1,4 @@
-import { render, screen } from "@testing-library/react";
-import { getIcon } from "__support__/ui";
+import { getIcon, renderWithProviders, screen } from "__support__/ui";
 
 import {
   createMockCard,
@@ -33,7 +32,7 @@ const state = createMockState({
 const metadata = getMetadata(state); // metabase-lib Metadata instance
 
 const setup = options => {
-  render(
+  renderWithProviders(
     <DashCardCardParameterMapper
       card={createMockCard()}
       dashcard={createMockDashboardCard()}
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/DisabledNativeCardHelpText.styled.tsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/DisabledNativeCardHelpText.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9d0ddc81c3cc527bb32d83c77cb1c4851b1e0945
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/DisabledNativeCardHelpText.styled.tsx
@@ -0,0 +1,31 @@
+import styled from "@emotion/styled";
+
+import { color } from "metabase/lib/colors";
+import { Icon } from "metabase/ui";
+import ExternalLink from "metabase/core/components/ExternalLink";
+
+export const NativeCardDefault = styled.div`
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+`;
+
+export const NativeCardIcon = styled(Icon)`
+  color: ${color("text-medium")};
+  margin-bottom: 0.5rem;
+  width: 1.25rem;
+  height: 1.25rem;
+`;
+
+export const NativeCardText = styled.div`
+  color: ${color("text-dark")};
+  max-width: 15rem;
+  text-align: center;
+  line-height: 1.5rem;
+`;
+
+export const NativeCardLink = styled(ExternalLink)`
+  color: ${color("brand")};
+  font-weight: bold;
+  margin-top: 0.5rem;
+`;
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/DisabledNativeCardHelpText.tsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/DisabledNativeCardHelpText.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..aca82b39723bbf547cdfc84fbfb6838eba548ffc
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/DisabledNativeCardHelpText.tsx
@@ -0,0 +1,38 @@
+import { t } from "ttag";
+import MetabaseSettings from "metabase/lib/settings";
+import { getNativeDashCardEmptyMappingText } from "metabase/dashboard/utils";
+import type { Parameter } from "metabase-types/api";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import {
+  NativeCardDefault,
+  NativeCardIcon,
+  NativeCardText,
+  NativeCardLink,
+} from "./DisabledNativeCardHelpText.styled";
+
+interface DisabledNativeCardHelpTextProps {
+  parameter: Parameter;
+}
+
+export function DisabledNativeCardHelpText({
+  parameter,
+}: DisabledNativeCardHelpTextProps) {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
+  return (
+    <NativeCardDefault>
+      <NativeCardIcon name="info" />
+      <NativeCardText>
+        {getNativeDashCardEmptyMappingText(parameter)}
+      </NativeCardText>
+      {showMetabaseLinks && (
+        <NativeCardLink
+          href={MetabaseSettings.docsUrl(
+            "questions/native-editor/sql-parameters",
+          )}
+        >{t`Learn how`}</NativeCardLink>
+      )}
+    </NativeCardDefault>
+  );
+}
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/index.ts b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..44e974328386f12b7dce7886725789f5f47d4915
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/index.ts
@@ -0,0 +1 @@
+export { DisabledNativeCardHelpText } from "./DisabledNativeCardHelpText";
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/common.unit.spec.ts b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..496a76b29a98d6ce70f318a45a9ee2ccc86154a0
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/common.unit.spec.ts
@@ -0,0 +1,26 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("DashCardParameterMapper > DisabledNativeCardHelpText (OSS)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Add a string variable to this question to connect it to a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn how")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Add a string variable to this question to connect it to a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn how")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/enterprise.unit.spec.ts b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ad053393d356ed83bca5acc1cd17b16bd4b25413
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/enterprise.unit.spec.ts
@@ -0,0 +1,31 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("DashCardParameterMapper > DisabledNativeCardHelpText (EE without token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Add a string variable to this question to connect it to a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn how")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Add a string variable to this question to connect it to a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn how")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/premium.unit.spec.ts b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9c3ef03470ee98c1841f3580d8ee6c57a7478bdf
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/premium.unit.spec.ts
@@ -0,0 +1,35 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("DashCardParameterMapper > DisabledNativeCardHelpText (EE with token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Add a string variable to this question to connect it to a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn how")).toBeInTheDocument();
+  });
+
+  it("should not show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Add a string variable to this question to connect it to a dashboard filter.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.queryByText("Learn how")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/setup.tsx b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6f41c541aab0b441b9afe521a62964f74b834ec5
--- /dev/null
+++ b/frontend/src/metabase/dashboard/components/DashCard/DashCardParameterMapper/DisabledNativeCardHelpText/tests/setup.tsx
@@ -0,0 +1,38 @@
+import type { TokenFeatures } from "metabase-types/api";
+import {
+  createMockParameter,
+  createMockTokenFeatures,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { DisabledNativeCardHelpText } from "../DisabledNativeCardHelpText";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(
+    <DisabledNativeCardHelpText parameter={createMockParameter()} />,
+    { storeInitialState: state },
+  );
+};
diff --git a/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.tsx b/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.tsx
index 4b57cc912572c9c0ba1384140d1a77363f405929..bdd836481d4e1ffbdae39a53ae6bea175fb2860d 100644
--- a/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.tsx
+++ b/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.tsx
@@ -2,12 +2,21 @@ import { t } from "ttag";
 import MetabaseSettings from "metabase/lib/settings";
 import { useUniqueId } from "metabase/hooks/use-unique-id";
 import { useSelector } from "metabase/lib/redux";
-import { getApplicationName } from "metabase/selectors/whitelabel";
+import {
+  getApplicationName,
+  getShowMetabaseLinks,
+} from "metabase/selectors/whitelabel";
 import { CardIcon, CardRoot, CardTitle } from "./HomeHelpCard.styled";
 
-export const HomeHelpCard = (): JSX.Element => {
+export const HomeHelpCard = (): JSX.Element | null => {
   const cardTitleId = useUniqueId();
   const applicationName = useSelector(getApplicationName);
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
+  if (!showMetabaseLinks) {
+    return null;
+  }
+
   return (
     <CardRoot href={MetabaseSettings.learnUrl()} aria-labelledby={cardTitleId}>
       <CardIcon name="reference" />
diff --git a/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.unit.spec.tsx b/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.unit.spec.tsx
deleted file mode 100644
index 42ee56e4aef5610aca1470ae563d3d6244074f20..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/home/components/HomeHelpCard/HomeHelpCard.unit.spec.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { renderWithProviders, screen } from "__support__/ui";
-import { HomeHelpCard } from "./HomeHelpCard";
-
-const setup = () => {
-  renderWithProviders(<HomeHelpCard />);
-};
-
-describe("HomeHelpCard", () => {
-  it("should render correctly", () => {
-    setup();
-    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
-  });
-});
diff --git a/frontend/src/metabase/home/components/HomeHelpCard/tests/common.unit.spec.tsx b/frontend/src/metabase/home/components/HomeHelpCard/tests/common.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..75f25880301e3c28820475d1b5895ec030e2b950
--- /dev/null
+++ b/frontend/src/metabase/home/components/HomeHelpCard/tests/common.unit.spec.tsx
@@ -0,0 +1,19 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("HomeHelpCard (OSS)", () => {
+  it("should show Metabase despite customizing the application name", () => {
+    setup({ applicationName: "My app analytics" });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/home/components/HomeHelpCard/tests/enterprise.unit.spec.tsx b/frontend/src/metabase/home/components/HomeHelpCard/tests/enterprise.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c98e7cb4ae3c66c3cb76c969b730c6aede5c4852
--- /dev/null
+++ b/frontend/src/metabase/home/components/HomeHelpCard/tests/enterprise.unit.spec.tsx
@@ -0,0 +1,24 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts = {}) {
+  return baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("HomeHelpCard (EE without token)", () => {
+  it("should show Metabase despite customizing the application name", () => {
+    setup({ applicationName: "My app analytics" });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/home/components/HomeHelpCard/tests/premium.unit.spec.tsx b/frontend/src/metabase/home/components/HomeHelpCard/tests/premium.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d1d4ff9de74885b07fe6924d098068b988caf1f7
--- /dev/null
+++ b/frontend/src/metabase/home/components/HomeHelpCard/tests/premium.unit.spec.tsx
@@ -0,0 +1,28 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts = {}) {
+  return baseSetup({
+    hasEnterprisePlugins: true,
+    ...opts,
+    tokenFeatures: { whitelabel: true },
+  });
+}
+
+describe("HomeHelpCard (EE with token)", () => {
+  it("should show the customized application name", () => {
+    setup({ applicationName: "My app analytics" });
+    expect(screen.getByText("My app analytics tips")).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+    expect(screen.getByText("Metabase tips")).toBeInTheDocument();
+  });
+
+  it("should not render help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+    expect(screen.queryByText("Metabase tips")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/home/components/HomeHelpCard/tests/setup.tsx b/frontend/src/metabase/home/components/HomeHelpCard/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6c44b7d61f1a38583226f9494d6615ec5cc4e0d1
--- /dev/null
+++ b/frontend/src/metabase/home/components/HomeHelpCard/tests/setup.tsx
@@ -0,0 +1,35 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { HomeHelpCard } from "../HomeHelpCard";
+
+export interface SetupOpts {
+  applicationName?: string;
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  applicationName = "Metabase",
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "application-name": applicationName,
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<HomeHelpCard />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/models/containers/NewModelOptions/NewModelOptions.tsx b/frontend/src/metabase/models/containers/NewModelOptions/NewModelOptions.tsx
index 0df4de706440359bf26d30046a5070d84bc2f61a..354674be3e724bb0b5005ef2f5dd9cc56bbefc3f 100644
--- a/frontend/src/metabase/models/containers/NewModelOptions/NewModelOptions.tsx
+++ b/frontend/src/metabase/models/containers/NewModelOptions/NewModelOptions.tsx
@@ -12,6 +12,7 @@ import { getHasDataAccess, getHasNativeWrite } from "metabase/selectors/data";
 
 import { useSelector } from "metabase/lib/redux";
 import { NoDatabasesEmptyState } from "metabase/reference/databases/NoDatabasesEmptyState";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
 import type Database from "metabase-lib/metadata/Database";
 import {
   OptionsGridItem,
@@ -38,6 +39,8 @@ const NewModelOptions = (props: NewModelOptionsProps) => {
     props.location.query.collectionId as string,
   );
 
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
   if (!hasDataAccess && !hasNativeWrite) {
     return (
       <div className="full-height flex align-center justify-center">
@@ -89,13 +92,15 @@ const NewModelOptions = (props: NewModelOptionsProps) => {
         )}
       </Grid>
 
-      <EducationalButton
-        target="_blank"
-        href={EDUCATIONAL_LINK}
-        className="mt4"
-      >
-        {t`What's a model?`}
-      </EducationalButton>
+      {showMetabaseLinks && (
+        <EducationalButton
+          target="_blank"
+          href={EDUCATIONAL_LINK}
+          className="mt4"
+        >
+          {t`What's a model?`}
+        </EducationalButton>
+      )}
     </OptionsRoot>
   );
 };
diff --git a/frontend/src/metabase/models/containers/NewModelOptions/tests/common.unit.spec.tsx b/frontend/src/metabase/models/containers/NewModelOptions/tests/common.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..35ab0754a895a27623960d9213f42fc22256667d
--- /dev/null
+++ b/frontend/src/metabase/models/containers/NewModelOptions/tests/common.unit.spec.tsx
@@ -0,0 +1,39 @@
+import { screen } from "__support__/ui";
+import { createMockDatabase } from "metabase-types/api/mocks";
+
+import { setup } from "./setup";
+
+describe("NewModelOptions (OSS)", () => {
+  it("should render no data access notice when instance have no database access", async () => {
+    setup({ databases: [] });
+
+    expect(
+      await screen.findByText("Metabase is no fun without any data"),
+    ).toBeInTheDocument();
+  });
+
+  describe("has data access", () => {
+    it("should render options for creating a model", async () => {
+      setup({ databases: [createMockDatabase()] });
+
+      expect(
+        await screen.findByText("Use the notebook editor"),
+      ).toBeInTheDocument();
+      expect(await screen.findByText("Use a native query")).toBeInTheDocument();
+    });
+
+    describe("whitelabel feature", () => {
+      it("should render help link when `show-metabase-links: false`", async () => {
+        setup({ databases: [createMockDatabase()], showMetabaseLinks: false });
+
+        expect(await screen.findByText("What's a model?")).toBeInTheDocument();
+      });
+
+      it("should render help link when `show-metabase-links: true`", async () => {
+        setup({ databases: [createMockDatabase()], showMetabaseLinks: true });
+
+        expect(await screen.findByText("What's a model?")).toBeInTheDocument();
+      });
+    });
+  });
+});
diff --git a/frontend/src/metabase/models/containers/NewModelOptions/tests/enterprise.unit.spec.tsx b/frontend/src/metabase/models/containers/NewModelOptions/tests/enterprise.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..98c25aad05a77357eef3abfb91625628a0f55290
--- /dev/null
+++ b/frontend/src/metabase/models/containers/NewModelOptions/tests/enterprise.unit.spec.tsx
@@ -0,0 +1,44 @@
+import { screen } from "__support__/ui";
+import { createMockDatabase } from "metabase-types/api/mocks";
+
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("NewModelOptions (EE without token)", () => {
+  it("should render no data access notice when instance have no database access", async () => {
+    setup({ databases: [] });
+
+    expect(
+      await screen.findByText("Metabase is no fun without any data"),
+    ).toBeInTheDocument();
+  });
+
+  describe("has data access", () => {
+    it("should render options for creating a model", async () => {
+      setup({ databases: [createMockDatabase()] });
+
+      expect(
+        await screen.findByText("Use the notebook editor"),
+      ).toBeInTheDocument();
+      expect(await screen.findByText("Use a native query")).toBeInTheDocument();
+    });
+
+    describe("whitelabel feature", () => {
+      it("should render help link when `show-metabase-links: false`", async () => {
+        setup({ databases: [createMockDatabase()], showMetabaseLinks: false });
+
+        expect(await screen.findByText("What's a model?")).toBeInTheDocument();
+      });
+
+      it("should render help link when `show-metabase-links: true`", async () => {
+        setup({ databases: [createMockDatabase()], showMetabaseLinks: true });
+
+        expect(await screen.findByText("What's a model?")).toBeInTheDocument();
+      });
+    });
+  });
+});
diff --git a/frontend/src/metabase/models/containers/NewModelOptions/tests/premium.unit.spec.tsx b/frontend/src/metabase/models/containers/NewModelOptions/tests/premium.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..86a759a40f49fd749f6084b0835c2751da252d80
--- /dev/null
+++ b/frontend/src/metabase/models/containers/NewModelOptions/tests/premium.unit.spec.tsx
@@ -0,0 +1,51 @@
+import { screen } from "__support__/ui";
+import { createMockDatabase } from "metabase-types/api/mocks";
+
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("NewModelOptions (EE with token)", () => {
+  it("should render no data access notice when instance have no database access", async () => {
+    setup({ databases: [] });
+
+    expect(
+      await screen.findByText("Metabase is no fun without any data"),
+    ).toBeInTheDocument();
+  });
+
+  describe("has data access", () => {
+    it("should render options for creating a model", async () => {
+      setup({ databases: [createMockDatabase()] });
+
+      expect(
+        await screen.findByText("Use the notebook editor"),
+      ).toBeInTheDocument();
+      expect(await screen.findByText("Use a native query")).toBeInTheDocument();
+    });
+
+    describe("whitelabel feature", () => {
+      it("should not render help link when `show-metabase-links: false`", async () => {
+        setup({ databases: [createMockDatabase()], showMetabaseLinks: false });
+
+        expect(
+          await screen.findByText("Use the notebook editor"),
+        ).toBeInTheDocument();
+        expect(screen.queryByText("What's a model?")).not.toBeInTheDocument();
+      });
+
+      it("should render help link when `show-metabase-links: true`", async () => {
+        setup({ databases: [createMockDatabase()], showMetabaseLinks: true });
+
+        expect(await screen.findByText("What's a model?")).toBeInTheDocument();
+      });
+    });
+  });
+});
diff --git a/frontend/src/metabase/models/containers/NewModelOptions/tests/setup.tsx b/frontend/src/metabase/models/containers/NewModelOptions/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7163269e0024b7018e148ffe926c6dce21c2d28d
--- /dev/null
+++ b/frontend/src/metabase/models/containers/NewModelOptions/tests/setup.tsx
@@ -0,0 +1,42 @@
+import { Route } from "react-router";
+import type { Database, TokenFeatures } from "metabase-types/api";
+import { setupDatabasesEndpoints } from "__support__/server-mocks";
+import { renderWithProviders } from "__support__/ui";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { createMockState } from "metabase-types/store/mocks";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { mockSettings } from "__support__/settings";
+
+import NewModelOptions from "../NewModelOptions";
+
+export interface SetupOpts {
+  databases: Database[];
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export function setup({
+  databases = [],
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) {
+  setupDatabasesEndpoints(databases);
+
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<Route path="*" component={NewModelOptions}></Route>, {
+    withRouter: true,
+    storeInitialState: state,
+  });
+}
diff --git a/frontend/src/metabase/plugins/index.ts b/frontend/src/metabase/plugins/index.ts
index 40c1a2dab426aa2e0859943d7f22b1e8abef85d4..70337e44511e37ecd9da7d477d1f9b86d8a43372 100644
--- a/frontend/src/metabase/plugins/index.ts
+++ b/frontend/src/metabase/plugins/index.ts
@@ -129,6 +129,7 @@ export const PLUGIN_SELECTORS = {
   getLoadingMessage: (_state: State) => t`Doing science...`,
   getIsWhiteLabeling: (_state: State) => false,
   getApplicationName: (_state: State) => "Metabase",
+  getShowMetabaseLinks: (_state: State) => true,
 };
 
 export const PLUGIN_FORM_WIDGETS: Record<string, ComponentType<any>> = {};
diff --git a/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/ImpossibleToCreateModelModal.tsx b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/ImpossibleToCreateModelModal.tsx
index c89d83ffdc7a2f321d7973b314232ceac2bd109e..66158f81e42c54e7e7ca5f86ec052442aec67f00 100644
--- a/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/ImpossibleToCreateModelModal.tsx
+++ b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/ImpossibleToCreateModelModal.tsx
@@ -4,19 +4,28 @@ import Button from "metabase/core/components/Button";
 import ExternalLink from "metabase/core/components/ExternalLink";
 import ModalContent from "metabase/components/ModalContent";
 
-import MetabaseSettings from "metabase/lib/settings";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { getDocsUrl } from "metabase/selectors/settings";
 
 type Props = {
   onClose: () => void;
 };
 
 function SQLSnippetsDocLink() {
-  const href = MetabaseSettings.docsUrl("questions/native-editor/sql-snippets");
+  const href = useSelector(state =>
+    getDocsUrl(state, { page: "questions/native-editor/sql-snippets" }),
+  );
   return <ExternalLink href={href}>{t`SQL snippets`}</ExternalLink>;
 }
 
 function ReferencingQuestionsDocLink() {
-  const href = MetabaseSettings.docsUrl("questions/native-editor/sql-snippets");
+  const href = useSelector(state =>
+    getDocsUrl(state, {
+      page: "questions/native-editor/referencing-saved-questions-in-queries",
+      anchor: "referencing-models-and-saved-questions",
+    }),
+  );
   return (
     <ExternalLink
       href={href}
@@ -25,16 +34,22 @@ function ReferencingQuestionsDocLink() {
 }
 
 export function ImpossibleToCreateModelModal({ onClose }: Props) {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
   return (
     <ModalContent
       title={t`Variables in models aren't supported yet`}
       onClose={onClose}
     >
-      <p className="text-paragraph">{jt`To solve this, just remove the variables in this question and try again. (It's okay to use ${(
-        <SQLSnippetsDocLink key="link-1" />
-      )} or ${(
-        <ReferencingQuestionsDocLink key="link-2" />
-      )} in your query.)`}</p>
+      <p className="text-paragraph">
+        {showMetabaseLinks
+          ? jt`To solve this, just remove the variables in this question and try again. (It's okay to use ${(
+              <SQLSnippetsDocLink key="link-1" />
+            )} or ${(
+              <ReferencingQuestionsDocLink key="link-2" />
+            )} in your query.)`
+          : t`To solve this, just remove the variables in this question and try again. (It's okay to use SQL snippets or reference the results of another saved question in your query.)`}
+      </p>
       <div className="flex justify-center py1">
         <Button primary onClick={onClose}>{t`Okay`}</Button>
       </div>
diff --git a/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/common.unit.spec.ts b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5909563b38966ab8f6f215ab7caa0d7c53ec939e
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/common.unit.spec.ts
@@ -0,0 +1,44 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("ImpossibleToCreateModelModal (OSS)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    const sqlSnippetLink = screen.getByRole("link", { name: "SQL snippets" });
+    expect(sqlSnippetLink).toBeInTheDocument();
+    expect(sqlSnippetLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/sql-snippets.html",
+    );
+
+    const referenceLink = screen.getByRole("link", {
+      name: "reference the results of another saved question",
+    });
+    expect(referenceLink).toBeInTheDocument();
+    expect(referenceLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/referencing-saved-questions-in-queries.html#referencing-models-and-saved-questions",
+    );
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    const sqlSnippetLink = screen.getByRole("link", { name: "SQL snippets" });
+    expect(sqlSnippetLink).toBeInTheDocument();
+    expect(sqlSnippetLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/sql-snippets.html",
+    );
+
+    const referenceLink = screen.getByRole("link", {
+      name: "reference the results of another saved question",
+    });
+    expect(referenceLink).toBeInTheDocument();
+    expect(referenceLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/referencing-saved-questions-in-queries.html#referencing-models-and-saved-questions",
+    );
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/enterprise.unit.spec.ts b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d3a29ed1db9e27b23d9d1bc2f6e8056c849d463
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/enterprise.unit.spec.ts
@@ -0,0 +1,49 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("ImpossibleToCreateModelModal (EE without token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    const sqlSnippetLink = screen.getByRole("link", { name: "SQL snippets" });
+    expect(sqlSnippetLink).toBeInTheDocument();
+    expect(sqlSnippetLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/sql-snippets.html",
+    );
+
+    const referenceLink = screen.getByRole("link", {
+      name: "reference the results of another saved question",
+    });
+    expect(referenceLink).toBeInTheDocument();
+    expect(referenceLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/referencing-saved-questions-in-queries.html#referencing-models-and-saved-questions",
+    );
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    const sqlSnippetLink = screen.getByRole("link", { name: "SQL snippets" });
+    expect(sqlSnippetLink).toBeInTheDocument();
+    expect(sqlSnippetLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/sql-snippets.html",
+    );
+
+    const referenceLink = screen.getByRole("link", {
+      name: "reference the results of another saved question",
+    });
+    expect(referenceLink).toBeInTheDocument();
+    expect(referenceLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/referencing-saved-questions-in-queries.html#referencing-models-and-saved-questions",
+    );
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/premium.unit.spec.ts b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..39c1ca13aae10c764c44930e5b73ce63c564caab
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/premium.unit.spec.ts
@@ -0,0 +1,51 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("ImpossibleToCreateModelModal (EE with token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    const sqlSnippetLink = screen.getByRole("link", { name: "SQL snippets" });
+    expect(sqlSnippetLink).toBeInTheDocument();
+    expect(sqlSnippetLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/sql-snippets.html",
+    );
+
+    const referenceLink = screen.getByRole("link", {
+      name: "reference the results of another saved question",
+    });
+    expect(referenceLink).toBeInTheDocument();
+    expect(referenceLink).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/native-editor/referencing-saved-questions-in-queries.html#referencing-models-and-saved-questions",
+    );
+  });
+
+  it("should not show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "To solve this, just remove the variables in this question and try again. (It's okay to use SQL snippets or reference the results of another saved question in your query.)",
+      ),
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByRole("link", { name: "SQL snippets" }),
+    ).not.toBeInTheDocument();
+    expect(
+      screen.queryByRole("link", {
+        name: "reference the results of another saved question",
+      }),
+    ).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/setup.tsx b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0973727205ee010b514a1f7cc5e96100d9b9b886
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/ImpossibleToCreateModelModal/tests/setup.tsx
@@ -0,0 +1,34 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { ImpossibleToCreateModelModal } from "../ImpossibleToCreateModelModal";
+
+export interface SetupOpts {
+  showMetabaseLinks: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<ImpossibleToCreateModelModal onClose={jest.fn()} />, {
+    storeInitialState: state,
+  });
+};
diff --git a/frontend/src/metabase/query_builder/components/QueryModals.tsx b/frontend/src/metabase/query_builder/components/QueryModals.tsx
index 796d1785b8e934da7822e82992f4019825c672ad..8242db135c6fd1fb6ec957041184df8b69f8eda1 100644
--- a/frontend/src/metabase/query_builder/components/QueryModals.tsx
+++ b/frontend/src/metabase/query_builder/components/QueryModals.tsx
@@ -27,7 +27,7 @@ import { FilterModal } from "metabase/querying";
 import NewEventModal from "metabase/timelines/questions/containers/NewEventModal";
 import EditEventModal from "metabase/timelines/questions/containers/EditEventModal";
 import MoveEventModal from "metabase/timelines/questions/containers/MoveEventModal";
-import PreviewQueryModal from "metabase/query_builder/components/view/PreviewQueryModal";
+import { PreviewQueryModal } from "metabase/query_builder/components/view/PreviewQueryModal";
 import ConvertQueryModal from "metabase/query_builder/components/view/ConvertQueryModal";
 import QuestionMoveToast from "metabase/questions/components/QuestionMoveToast";
 import type { Alert, Card, Collection, User } from "metabase-types/api";
diff --git a/frontend/src/metabase/query_builder/components/QueryVisualization.jsx b/frontend/src/metabase/query_builder/components/QueryVisualization.jsx
index de075050e92010718b71c38c73efe1bccba08bc6..437b5b4b986cd99a00d461b93df05fb3c10b3832 100644
--- a/frontend/src/metabase/query_builder/components/QueryVisualization.jsx
+++ b/frontend/src/metabase/query_builder/components/QueryVisualization.jsx
@@ -6,7 +6,7 @@ import cx from "classnames";
 import LoadingSpinner from "metabase/components/LoadingSpinner";
 
 import { HARD_ROW_LIMIT } from "metabase-lib/queries/utils";
-import VisualizationError from "./VisualizationError";
+import { VisualizationError } from "./VisualizationError";
 import VisualizationResult from "./VisualizationResult";
 import Warnings from "./Warnings";
 import RunButtonWithTooltip from "./RunButtonWithTooltip";
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError.jsx b/frontend/src/metabase/query_builder/components/VisualizationError.jsx
deleted file mode 100644
index f7f2740c925f0df08968ae8f687e80690d8fdf7d..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/query_builder/components/VisualizationError.jsx
+++ /dev/null
@@ -1,181 +0,0 @@
-/* eslint "react/prop-types": "warn" */
-
-import { Component } from "react";
-import PropTypes from "prop-types";
-import { t } from "ttag";
-import { getIn } from "icepick";
-import cx from "classnames";
-
-import MetabaseSettings from "metabase/lib/settings";
-import { getEngineNativeType } from "metabase/lib/engine";
-import ErrorMessage from "metabase/components/ErrorMessage";
-import ErrorDetails from "metabase/components/ErrorDetails/ErrorDetails";
-import { VISUALIZATION_SLOW_TIMEOUT } from "../constants";
-import {
-  QueryError,
-  QueryErrorHeader,
-  QueryErrorIcon,
-  QueryErrorTitle,
-  QueryErrorLink,
-  QueryErrorMessage,
-  QueryErrorContent,
-} from "./VisualizationError.styled";
-
-const EmailAdmin = () => {
-  const adminEmail = MetabaseSettings.adminEmail();
-  return (
-    adminEmail && (
-      <span className="QueryError-adminEmail">
-        <a className="no-decoration" href={`mailto:${adminEmail}`}>
-          {adminEmail}
-        </a>
-      </span>
-    )
-  );
-};
-
-export function adjustPositions(error, origSql) {
-  /* Positions in error messages are borked coming in for Postgres errors.
-   * Previously, you would see "blahblahblah bombed out, Position: 119" in a 10-character invalid query.
-   * This is because MB shoves in 'remarks' into the original query and we get the exception from the query with remarks.
-   * This function adjusts the value of the positions in the exception message to account for this.
-   * This is done in mildly scary kludge here in frontend after everything,
-   * because the alternative of doing it in backend
-   * is an absolutely terrifying kludge involving messing with exceptions.
-   */
-  let adjustmentLength = 0;
-
-  // redshift remarks use c-style multiline comments...
-  const multiLineBeginPos = origSql.search("/\\*");
-  const multiLineEndPos = origSql.search("\\*/");
-  // if multiLineBeginPos is 0 then we know it's a redshift remark
-  if (multiLineBeginPos === 0 && multiLineEndPos !== -1) {
-    adjustmentLength += multiLineEndPos + 2; // 2 for */ in itself
-  }
-
-  const chompedSql = origSql.substr(adjustmentLength);
-  // there also seem to be cases where remarks don't get in...
-  const commentPos = chompedSql.search("--");
-  const newLinePos = chompedSql.search("\n");
-  // 5 is a heuristic: this indicates that this is almost certainly an initial remark comment
-  if (commentPos !== -1 && commentPos < 5) {
-    // There will be a \n after the redshift comment,
-    // which is why there needs to be a 2 added
-    adjustmentLength += newLinePos + 2;
-  }
-
-  return error.replace(/Position: (\d+)/, function (_, p1) {
-    return "Position: " + (parseInt(p1) - adjustmentLength);
-  });
-}
-
-export function stripRemarks(error) {
-  /* SQL snippets in error messages are borked coming in for errors in many DBs.
-   * You're expecting something with just your sql in the message,
-   * but the whole error contains these remarks that MB added in. Confusing!
-   */
-  return error.replace(
-    /-- Metabase:: userID: \d+ queryType: native queryHash: \w+\n/,
-    "",
-  );
-}
-
-class VisualizationError extends Component {
-  constructor(props) {
-    super(props);
-    this.state = {
-      showError: false,
-    };
-  }
-  static propTypes = {
-    via: PropTypes.object.isRequired,
-    question: PropTypes.object.isRequired,
-    duration: PropTypes.number.isRequired,
-    error: PropTypes.any.isRequired,
-    className: PropTypes.string,
-  };
-
-  render() {
-    const { via, question, duration, error, className } = this.props;
-
-    if (error && typeof error.status === "number") {
-      // Assume if the request took more than 15 seconds it was due to a timeout
-      // Some platforms like Heroku return a 503 for numerous types of errors so we can't use the status code to distinguish between timeouts and other failures.
-      if (duration > VISUALIZATION_SLOW_TIMEOUT) {
-        return (
-          <ErrorMessage
-            className={className}
-            type="timeout"
-            title={t`Your question took too long`}
-            message={t`We didn't get an answer back from your database in time, so we had to stop. You can try again in a minute, or if the problem persists, you can email an admin to let them know.`}
-            action={<EmailAdmin />}
-          />
-        );
-      } else {
-        return (
-          <ErrorMessage
-            className={className}
-            type="serverError"
-            title={t`We're experiencing server issues`}
-            message={t`Try refreshing the page after waiting a minute or two. If the problem persists we'd recommend you contact an admin.`}
-            action={<EmailAdmin />}
-          />
-        );
-      }
-    } else if (error instanceof Error) {
-      return (
-        <div className={cx(className, "QueryError2 flex justify-center")}>
-          <div className="QueryError-image QueryError-image--queryError mr4" />
-          <div className="QueryError2-details">
-            <h1 className="text-bold">{t`There was a problem with this visualization`}</h1>
-            <ErrorDetails className="pt2" details={error} />
-          </div>
-        </div>
-      );
-    } else if (question?.isNative()) {
-      // always show errors for native queries
-      let processedError = error;
-      const origSql = getIn(via, [(via || "").length - 1, "ex-data", "sql"]);
-      if (typeof error === "string" && typeof origSql === "string") {
-        processedError = adjustPositions(error, origSql);
-      }
-      if (typeof error === "string") {
-        processedError = stripRemarks(processedError);
-      }
-      const database = question.database();
-      const isSql = database && getEngineNativeType(database.engine) === "sql";
-
-      return (
-        <QueryError className={className}>
-          <QueryErrorContent>
-            <QueryErrorHeader>
-              <QueryErrorIcon name="warning" />
-              <QueryErrorTitle>{t`An error occurred in your query`}</QueryErrorTitle>
-            </QueryErrorHeader>
-            <QueryErrorMessage>{processedError}</QueryErrorMessage>
-            {isSql && (
-              <QueryErrorLink
-                href={MetabaseSettings.learnUrl("debugging-sql/sql-syntax")}
-              >
-                {t`Learn how to debug SQL errors`}
-              </QueryErrorLink>
-            )}
-          </QueryErrorContent>
-        </QueryError>
-      );
-    } else {
-      return (
-        <div className={cx(className, "QueryError2 flex justify-center")}>
-          <div className="QueryError-image QueryError-image--queryError mr4" />
-          <div className="QueryError2-details">
-            <h1 className="text-bold">{t`There was a problem with your question`}</h1>
-            <p className="QueryError-messageText">{t`Most of the time this is caused by an invalid selection or bad input value. Double check your inputs and retry your query.`}</p>
-            <ErrorDetails className="pt2" details={error} />
-          </div>
-        </div>
-      );
-    }
-  }
-}
-
-export default VisualizationError;
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError.styled.tsx b/frontend/src/metabase/query_builder/components/VisualizationError/VisualizationError.styled.tsx
similarity index 100%
rename from frontend/src/metabase/query_builder/components/VisualizationError.styled.tsx
rename to frontend/src/metabase/query_builder/components/VisualizationError/VisualizationError.styled.tsx
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/VisualizationError.tsx b/frontend/src/metabase/query_builder/components/VisualizationError/VisualizationError.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e9a0fb8e4c2380962c6f4ea9eca46ffaffb9a0c9
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/VisualizationError.tsx
@@ -0,0 +1,129 @@
+import { t } from "ttag";
+import { getIn } from "icepick";
+import cx from "classnames";
+
+import MetabaseSettings from "metabase/lib/settings";
+import { getEngineNativeType } from "metabase/lib/engine";
+import { ErrorMessage } from "metabase/components/ErrorMessage";
+import ErrorDetails from "metabase/components/ErrorDetails/ErrorDetails";
+import { isNotNull } from "metabase/lib/types";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { useSelector } from "metabase/lib/redux";
+import type Question from "metabase-lib/Question";
+import { VISUALIZATION_SLOW_TIMEOUT } from "../../constants";
+import {
+  QueryError,
+  QueryErrorHeader,
+  QueryErrorIcon,
+  QueryErrorTitle,
+  QueryErrorLink,
+  QueryErrorMessage,
+  QueryErrorContent,
+} from "./VisualizationError.styled";
+import { adjustPositions, stripRemarks } from "./utils";
+
+function EmailAdmin(): JSX.Element | null {
+  const hasAdminEmail = isNotNull(MetabaseSettings.adminEmail());
+  return hasAdminEmail ? (
+    <span className="QueryError-adminEmail">
+      <a className="no-decoration" href={`mailto:${hasAdminEmail}`}>
+        {hasAdminEmail}
+      </a>
+    </span>
+  ) : null;
+}
+
+interface VisualizationErrorProps {
+  via: Record<string, any>[];
+  question: Question;
+  duration: number;
+  error: any;
+  className?: string;
+}
+
+export function VisualizationError({
+  via,
+  question,
+  duration,
+  error,
+  className,
+}: VisualizationErrorProps) {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+  if (error && typeof error.status === "number") {
+    // Assume if the request took more than 15 seconds it was due to a timeout
+    // Some platforms like Heroku return a 503 for numerous types of errors so we can't use the status code to distinguish between timeouts and other failures.
+    if (duration > VISUALIZATION_SLOW_TIMEOUT) {
+      return (
+        <ErrorMessage
+          className={className}
+          type="timeout"
+          title={t`Your question took too long`}
+          message={t`We didn't get an answer back from your database in time, so we had to stop. You can try again in a minute, or if the problem persists, you can email an admin to let them know.`}
+          action={<EmailAdmin />}
+        />
+      );
+    } else {
+      return (
+        <ErrorMessage
+          className={className}
+          type="serverError"
+          title={t`We're experiencing server issues`}
+          message={t`Try refreshing the page after waiting a minute or two. If the problem persists we'd recommend you contact an admin.`}
+          action={<EmailAdmin />}
+        />
+      );
+    }
+  } else if (error instanceof Error) {
+    return (
+      <div className={cx(className, "QueryError2 flex justify-center")}>
+        <div className="QueryError-image QueryError-image--queryError mr4" />
+        <div className="QueryError2-details">
+          <h1 className="text-bold">{t`There was a problem with this visualization`}</h1>
+          <ErrorDetails className="pt2" details={error} />
+        </div>
+      </div>
+    );
+  } else if (question?.isNative()) {
+    // always show errors for native queries
+    let processedError = error;
+    const origSql = getIn(via, [(via || "").length - 1, "ex-data", "sql"]);
+    if (typeof error === "string" && typeof origSql === "string") {
+      processedError = adjustPositions(error, origSql);
+    }
+    if (typeof error === "string") {
+      processedError = stripRemarks(processedError);
+    }
+    const database = question.database();
+    const isSql = database && getEngineNativeType(database.engine) === "sql";
+
+    return (
+      <QueryError className={className}>
+        <QueryErrorContent>
+          <QueryErrorHeader>
+            <QueryErrorIcon name="warning" />
+            <QueryErrorTitle>{t`An error occurred in your query`}</QueryErrorTitle>
+          </QueryErrorHeader>
+          <QueryErrorMessage>{processedError}</QueryErrorMessage>
+          {isSql && showMetabaseLinks && (
+            <QueryErrorLink
+              href={MetabaseSettings.learnUrl("debugging-sql/sql-syntax")}
+            >
+              {t`Learn how to debug SQL errors`}
+            </QueryErrorLink>
+          )}
+        </QueryErrorContent>
+      </QueryError>
+    );
+  } else {
+    return (
+      <div className={cx(className, "QueryError2 flex justify-center")}>
+        <div className="QueryError-image QueryError-image--queryError mr4" />
+        <div className="QueryError2-details">
+          <h1 className="text-bold">{t`There was a problem with your question`}</h1>
+          <p className="QueryError-messageText">{t`Most of the time this is caused by an invalid selection or bad input value. Double check your inputs and retry your query.`}</p>
+          <ErrorDetails className="pt2" details={error} />
+        </div>
+      </div>
+    );
+  }
+}
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/index.ts b/frontend/src/metabase/query_builder/components/VisualizationError/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..078f966ebfef7ffa412e58be93590c00d527d0c5
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/index.ts
@@ -0,0 +1 @@
+export { VisualizationError } from "./VisualizationError";
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/tests/common.unit.spec.ts b/frontend/src/metabase/query_builder/components/VisualizationError/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0f235ea0fd4d56c990839121835e69e58e519a4b
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/tests/common.unit.spec.ts
@@ -0,0 +1,68 @@
+import { createMockCard, createMockDatabase } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("VisualizationError (OSS)", () => {
+  describe("SQL databases", () => {
+    const database = createMockDatabase({
+      engine: "postgres",
+    });
+
+    it("should show a SQL help link when `show-metabase-links: true`", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "SELECT * FROM ORDERS",
+          },
+        },
+      });
+      setup({ database, card, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText("Learn how to debug SQL errors"),
+      ).toBeInTheDocument();
+    });
+
+    it("should show a SQL help link when `show-metabase-links: false`", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "SELECT * FROM ORDERS",
+          },
+        },
+      });
+      setup({ database, card, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText("Learn how to debug SQL errors"),
+      ).toBeInTheDocument();
+    });
+  });
+
+  describe("NoSQL databases", () => {
+    const database = createMockDatabase({
+      engine: "mongo",
+    });
+
+    it("should not show a SQL help link", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "[]",
+          },
+        },
+      });
+      setup({ database, card });
+
+      expect(
+        screen.queryByText("Learn how to debug SQL errors"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/tests/enterprise.unit.spec.ts b/frontend/src/metabase/query_builder/components/VisualizationError/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e9ced54352aef9dd740babd68ecbeb17d2b675d7
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/tests/enterprise.unit.spec.ts
@@ -0,0 +1,73 @@
+import { createMockCard, createMockDatabase } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("VisualizationError (EE without token)", () => {
+  describe("SQL databases", () => {
+    const database = createMockDatabase({
+      engine: "postgres",
+    });
+
+    it("should show a SQL help link when `show-metabase-links: true`", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "SELECT * FROM ORDERS",
+          },
+        },
+      });
+      setup({ database, card, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText("Learn how to debug SQL errors"),
+      ).toBeInTheDocument();
+    });
+
+    it("should show a SQL help link when `show-metabase-links: false`", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "SELECT * FROM ORDERS",
+          },
+        },
+      });
+      setup({ database, card, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText("Learn how to debug SQL errors"),
+      ).toBeInTheDocument();
+    });
+  });
+
+  describe("NoSQL databases", () => {
+    const database = createMockDatabase({
+      engine: "mongo",
+    });
+
+    it("should not show a SQL help link", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "[]",
+          },
+        },
+      });
+      setup({ database, card });
+
+      expect(
+        screen.queryByText("Learn how to debug SQL errors"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/tests/premium.unit.spec.ts b/frontend/src/metabase/query_builder/components/VisualizationError/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..78a593f097245e46b393a57ed145268c47b639b8
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/tests/premium.unit.spec.ts
@@ -0,0 +1,77 @@
+import { createMockCard, createMockDatabase } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("VisualizationError (EE with token)", () => {
+  describe("SQL databases", () => {
+    const database = createMockDatabase({
+      engine: "postgres",
+    });
+
+    it("should show a SQL help link when `show-metabase-links: true`", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "SELECT * FROM ORDERS",
+          },
+        },
+      });
+      setup({ database, card, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText("Learn how to debug SQL errors"),
+      ).toBeInTheDocument();
+    });
+
+    it("should not show a SQL help link when `show-metabase-links: false`", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "SELECT * FROM ORDERS",
+          },
+        },
+      });
+      setup({ database, card, showMetabaseLinks: false });
+
+      expect(
+        screen.queryByText("Learn how to debug SQL errors"),
+      ).not.toBeInTheDocument();
+    });
+  });
+
+  describe("NoSQL databases", () => {
+    const database = createMockDatabase({
+      engine: "mongo",
+    });
+
+    it("should not show a SQL help link", () => {
+      const card = createMockCard({
+        dataset_query: {
+          database: database.id,
+          type: "native",
+          native: {
+            query: "[]",
+          },
+        },
+      });
+      setup({ database, card });
+
+      expect(
+        screen.queryByText("Learn how to debug SQL errors"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/tests/setup.tsx b/frontend/src/metabase/query_builder/components/VisualizationError/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e965764308ef521d80f5e1e27eb56c71ea876ef4
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/tests/setup.tsx
@@ -0,0 +1,62 @@
+import type { Card, Database, TokenFeatures } from "metabase-types/api";
+import {
+  createMockCard,
+  createMockDatabase,
+  createMockTokenFeatures,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { createMockEntitiesState } from "__support__/store";
+import { renderWithProviders } from "__support__/ui";
+import { mockSettings } from "__support__/settings";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { checkNotNull } from "metabase/lib/types";
+import { createMockMetadata } from "__support__/metadata";
+
+import { VisualizationError } from "../VisualizationError";
+
+export interface SetupOpts {
+  database?: Database;
+  card?: Card;
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  database = createMockDatabase(),
+  card = createMockCard(),
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) => {
+  const state = createMockState({
+    entities: createMockEntitiesState({
+      databases: [database],
+      questions: [card],
+    }),
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  const metadata = createMockMetadata({
+    questions: [card],
+    databases: [database],
+  });
+  const question = checkNotNull(metadata.question(card.id));
+
+  renderWithProviders(
+    <VisualizationError
+      question={question}
+      duration={0}
+      error="An error occurred"
+      via={[]}
+    />,
+    { storeInitialState: state },
+  );
+};
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError.unit.spec.tsx b/frontend/src/metabase/query_builder/components/VisualizationError/tests/utils.unit.spec.ts
similarity index 51%
rename from frontend/src/metabase/query_builder/components/VisualizationError.unit.spec.tsx
rename to frontend/src/metabase/query_builder/components/VisualizationError/tests/utils.unit.spec.ts
index 5007f06da3cc0b0dc2d1e80f80bdb6a5bcb7fdfd..ef5b4ce0d65dd772e40cc0465c94036ebc9dfc47 100644
--- a/frontend/src/metabase/query_builder/components/VisualizationError.unit.spec.tsx
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/tests/utils.unit.spec.ts
@@ -1,84 +1,4 @@
-import { getMetadata } from "metabase/selectors/metadata";
-import type { Card, Database } from "metabase-types/api";
-import { createMockCard, createMockDatabase } from "metabase-types/api/mocks";
-import { createMockState } from "metabase-types/store/mocks";
-import { createMockEntitiesState } from "__support__/store";
-import { render, screen } from "__support__/ui";
-import VisualizationError, {
-  adjustPositions,
-  stripRemarks,
-} from "./VisualizationError";
-
-interface SetupOpts {
-  database?: Database;
-  card?: Card;
-}
-
-const setup = ({
-  database = createMockDatabase(),
-  card = createMockCard(),
-}: SetupOpts) => {
-  const state = createMockState({
-    entities: createMockEntitiesState({
-      databases: [database],
-      questions: [card],
-    }),
-  });
-
-  const metadata = getMetadata(state);
-  const question = metadata.question(card.id);
-
-  render(
-    <VisualizationError
-      question={question}
-      duration={0}
-      error="An error occurred"
-      via={{}}
-    />,
-  );
-};
-
-describe("VisualizationError", () => {
-  it("should show a help link for sql databases", () => {
-    const database = createMockDatabase({
-      engine: "postgres",
-    });
-    const card = createMockCard({
-      dataset_query: {
-        database: database.id,
-        type: "native",
-        native: {
-          query: "SELECT * FROM ORDERS",
-        },
-      },
-    });
-    setup({ database, card });
-
-    expect(
-      screen.getByText("Learn how to debug SQL errors"),
-    ).toBeInTheDocument();
-  });
-
-  it("should not show a help link for a nosql databases", () => {
-    const database = createMockDatabase({
-      engine: "mongo",
-    });
-    const card = createMockCard({
-      dataset_query: {
-        database: database.id,
-        type: "native",
-        native: {
-          query: "[]",
-        },
-      },
-    });
-    setup({ database, card });
-
-    expect(
-      screen.queryByText("Learn how to debug SQL errors"),
-    ).not.toBeInTheDocument();
-  });
-});
+import { adjustPositions, stripRemarks } from "../utils";
 
 describe("adjustPositions", () => {
   const remarkedQuery =
@@ -117,6 +37,7 @@ describe("adjustPositions", () => {
     );
   });
 });
+
 describe("stripRemarks", () => {
   const errorH2Unstripped = `
   Syntax error in SQL statement " FWEFWEF[*] "; expected "FROM, {"; SQL statement: -- Metabase:: userID: 1 queryType: native queryHash: 9863b8284f269ce8763ad59b04cec26407a1dd74eebeb16cffdf1ef3e23b325a\nfwefwef [42001-197]`;
diff --git a/frontend/src/metabase/query_builder/components/VisualizationError/utils.jsx b/frontend/src/metabase/query_builder/components/VisualizationError/utils.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..5d763b2ada6929e749ca7378cb5ba4379ea8c5ae
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/VisualizationError/utils.jsx
@@ -0,0 +1,45 @@
+export function adjustPositions(error, origSql) {
+  /* Positions in error messages are borked coming in for Postgres errors.
+   * Previously, you would see "blahblahblah bombed out, Position: 119" in a 10-character invalid query.
+   * This is because MB shoves in 'remarks' into the original query and we get the exception from the query with remarks.
+   * This function adjusts the value of the positions in the exception message to account for this.
+   * This is done in mildly scary kludge here in frontend after everything,
+   * because the alternative of doing it in backend
+   * is an absolutely terrifying kludge involving messing with exceptions.
+   */
+  let adjustmentLength = 0;
+
+  // redshift remarks use c-style multiline comments...
+  const multiLineBeginPos = origSql.search("/\\*");
+  const multiLineEndPos = origSql.search("\\*/");
+  // if multiLineBeginPos is 0 then we know it's a redshift remark
+  if (multiLineBeginPos === 0 && multiLineEndPos !== -1) {
+    adjustmentLength += multiLineEndPos + 2; // 2 for */ in itself
+  }
+
+  const chompedSql = origSql.substr(adjustmentLength);
+  // there also seem to be cases where remarks don't get in...
+  const commentPos = chompedSql.search("--");
+  const newLinePos = chompedSql.search("\n");
+  // 5 is a heuristic: this indicates that this is almost certainly an initial remark comment
+  if (commentPos !== -1 && commentPos < 5) {
+    // There will be a \n after the redshift comment,
+    // which is why there needs to be a 2 added
+    adjustmentLength += newLinePos + 2;
+  }
+
+  return error.replace(/Position: (\d+)/, function (_, p1) {
+    return "Position: " + (parseInt(p1) - adjustmentLength);
+  });
+}
+
+export function stripRemarks(error) {
+  /* SQL snippets in error messages are borked coming in for errors in many DBs.
+   * You're expecting something with just your sql in the message,
+   * but the whole error contains these remarks that MB added in. Confusing!
+   */
+  return error.replace(
+    /-- Metabase:: userID: \d+ queryType: native queryHash: \w+\n/,
+    "",
+  );
+}
diff --git a/frontend/src/metabase/query_builder/components/VisualizationResult.jsx b/frontend/src/metabase/query_builder/components/VisualizationResult.jsx
index bf4d497857e9de61d6aa0fd6e5544196f9413c4c..0c12c581f3e89240968a2ee2f7820ea50f37d15b 100644
--- a/frontend/src/metabase/query_builder/components/VisualizationResult.jsx
+++ b/frontend/src/metabase/query_builder/components/VisualizationResult.jsx
@@ -4,7 +4,7 @@ import { t, jt } from "ttag";
 import cx from "classnames";
 import _ from "underscore";
 
-import ErrorMessage from "metabase/components/ErrorMessage";
+import { ErrorMessage } from "metabase/components/ErrorMessage";
 import Visualization from "metabase/visualizations/components/Visualization";
 import { CreateAlertModalContent } from "metabase/query_builder/components/AlertModals";
 import Modal from "metabase/components/Modal";
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.stories.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.stories.tsx
similarity index 93%
rename from frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.stories.tsx
rename to frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.stories.tsx
index e5e117be379007fb47b5f4af01d20c28397773e6..1ccd5d960deaf1f763fea910b90acc3de777f519 100644
--- a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.stories.tsx
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.stories.tsx
@@ -5,7 +5,7 @@ import { createMockDatabase } from "metabase-types/api/mocks";
 import { createMockMetadata } from "__support__/metadata";
 import { getHelpText } from "metabase-lib/expressions/helper-text-strings";
 import type { ExpressionEditorHelpTextProps } from "./ExpressionEditorHelpText";
-import ExpressionEditorHelpText from "./ExpressionEditorHelpText";
+import { ExpressionEditorHelpText } from "./ExpressionEditorHelpText";
 
 export default {
   title: "Query Builder/ExpressionEditorHelpText",
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.styled.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.styled.tsx
similarity index 100%
rename from frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.styled.tsx
rename to frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.styled.tsx
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.tsx
similarity index 82%
rename from frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.tsx
rename to frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.tsx
index 31a9e09a30645898a9b360998581a850bcbabaec..66bc9c135de7a5956c129a470ad6a41e0ffb54f2 100644
--- a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.tsx
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/ExpressionEditorHelpText.tsx
@@ -2,6 +2,8 @@ import * as React from "react";
 import { t } from "ttag";
 import TippyPopover from "metabase/components/Popover/TippyPopover";
 import MetabaseSettings from "metabase/lib/settings";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
 import type { HelpText } from "metabase-lib/expressions/types";
 import { getHelpDocsUrl } from "metabase-lib/expressions/helper-text-strings";
 import {
@@ -23,11 +25,12 @@ export interface ExpressionEditorHelpTextProps {
   target: React.RefObject<HTMLElement>;
 }
 
-const ExpressionEditorHelpText = ({
+export const ExpressionEditorHelpText = ({
   helpText,
   width,
   target,
 }: ExpressionEditorHelpTextProps) => {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
   if (!helpText) {
     return null;
   }
@@ -95,24 +98,23 @@ const ExpressionEditorHelpText = ({
             <ExampleCode data-ignore-outside-clicks>
               {helpText.example}
             </ExampleCode>
-            <DocumentationLink
-              href={MetabaseSettings.docsUrl(getHelpDocsUrl(helpText))}
-              target="_blank"
-              data-ignore-outside-clicks
-            >
-              <LearnMoreIcon
-                name="reference"
-                size={12}
+            {showMetabaseLinks && (
+              <DocumentationLink
+                href={MetabaseSettings.docsUrl(getHelpDocsUrl(helpText))}
+                target="_blank"
                 data-ignore-outside-clicks
-              />
-              {t`Learn more`}
-            </DocumentationLink>
+              >
+                <LearnMoreIcon
+                  name="reference"
+                  size={12}
+                  data-ignore-outside-clicks
+                />
+                {t`Learn more`}
+              </DocumentationLink>
+            )}
           </Container>
         </>
       }
     />
   );
 };
-
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export default ExpressionEditorHelpText;
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/index.ts b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6ad52d8f4488c61109c7c22e681b6ed7cdf4b517
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/index.ts
@@ -0,0 +1 @@
+export { ExpressionEditorHelpText } from "./ExpressionEditorHelpText";
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.unit.spec.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/common.unit.spec.tsx
similarity index 70%
rename from frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.unit.spec.tsx
rename to frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/common.unit.spec.tsx
index 8cb8556b5b471b966a972069b5057dcb5b132398..ec5127829fb541fe0c4f1d6f683c5ca206810283 100644
--- a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText.unit.spec.tsx
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/common.unit.spec.tsx
@@ -1,4 +1,4 @@
-import { render, screen, within } from "@testing-library/react";
+import { screen, within } from "@testing-library/react";
 import { checkNotNull } from "metabase/lib/types";
 import { createMockMetadata } from "__support__/metadata";
 import { getBrokenUpTextMatcher } from "__support__/ui";
@@ -7,10 +7,9 @@ import {
   SAMPLE_DB_ID,
 } from "metabase-types/api/mocks/presets";
 import { getHelpText } from "metabase-lib/expressions/helper-text-strings";
-import type { ExpressionEditorHelpTextProps } from "./ExpressionEditorHelpText";
-import ExpressionEditorHelpText from "./ExpressionEditorHelpText";
+import { setup } from "./setup";
 
-describe("ExpressionEditorHelpText", () => {
+describe("ExpressionEditorHelpText (OSS)", () => {
   const metadata = createMockMetadata({ databases: [createSampleDatabase()] });
   const database = checkNotNull(metadata.database(SAMPLE_DB_ID));
 
@@ -59,9 +58,8 @@ describe("ExpressionEditorHelpText", () => {
   });
 
   it("should render function arguments", async () => {
-    const {
-      props: { helpText },
-    } = await setup({ helpText: getHelpText("concat", database, "UTC") });
+    const helpText = getHelpText("concat", database, "UTC");
+    await setup({ helpText });
 
     const argumentsBlock = screen.getByTestId(
       "expression-helper-popover-arguments",
@@ -72,24 +70,25 @@ describe("ExpressionEditorHelpText", () => {
       expect(within(argumentsBlock).getByText(description)).toBeInTheDocument();
     });
   });
-});
-
-async function setup(additionalProps?: Partial<ExpressionEditorHelpTextProps>) {
-  const target = { current: null };
 
-  const props: ExpressionEditorHelpTextProps = {
-    helpText: additionalProps?.helpText,
-    width: 397,
-    target,
-    ...additionalProps,
-  };
+  describe("Metabase links", () => {
+    const helpText = getHelpText("concat", database, "UTC");
+    it("should show a help link when `show-metabase-links: true`", async () => {
+      await setup({ helpText, showMetabaseLinks: true });
 
-  render(<ExpressionEditorHelpText {...props} />);
+      expect(
+        screen.getByRole("img", { name: "reference icon" }),
+      ).toBeInTheDocument();
+      expect(screen.getByText("Learn more")).toBeInTheDocument();
+    });
 
-  // have to wait for TippyPopover to render content
-  expect(
-    await screen.findByTestId("expression-helper-popover"),
-  ).toBeInTheDocument();
+    it("should show a help link when `show-metabase-links: false`", async () => {
+      await setup({ helpText, showMetabaseLinks: false });
 
-  return { props };
-}
+      expect(
+        screen.getByRole("img", { name: "reference icon" }),
+      ).toBeInTheDocument();
+      expect(screen.getByText("Learn more")).toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/enterprise.unit.spec.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/enterprise.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..788437b233f551586e7cc8b7a728ae24bd970776
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/enterprise.unit.spec.tsx
@@ -0,0 +1,40 @@
+import { screen } from "@testing-library/react";
+import { checkNotNull } from "metabase/lib/types";
+import { createMockMetadata } from "__support__/metadata";
+import {
+  createSampleDatabase,
+  SAMPLE_DB_ID,
+} from "metabase-types/api/mocks/presets";
+import { getHelpText } from "metabase-lib/expressions/helper-text-strings";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+async function setup(opts: SetupOpts) {
+  await baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("ExpressionEditorHelpText (EE without token)", () => {
+  const metadata = createMockMetadata({ databases: [createSampleDatabase()] });
+  const database = checkNotNull(metadata.database(SAMPLE_DB_ID));
+
+  describe("Metabase links", () => {
+    const helpText = getHelpText("concat", database, "UTC");
+    it("should show a help link when `show-metabase-links: true`", async () => {
+      await setup({ helpText, showMetabaseLinks: true });
+
+      expect(
+        screen.getByRole("img", { name: "reference icon" }),
+      ).toBeInTheDocument();
+      expect(screen.getByText("Learn more")).toBeInTheDocument();
+    });
+
+    it("should show a help link when `show-metabase-links: false`", async () => {
+      await setup({ helpText, showMetabaseLinks: false });
+
+      expect(
+        screen.getByRole("img", { name: "reference icon" }),
+      ).toBeInTheDocument();
+      expect(screen.getByText("Learn more")).toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/premium.unit.spec.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/premium.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..baf36974a47c5e5a2d1d35e2233d9648649db114
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/premium.unit.spec.tsx
@@ -0,0 +1,44 @@
+import { screen } from "@testing-library/react";
+import { checkNotNull } from "metabase/lib/types";
+import { createMockMetadata } from "__support__/metadata";
+import {
+  createSampleDatabase,
+  SAMPLE_DB_ID,
+} from "metabase-types/api/mocks/presets";
+import { getHelpText } from "metabase-lib/expressions/helper-text-strings";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+async function setup(opts: SetupOpts) {
+  await baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("ExpressionEditorHelpText (EE with token)", () => {
+  const metadata = createMockMetadata({ databases: [createSampleDatabase()] });
+  const database = checkNotNull(metadata.database(SAMPLE_DB_ID));
+
+  describe("Metabase links", () => {
+    const helpText = getHelpText("concat", database, "UTC");
+    it("should show a help link when `show-metabase-links: true`", async () => {
+      await setup({ helpText, showMetabaseLinks: true });
+
+      expect(
+        screen.getByRole("img", { name: "reference icon" }),
+      ).toBeInTheDocument();
+      expect(screen.getByText("Learn more")).toBeInTheDocument();
+    });
+
+    it("should not show a help link when `show-metabase-links: false`", async () => {
+      await setup({ helpText, showMetabaseLinks: false });
+
+      expect(
+        screen.queryByRole("img", { name: "reference icon" }),
+      ).not.toBeInTheDocument();
+      expect(screen.queryByText("Learn more")).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/setup.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bd33d3acaaf0526bf69fd717920c423c01450abc
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorHelpText/tests/setup.tsx
@@ -0,0 +1,50 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { renderWithProviders, screen } from "__support__/ui";
+import { createMockState } from "metabase-types/store/mocks";
+import { mockSettings } from "__support__/settings";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { ExpressionEditorHelpText } from "../ExpressionEditorHelpText";
+import type { ExpressionEditorHelpTextProps } from "../ExpressionEditorHelpText";
+
+export interface SetupOpts {
+  helpText?: ExpressionEditorHelpTextProps["helpText"];
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export async function setup({
+  helpText,
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) {
+  const target = { current: null };
+
+  const props: ExpressionEditorHelpTextProps = {
+    helpText,
+    width: 397,
+    target,
+  };
+
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<ExpressionEditorHelpText {...props} />, {
+    storeInitialState: state,
+  });
+
+  // have to wait for TippyPopover to render content
+  expect(
+    await screen.findByTestId("expression-helper-popover"),
+  ).toBeInTheDocument();
+}
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorTextfield/ExpressionEditorTextfield.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorTextfield/ExpressionEditorTextfield.tsx
index 0d20065fda93363fe6a001d6d8c9790abeadd100..d59e306323ad43e19971e881454edfa98a901b9f 100644
--- a/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorTextfield/ExpressionEditorTextfield.tsx
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionEditorTextfield/ExpressionEditorTextfield.tsx
@@ -26,7 +26,7 @@ import type {
 } from "metabase-lib/expressions/types";
 
 import type Metadata from "metabase-lib/metadata/Metadata";
-import ExpressionEditorHelpText from "../ExpressionEditorHelpText";
+import { ExpressionEditorHelpText } from "../ExpressionEditorHelpText";
 import ExpressionEditorSuggestions from "../ExpressionEditorSuggestions";
 import ExpressionMode from "../ExpressionMode";
 import {
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidget.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidget.tsx
index f8778f93cc0d1c48e2c3e13585af9837e23da24c..c5c5e4d9e64b7f3393ebc9d0222a740b6b7ed30d 100644
--- a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidget.tsx
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidget.tsx
@@ -4,7 +4,6 @@ import { t } from "ttag";
 import { isNotNull } from "metabase/lib/types";
 import Button from "metabase/core/components/Button";
 import Input from "metabase/core/components/Input/Input";
-import Tooltip from "metabase/core/components/Tooltip";
 import MetabaseSettings from "metabase/lib/settings";
 import type { Expression } from "metabase-types/api";
 import type * as Lib from "metabase-lib";
@@ -18,12 +17,11 @@ import {
   FieldLabel,
   FieldWrapper,
   Footer,
-  InfoLink,
   RemoveLink,
-  StyledFieldTitleIcon,
 } from "./ExpressionWidget.styled";
+import { ExpressionWidgetInfo } from "./ExpressionWidgetInfo";
 
-const EXPRESSIONS_DOCUMENTATION_URL = MetabaseSettings.docsUrl(
+export const EXPRESSIONS_DOCUMENTATION_URL = MetabaseSettings.docsUrl(
   "questions/query-builder/expressions",
 );
 
@@ -131,19 +129,7 @@ export const ExpressionWidget = <Clause extends object = Lib.ExpressionClause>(
       <ExpressionFieldWrapper>
         <FieldLabel htmlFor="expression-content">
           {t`Expression`}
-          <Tooltip
-            tooltip={t`You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.`}
-            placement="right"
-            maxWidth={332}
-          >
-            <InfoLink
-              target="_blank"
-              href={EXPRESSIONS_DOCUMENTATION_URL}
-              aria-label={t`Open expressions documentation`}
-            >
-              <StyledFieldTitleIcon name="info" />
-            </InfoLink>
-          </Tooltip>
+          <ExpressionWidgetInfo />
         </FieldLabel>
         <div ref={helpTextTargetRef}>
           <ExpressionEditorTextfield
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/ExpressionWidgetInfo.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/ExpressionWidgetInfo.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c4a30e3e0d77466fb7c43cd33578345a4780d8bd
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/ExpressionWidgetInfo.tsx
@@ -0,0 +1,37 @@
+import { t } from "ttag";
+import Tooltip from "metabase/core/components/Tooltip";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { Box } from "metabase/ui";
+import { InfoLink, StyledFieldTitleIcon } from "../ExpressionWidget.styled";
+import { EXPRESSIONS_DOCUMENTATION_URL } from "../ExpressionWidget";
+
+export function ExpressionWidgetInfo() {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
+  return showMetabaseLinks ? (
+    <Tooltip
+      tooltip={t`You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.`}
+      placement="right"
+      maxWidth={332}
+    >
+      <InfoLink
+        target="_blank"
+        href={EXPRESSIONS_DOCUMENTATION_URL}
+        aria-label={t`Open expressions documentation`}
+      >
+        <StyledFieldTitleIcon name="info" />
+      </InfoLink>
+    </Tooltip>
+  ) : (
+    <Tooltip
+      tooltip={t`You can reference columns here in functions or equations, like: floor([Price] - [Discount]).`}
+      placement="right"
+      maxWidth={332}
+    >
+      <Box ml="0.25rem">
+        <StyledFieldTitleIcon name="info" />
+      </Box>
+    </Tooltip>
+  );
+}
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/index.ts b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d833d913eb44395206ff7ee77cba052bce6bcf40
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/index.ts
@@ -0,0 +1 @@
+export { ExpressionWidgetInfo } from "./ExpressionWidgetInfo";
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/common.unit.spec.ts b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b6d482963b05e67116935889f7dfc2c71cf2bf43
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/common.unit.spec.ts
@@ -0,0 +1,39 @@
+import userEvent from "@testing-library/user-event";
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("ExpressionWidgetInfo (OSS)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByRole("link", { name: "Open expressions documentation" }),
+    ).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/query-builder/expressions.html",
+    );
+    userEvent.hover(screen.getByLabelText("info icon"));
+    expect(
+      screen.getByText(
+        "You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByRole("link", { name: "Open expressions documentation" }),
+    ).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/query-builder/expressions.html",
+    );
+    userEvent.hover(screen.getByLabelText("info icon"));
+    expect(
+      screen.getByText(
+        "You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.",
+      ),
+    ).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/enterprise.unit.spec.ts b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f79024f3e27093bb19bf9c5fdc21eafaa617e648
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/enterprise.unit.spec.ts
@@ -0,0 +1,44 @@
+import userEvent from "@testing-library/user-event";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("ExpressionWidgetInfo (EE without token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByRole("link", { name: "Open expressions documentation" }),
+    ).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/query-builder/expressions.html",
+    );
+    userEvent.hover(screen.getByLabelText("info icon"));
+    expect(
+      screen.getByText(
+        "You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByRole("link", { name: "Open expressions documentation" }),
+    ).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/query-builder/expressions.html",
+    );
+    userEvent.hover(screen.getByLabelText("info icon"));
+    expect(
+      screen.getByText(
+        "You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.",
+      ),
+    ).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/premium.unit.spec.ts b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..940e6736bfeaab02f3171de374da78dfbf2106d2
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/premium.unit.spec.ts
@@ -0,0 +1,45 @@
+import userEvent from "@testing-library/user-event";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("ExpressionWidgetInfo (EE with token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByRole("link", { name: "Open expressions documentation" }),
+    ).toHaveProperty(
+      "href",
+      "https://www.metabase.com/docs/latest/questions/query-builder/expressions.html",
+    );
+    userEvent.hover(screen.getByLabelText("info icon"));
+    expect(
+      screen.getByText(
+        "You can reference columns here in functions or equations, like: floor([Price] - [Discount]). Click for documentation.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("should not show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.queryByRole("link", { name: "Open expressions documentation" }),
+    ).not.toBeInTheDocument();
+    userEvent.hover(screen.getByLabelText("info icon"));
+    expect(
+      screen.getByText(
+        "You can reference columns here in functions or equations, like: floor([Price] - [Discount]).",
+      ),
+    ).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/setup.tsx b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..32e1712554c0dd595e3ccac571b6e3e978b6082a
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/expressions/ExpressionWidgetInfo/tests/setup.tsx
@@ -0,0 +1,32 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { ExpressionWidgetInfo } from "../ExpressionWidgetInfo";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<ExpressionWidgetInfo />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp.tsx b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/TagEditorHelp.tsx
similarity index 92%
rename from frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp.tsx
rename to frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/TagEditorHelp.tsx
index f72e380c9f5390cc51a59209b7834c33c30d0625..e8cf41526a9227388dd49d610ca9aaf084d49c16 100644
--- a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp.tsx
+++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/TagEditorHelp.tsx
@@ -5,6 +5,8 @@ import ExternalLink from "metabase/core/components/ExternalLink";
 import MetabaseSettings from "metabase/lib/settings";
 import { uuid } from "metabase/lib/utils";
 import type { DatabaseId, NativeDatasetQuery } from "metabase-types/api";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
 import type Database from "metabase-lib/metadata/Database";
 
 const SQL_EXAMPLES: Record<string, NativeDatasetQuery> = {
@@ -234,6 +236,8 @@ export const TagEditorHelp = ({
   const examples = engine === "mongo" ? MONGO_EXAMPLES : SQL_EXAMPLES;
   const datasetId = engine === "mongo" ? database?.id : sampleDatabaseId;
 
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
   let setQueryWithDatasetId;
 
   if (datasetId != null) {
@@ -262,7 +266,7 @@ export const TagEditorHelp = ({
       <h4 className="pt2">{t`Variables`}</h4>
       <p>
         {jt`${(
-          <Code>{"{{variable_name}}"}</Code>
+          <Code key="code">{"{{variable_name}}"}</Code>
         )} creates a variable in this query template called "variable_name". Variables can be given types in the side panel, which changes their behavior. All variable types other than "Field Filter" will automatically cause a filter widget to be placed on this question; with Field Filters, this is optional. When this filter widget is filled in, that value replaces the variable in the query template.`}
       </p>
       <TagExample
@@ -285,7 +289,7 @@ export const TagEditorHelp = ({
       <h4 className="pt2">{t`Optional Clauses`}</h4>
       <p>
         {jt`Brackets around a ${(
-          <Code>{"[[{{variable}}]]"}</Code>
+          <Code key="code">{"[[{{variable}}]]"}</Code>
         )} create an optional clause in the template. If "variable" is set, then the entire clause is placed into the template. If not, then the entire clause is ignored.`}
       </p>
       <TagExample
@@ -307,15 +311,17 @@ export const TagEditorHelp = ({
         setDatasetQuery={setQueryWithDatasetId}
       />
 
-      <p className="pt2 link">
-        <ExternalLink
-          href={MetabaseSettings.docsUrl(
-            "questions/native-editor/sql-parameters",
-          )}
-          target="_blank"
-          data-metabase-event="QueryBuilder;Template Tag Documentation Click"
-        >{t`Read the full documentation`}</ExternalLink>
-      </p>
+      {showMetabaseLinks && (
+        <p className="pt2 link">
+          <ExternalLink
+            href={MetabaseSettings.docsUrl(
+              "questions/native-editor/sql-parameters",
+            )}
+            target="_blank"
+            data-metabase-event="QueryBuilder;Template Tag Documentation Click"
+          >{t`Read the full documentation`}</ExternalLink>
+        </p>
+      )}
     </div>
   );
 };
diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/index.ts b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..47b75d54308da14a711e05b5f47524ba3d9bb257
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/index.ts
@@ -0,0 +1 @@
+export { TagEditorHelp } from "./TagEditorHelp";
diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/common.unit.spec.ts b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99ea0fa90ea238bbd1bc2143b2b94b9a0d9e0942
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/common.unit.spec.ts
@@ -0,0 +1,16 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("TagEditorHelp (OSS)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(screen.getByText("Read the full documentation")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(screen.getByText("Read the full documentation")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/enterprise.unit.spec.ts b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..52f71e6a434a38e8cfa7d8203f0941046895ba48
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/enterprise.unit.spec.ts
@@ -0,0 +1,24 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    ...opts,
+  });
+}
+
+describe("TagEditorHelp (EE without token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(screen.getByText("Read the full documentation")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(screen.getByText("Read the full documentation")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/premium.unit.spec.ts b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e9bd3b03fdc7dd1ee5a71b416a289f468c304b37
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/premium.unit.spec.ts
@@ -0,0 +1,27 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("TagEditorHelp (EE with token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(screen.getByText("Read the full documentation")).toBeInTheDocument();
+  });
+
+  it("should not show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.queryByText("Read the full documentation"),
+    ).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/setup.tsx b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0237eabb98d6ed2b060bc0fefce627a5b4f59379
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/template_tags/TagEditorHelp/tests/setup.tsx
@@ -0,0 +1,46 @@
+import type { TokenFeatures } from "metabase-types/api";
+import {
+  createMockDatabase,
+  createMockTokenFeatures,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import Database from "metabase-lib/metadata/Database";
+import { TagEditorHelp } from "../TagEditorHelp";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(
+    <TagEditorHelp
+      database={new Database({ ...createMockDatabase(), tables: [] })}
+      sampleDatabaseId={99}
+      setDatasetQuery={jest.fn()}
+      switchToSettings={jest.fn()}
+    />,
+    {
+      storeInitialState: state,
+    },
+  );
+};
diff --git a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/PreviewQueryModal.tsx b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/PreviewQueryModal.tsx
index a6e8197854995244078978c135472de6345c35e1..42662d8740a3655c8bc085527f6d213e7519f21e 100644
--- a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/PreviewQueryModal.tsx
+++ b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/PreviewQueryModal.tsx
@@ -1,31 +1,32 @@
-import { connect } from "react-redux";
 import { t } from "ttag";
+import { useCallback } from "react";
 import MetabaseSettings from "metabase/lib/settings";
 import {
   getNativeQueryFn,
   getQuestion,
 } from "metabase/query_builder/selectors";
-import type { NativeQueryForm } from "metabase-types/api";
-import type { State } from "metabase-types/store";
-import type Question from "metabase-lib/Question";
+import { checkNotNull } from "metabase/lib/types";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
 import NativeQueryModal, { useNativeQuery } from "../NativeQueryModal";
 import { ModalExternalLink } from "./PreviewQueryModal.styled";
 
 interface PreviewQueryModalProps {
-  question: Question;
-  onLoadQuery: ({ pretty }: { pretty?: boolean }) => Promise<NativeQueryForm>;
   onClose?: () => void;
 }
 
-const PreviewQueryModal = ({
-  question,
-  onLoadQuery,
+export const PreviewQueryModal = ({
   onClose,
 }: PreviewQueryModalProps): JSX.Element => {
-  const { query, error, isLoading } = useNativeQuery(question, () =>
-    onLoadQuery({ pretty: false }),
+  const question = checkNotNull(useSelector(getQuestion));
+  const onLoadQuery = useSelector(getNativeQueryFn);
+  const handleLoadQuery = useCallback(
+    () => onLoadQuery({ pretty: false }),
+    [onLoadQuery],
   );
+  const { query, error, isLoading } = useNativeQuery(question, handleLoadQuery);
   const learnUrl = MetabaseSettings.learnUrl("debugging-sql/sql-syntax");
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
 
   return (
     <NativeQueryModal
@@ -35,7 +36,7 @@ const PreviewQueryModal = ({
       isLoading={isLoading}
       onClose={onClose}
     >
-      {error && (
+      {error && showMetabaseLinks && (
         <ModalExternalLink href={learnUrl}>
           {t`Learn how to debug SQL errors`}
         </ModalExternalLink>
@@ -43,13 +44,3 @@ const PreviewQueryModal = ({
     </NativeQueryModal>
   );
 };
-
-const mapStateToProps = (state: State) => ({
-  // FIXME: remove the non-null assertion operator
-  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-  question: getQuestion(state)!,
-  onLoadQuery: getNativeQueryFn(state),
-});
-
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export default connect(mapStateToProps)(PreviewQueryModal);
diff --git a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/index.ts b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/index.ts
index e2d9200b81d618cb5a58111c39760c95a4e2ce16..54756d74cecf051c370bea2ca7a5e5cadd74bfd9 100644
--- a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/index.ts
+++ b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/index.ts
@@ -1,2 +1 @@
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export { default } from "./PreviewQueryModal";
+export { PreviewQueryModal } from "./PreviewQueryModal";
diff --git a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/common.unit.spec.tsx b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/common.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b84032b427564418ed10e081ae69ffe05c7d9eee
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/common.unit.spec.tsx
@@ -0,0 +1,22 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("PreviewQueryModal (OSS)", () => {
+  it("should render help link when `show-metabase-links: true", async () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(await screen.findByText("Query preview")).toBeInTheDocument();
+    expect(
+      screen.getByText("Learn how to debug SQL errors"),
+    ).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false", async () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(await screen.findByText("Query preview")).toBeInTheDocument();
+    expect(
+      screen.getByText("Learn how to debug SQL errors"),
+    ).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/enterprise.unit.spec.tsx b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/enterprise.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..09cf0e31bd45d32bf0b94b8d2da32ea8ec8a6647
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/enterprise.unit.spec.tsx
@@ -0,0 +1,27 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("PreviewQueryModal (EE without token)", () => {
+  it("should render help link when `show-metabase-links: true", async () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(await screen.findByText("Query preview")).toBeInTheDocument();
+    expect(
+      screen.getByText("Learn how to debug SQL errors"),
+    ).toBeInTheDocument();
+  });
+
+  it("should render help link when `show-metabase-links: false", async () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(await screen.findByText("Query preview")).toBeInTheDocument();
+    expect(
+      screen.getByText("Learn how to debug SQL errors"),
+    ).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/premium.unit.spec.tsx b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/premium.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7a9bd3877c3b668a5d0097278524390990fe7a73
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/premium.unit.spec.tsx
@@ -0,0 +1,31 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("PreviewQueryModal (EE with token)", () => {
+  it("should render help link when `show-metabase-links: true", async () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(await screen.findByText("Query preview")).toBeInTheDocument();
+    expect(
+      screen.getByText("Learn how to debug SQL errors"),
+    ).toBeInTheDocument();
+  });
+
+  it("should not render help link when `show-metabase-links: false", async () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(await screen.findByText("Query preview")).toBeInTheDocument();
+    expect(
+      screen.queryByText("Learn how to debug SQL errors"),
+    ).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/setup.tsx b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e2f77939b62df4d2564d14d1df836127d944758b
--- /dev/null
+++ b/frontend/src/metabase/query_builder/components/view/PreviewQueryModal/tests/setup.tsx
@@ -0,0 +1,55 @@
+import fetchMock from "fetch-mock";
+import type { TokenFeatures } from "metabase-types/api";
+import {
+  createMockCard,
+  createMockDatabase,
+  createMockTokenFeatures,
+} from "metabase-types/api/mocks";
+import {
+  createMockQueryBuilderState,
+  createMockState,
+} from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { createMockEntitiesState } from "__support__/store";
+import { renderWithProviders } from "__support__/ui";
+
+import { PreviewQueryModal } from "..";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const card = createMockCard();
+  const state = createMockState({
+    qb: createMockQueryBuilderState({ card }),
+    entities: createMockEntitiesState({
+      databases: [createMockDatabase()],
+      questions: [card],
+    }),
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  fetchMock.post("path:/api/dataset/native", {
+    status: 500,
+    body: {
+      message: 'Cannot run the query: missing required parameters: #{"value"}',
+    },
+  });
+
+  renderWithProviders(<PreviewQueryModal />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/reference/metrics/MetricList.jsx b/frontend/src/metabase/reference/metrics/MetricList.jsx
deleted file mode 100644
index 6097af58dd4983936e4822760c71019579eef0fa..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/reference/metrics/MetricList.jsx
+++ /dev/null
@@ -1,93 +0,0 @@
-/* eslint "react/prop-types": "warn" */
-import { Component } from "react";
-import PropTypes from "prop-types";
-import { connect } from "react-redux";
-import { t } from "ttag";
-
-import S from "metabase/components/List/List.css";
-
-import List from "metabase/components/List";
-import ListItem from "metabase/components/ListItem";
-import AdminAwareEmptyState from "metabase/components/AdminAwareEmptyState";
-
-import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
-
-import MetabaseSettings from "metabase/lib/settings";
-import * as metadataActions from "metabase/redux/metadata";
-import ReferenceHeader from "../components/ReferenceHeader";
-
-import { getMetrics, getError, getLoading } from "../selectors";
-
-const emptyStateData = {
-  title: t`Metrics are the official numbers that your team cares about`,
-  adminMessage: t`Defining common metrics for your team makes it even easier to ask questions`,
-  message: t`Metrics will appear here once your admins have created some`,
-  image: "app/assets/img/metrics-list",
-  adminAction: t`Learn how to create metrics`,
-  adminLink: MetabaseSettings.docsUrl(
-    "data-modeling/segments-and-metrics",
-    "creating-a-metric",
-  ),
-};
-
-const mapStateToProps = (state, props) => ({
-  entities: getMetrics(state, props),
-  loading: getLoading(state, props),
-  loadingError: getError(state, props),
-});
-
-const mapDispatchToProps = {
-  ...metadataActions,
-};
-
-class MetricList extends Component {
-  static propTypes = {
-    style: PropTypes.object.isRequired,
-    entities: PropTypes.object.isRequired,
-    loading: PropTypes.bool,
-    loadingError: PropTypes.object,
-  };
-
-  render() {
-    const { entities, style, loadingError, loading } = this.props;
-
-    return (
-      <div style={style} className="full">
-        <ReferenceHeader name={t`Metrics`} />
-        <LoadingAndErrorWrapper
-          loading={!loadingError && loading}
-          error={loadingError}
-        >
-          {() =>
-            Object.keys(entities).length > 0 ? (
-              <div className="wrapper wrapper--trim">
-                <List>
-                  {Object.values(entities).map(
-                    entity =>
-                      entity &&
-                      entity.id &&
-                      entity.name && (
-                        <ListItem
-                          key={entity.id}
-                          name={entity.display_name || entity.name}
-                          description={entity.description}
-                          url={`/reference/metrics/${entity.id}`}
-                          icon="ruler"
-                        />
-                      ),
-                  )}
-                </List>
-              </div>
-            ) : (
-              <div className={S.empty}>
-                <AdminAwareEmptyState {...emptyStateData} />
-              </div>
-            )
-          }
-        </LoadingAndErrorWrapper>
-      </div>
-    );
-  }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(MetricList);
diff --git a/frontend/src/metabase/reference/metrics/MetricList/MetricList.tsx b/frontend/src/metabase/reference/metrics/MetricList/MetricList.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..81b30f71a11b45b8104e8c6e529019d61d470bac
--- /dev/null
+++ b/frontend/src/metabase/reference/metrics/MetricList/MetricList.tsx
@@ -0,0 +1,81 @@
+import type { CSSProperties } from "react";
+import { t } from "ttag";
+
+import S from "metabase/components/List/List.css";
+
+import List from "metabase/components/List";
+import ListItem from "metabase/components/ListItem";
+import AdminAwareEmptyState from "metabase/components/AdminAwareEmptyState";
+
+import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
+
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { getDocsUrl } from "metabase/selectors/settings";
+import ReferenceHeader from "../../components/ReferenceHeader";
+
+import { getMetrics, getError, getLoading } from "../../selectors";
+
+const emptyStateData = {
+  title: t`Metrics are the official numbers that your team cares about`,
+  adminMessage: t`Defining common metrics for your team makes it even easier to ask questions`,
+  message: t`Metrics will appear here once your admins have created some`,
+  image: "app/assets/img/metrics-list",
+  adminAction: t`Learn how to create metrics`,
+};
+
+interface MetricListProps {
+  style?: CSSProperties;
+}
+
+export function MetricList({ style }: MetricListProps) {
+  const entities = useSelector(getMetrics);
+  const loading = useSelector(getLoading);
+  const loadingError = useSelector(getError);
+  const adminLink = useSelector(state =>
+    getDocsUrl(state, {
+      page: "data-modeling/segments-and-metrics",
+      anchor: "creating-a-metric",
+    }),
+  );
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+  return (
+    <div style={style} className="full">
+      <ReferenceHeader name={t`Metrics`} />
+      <LoadingAndErrorWrapper
+        loading={!loadingError && loading}
+        error={loadingError}
+      >
+        {() =>
+          Object.keys(entities).length > 0 ? (
+            <div className="wrapper wrapper--trim">
+              <List>
+                {Object.values(entities).map(
+                  entity =>
+                    entity &&
+                    entity.id &&
+                    entity.name && (
+                      <ListItem
+                        key={entity.id}
+                        name={entity.name}
+                        description={entity.description}
+                        url={`/reference/metrics/${entity.id}`}
+                        icon="ruler"
+                      />
+                    ),
+                )}
+              </List>
+            </div>
+          ) : (
+            <div className={S.empty}>
+              <AdminAwareEmptyState
+                {...emptyStateData}
+                adminLink={showMetabaseLinks ? adminLink : undefined}
+              />
+            </div>
+          )
+        }
+      </LoadingAndErrorWrapper>
+    </div>
+  );
+}
diff --git a/frontend/src/metabase/reference/metrics/MetricList/index.ts b/frontend/src/metabase/reference/metrics/MetricList/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b21b9b6715aeb37ae3c600b9203b4dcfa3a05abf
--- /dev/null
+++ b/frontend/src/metabase/reference/metrics/MetricList/index.ts
@@ -0,0 +1 @@
+export { MetricList } from "./MetricList";
diff --git a/frontend/src/metabase/reference/metrics/MetricList/tests/common.unit.spec.ts b/frontend/src/metabase/reference/metrics/MetricList/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e786b27b79940f7b8f86ebd4d6c2a5e9730241b9
--- /dev/null
+++ b/frontend/src/metabase/reference/metrics/MetricList/tests/common.unit.spec.ts
@@ -0,0 +1,53 @@
+import { createMockUser } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("MetricList (OSS)", () => {
+  describe("Admins", () => {
+    const adminUser = createMockUser({
+      is_superuser: true,
+    });
+
+    it("should render help link when `show-metabase-links: true`", () => {
+      setup({ user: adminUser, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create metrics"),
+      ).toBeInTheDocument();
+    });
+
+    it("should render help link when `show-metabase-links: false`", () => {
+      setup({ user: adminUser, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create metrics"),
+      ).toBeInTheDocument();
+    });
+  });
+
+  describe("Non-admins", () => {
+    const user = createMockUser();
+    it("should not render help link", () => {
+      setup({ user });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create metrics"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/reference/metrics/MetricList/tests/enterprise.unit.spec.ts b/frontend/src/metabase/reference/metrics/MetricList/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e733e1c0966100702abaf7725316b3361ebc13d3
--- /dev/null
+++ b/frontend/src/metabase/reference/metrics/MetricList/tests/enterprise.unit.spec.ts
@@ -0,0 +1,61 @@
+import { createMockUser } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    ...opts,
+  });
+}
+
+describe("MetricList (EE without token)", () => {
+  describe("Admins", () => {
+    const adminUser = createMockUser({
+      is_superuser: true,
+    });
+
+    it("should render help link when `show-metabase-links: true`", () => {
+      setup({ user: adminUser, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create metrics"),
+      ).toBeInTheDocument();
+    });
+
+    it("should render help link when `show-metabase-links: false`", () => {
+      setup({ user: adminUser, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create metrics"),
+      ).toBeInTheDocument();
+    });
+  });
+
+  describe("Non-admins", () => {
+    const user = createMockUser();
+    it("should not render help link", () => {
+      setup({ user });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create metrics"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/reference/metrics/MetricList/tests/premium.unit.spec.ts b/frontend/src/metabase/reference/metrics/MetricList/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..39df9e08796df86ba5f4467d91abe5210b22c03e
--- /dev/null
+++ b/frontend/src/metabase/reference/metrics/MetricList/tests/premium.unit.spec.ts
@@ -0,0 +1,62 @@
+import { createMockUser } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("MetricList (EE with token)", () => {
+  describe("Admins", () => {
+    const adminUser = createMockUser({
+      is_superuser: true,
+    });
+
+    it("should render help link when `show-metabase-links: true`", () => {
+      setup({ user: adminUser, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create metrics"),
+      ).toBeInTheDocument();
+    });
+
+    it("should not render help link when `show-metabase-links: false`", () => {
+      setup({ user: adminUser, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create metrics"),
+      ).not.toBeInTheDocument();
+    });
+  });
+
+  describe("Non-admins", () => {
+    const user = createMockUser();
+    it("should not render help link", () => {
+      setup({ user });
+
+      expect(
+        screen.getByText(
+          "Metrics are the official numbers that your team cares about",
+        ),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create metrics"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/reference/metrics/MetricList/tests/setup.tsx b/frontend/src/metabase/reference/metrics/MetricList/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2bd4736d57d7774e6db467199f8de6b74e94f53d
--- /dev/null
+++ b/frontend/src/metabase/reference/metrics/MetricList/tests/setup.tsx
@@ -0,0 +1,38 @@
+import type { TokenFeatures, User } from "metabase-types/api";
+import {
+  createMockTokenFeatures,
+  createMockUser,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { MetricList } from "../MetricList";
+
+export interface SetupOpts {
+  user: User;
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  user,
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) => {
+  const state = createMockState({
+    currentUser: createMockUser(user),
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<MetricList />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/reference/metrics/MetricListContainer.jsx b/frontend/src/metabase/reference/metrics/MetricListContainer.jsx
index 0dadc5950800d8ff0599018cadfe5e0dc7c35bdc..b2f6cdb711c99de4bd60c29fef20958941aa458c 100644
--- a/frontend/src/metabase/reference/metrics/MetricListContainer.jsx
+++ b/frontend/src/metabase/reference/metrics/MetricListContainer.jsx
@@ -5,7 +5,7 @@ import { connect } from "react-redux";
 
 import BaseSidebar from "metabase/reference/guide/BaseSidebar";
 import SidebarLayout from "metabase/components/SidebarLayout";
-import MetricList from "metabase/reference/metrics/MetricList";
+import { MetricList } from "metabase/reference/metrics/MetricList";
 
 import * as metadataActions from "metabase/redux/metadata";
 import * as actions from "metabase/reference/reference";
diff --git a/frontend/src/metabase/reference/segments/SegmentList.jsx b/frontend/src/metabase/reference/segments/SegmentList.jsx
deleted file mode 100644
index 6ab37213572346795df0c948e300eb497aea42df..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/reference/segments/SegmentList.jsx
+++ /dev/null
@@ -1,93 +0,0 @@
-/* eslint "react/prop-types": "warn" */
-import { Component } from "react";
-import PropTypes from "prop-types";
-import { connect } from "react-redux";
-import { t } from "ttag";
-import MetabaseSettings from "metabase/lib/settings";
-
-import S from "metabase/components/List/List.css";
-
-import List from "metabase/components/List";
-import ListItem from "metabase/components/ListItem";
-import AdminAwareEmptyState from "metabase/components/AdminAwareEmptyState";
-
-import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
-
-import * as metadataActions from "metabase/redux/metadata";
-import ReferenceHeader from "../components/ReferenceHeader";
-
-import { getSegments, getError, getLoading } from "../selectors";
-
-const emptyStateData = {
-  title: t`Segments are interesting subsets of tables`,
-  adminMessage: t`Defining common segments for your team makes it even easier to ask questions`,
-  message: t`Segments will appear here once your admins have created some`,
-  image: "app/assets/img/segments-list",
-  adminAction: t`Learn how to create segments`,
-  adminLink: MetabaseSettings.docsUrl(
-    "data-modeling/segments-and-metrics",
-    "creating-a-segment",
-  ),
-};
-
-const mapStateToProps = (state, props) => ({
-  entities: getSegments(state, props),
-  loading: getLoading(state, props),
-  loadingError: getError(state, props),
-});
-
-const mapDispatchToProps = {
-  ...metadataActions,
-};
-
-class SegmentList extends Component {
-  static propTypes = {
-    style: PropTypes.object.isRequired,
-    entities: PropTypes.object.isRequired,
-    loading: PropTypes.bool,
-    loadingError: PropTypes.object,
-  };
-
-  render() {
-    const { entities, style, loadingError, loading } = this.props;
-
-    return (
-      <div style={style} className="full">
-        <ReferenceHeader name={t`Segments`} />
-        <LoadingAndErrorWrapper
-          loading={!loadingError && loading}
-          error={loadingError}
-        >
-          {() =>
-            Object.keys(entities).length > 0 ? (
-              <div className="wrapper wrapper--trim">
-                <List>
-                  {Object.values(entities).map(
-                    entity =>
-                      entity &&
-                      entity.id &&
-                      entity.name && (
-                        <ListItem
-                          key={entity.id}
-                          name={entity.display_name || entity.name}
-                          description={entity.description}
-                          url={`/reference/segments/${entity.id}`}
-                          icon="segment"
-                        />
-                      ),
-                  )}
-                </List>
-              </div>
-            ) : (
-              <div className={S.empty}>
-                <AdminAwareEmptyState {...emptyStateData} />
-              </div>
-            )
-          }
-        </LoadingAndErrorWrapper>
-      </div>
-    );
-  }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(SegmentList);
diff --git a/frontend/src/metabase/reference/segments/SegmentList/SegmentList.tsx b/frontend/src/metabase/reference/segments/SegmentList/SegmentList.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4837d57e4e4c1b6e68a2dfc21abe9ff496aa7706
--- /dev/null
+++ b/frontend/src/metabase/reference/segments/SegmentList/SegmentList.tsx
@@ -0,0 +1,81 @@
+import type { CSSProperties } from "react";
+import { t } from "ttag";
+
+import S from "metabase/components/List/List.css";
+
+import List from "metabase/components/List";
+import ListItem from "metabase/components/ListItem";
+import AdminAwareEmptyState from "metabase/components/AdminAwareEmptyState";
+
+import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
+
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { getDocsUrl } from "metabase/selectors/settings";
+import ReferenceHeader from "../../components/ReferenceHeader";
+
+import { getSegments, getError, getLoading } from "../../selectors";
+
+const emptyStateData = {
+  title: t`Segments are interesting subsets of tables`,
+  adminMessage: t`Defining common segments for your team makes it even easier to ask questions`,
+  message: t`Segments will appear here once your admins have created some`,
+  image: "app/assets/img/segments-list",
+  adminAction: t`Learn how to create segments`,
+};
+
+interface SegmentListProps {
+  style?: CSSProperties;
+}
+
+export function SegmentList({ style }: SegmentListProps) {
+  const entities = useSelector(getSegments);
+  const loading = useSelector(getLoading);
+  const loadingError = useSelector(getError);
+  const adminLink = useSelector(state =>
+    getDocsUrl(state, {
+      page: "data-modeling/segments-and-metrics",
+      anchor: "creating-a-segment",
+    }),
+  );
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+  return (
+    <div style={style} className="full">
+      <ReferenceHeader name={t`Segments`} />
+      <LoadingAndErrorWrapper
+        loading={!loadingError && loading}
+        error={loadingError}
+      >
+        {() =>
+          Object.keys(entities).length > 0 ? (
+            <div className="wrapper wrapper--trim">
+              <List>
+                {Object.values(entities).map(
+                  entity =>
+                    entity &&
+                    entity.id &&
+                    entity.name && (
+                      <ListItem
+                        key={entity.id}
+                        name={entity.name}
+                        description={entity.description}
+                        url={`/reference/segments/${entity.id}`}
+                        icon="segment"
+                      />
+                    ),
+                )}
+              </List>
+            </div>
+          ) : (
+            <div className={S.empty}>
+              <AdminAwareEmptyState
+                {...emptyStateData}
+                adminLink={showMetabaseLinks ? adminLink : undefined}
+              />
+            </div>
+          )
+        }
+      </LoadingAndErrorWrapper>
+    </div>
+  );
+}
diff --git a/frontend/src/metabase/reference/segments/SegmentList/index.ts b/frontend/src/metabase/reference/segments/SegmentList/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..20289d9e93b3306eecd39182e1e5cc59956330ef
--- /dev/null
+++ b/frontend/src/metabase/reference/segments/SegmentList/index.ts
@@ -0,0 +1 @@
+export { SegmentList } from "./SegmentList";
diff --git a/frontend/src/metabase/reference/segments/SegmentList/tests/common.unit.spec.ts b/frontend/src/metabase/reference/segments/SegmentList/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4b10dc07b993672ea6b882d0fad3654db18d7572
--- /dev/null
+++ b/frontend/src/metabase/reference/segments/SegmentList/tests/common.unit.spec.ts
@@ -0,0 +1,47 @@
+import { createMockUser } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("SegmentList (OSS)", () => {
+  describe("Admins", () => {
+    const adminUser = createMockUser({
+      is_superuser: true,
+    });
+
+    it("should render help link when `show-metabase-links: true`", () => {
+      setup({ user: adminUser, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create segments"),
+      ).toBeInTheDocument();
+    });
+
+    it("should render help link when `show-metabase-links: false`", () => {
+      setup({ user: adminUser, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create segments"),
+      ).toBeInTheDocument();
+    });
+  });
+
+  describe("Non-admins", () => {
+    const user = createMockUser();
+    it("should not render help link", () => {
+      setup({ user });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create segments"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/reference/segments/SegmentList/tests/enterprise.unit.spec.ts b/frontend/src/metabase/reference/segments/SegmentList/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7363bfe9754a95ca14ca86258552d8484e9a851e
--- /dev/null
+++ b/frontend/src/metabase/reference/segments/SegmentList/tests/enterprise.unit.spec.ts
@@ -0,0 +1,55 @@
+import { createMockUser } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    ...opts,
+  });
+}
+
+describe("SegmentList (EE without token)", () => {
+  describe("Admins", () => {
+    const adminUser = createMockUser({
+      is_superuser: true,
+    });
+
+    it("should render help link when `show-metabase-links: true`", () => {
+      setup({ user: adminUser, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create segments"),
+      ).toBeInTheDocument();
+    });
+
+    it("should render help link when `show-metabase-links: false`", () => {
+      setup({ user: adminUser, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create segments"),
+      ).toBeInTheDocument();
+    });
+  });
+
+  describe("Non-admins", () => {
+    const user = createMockUser();
+    it("should not render help link", () => {
+      setup({ user });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create segments"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/reference/segments/SegmentList/tests/premium.unit.spec.ts b/frontend/src/metabase/reference/segments/SegmentList/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..056e3cb212d081aa28d568036d6d1913c96770b6
--- /dev/null
+++ b/frontend/src/metabase/reference/segments/SegmentList/tests/premium.unit.spec.ts
@@ -0,0 +1,56 @@
+import { createMockUser } from "metabase-types/api/mocks";
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("SegmentList (EE with token)", () => {
+  describe("Admins", () => {
+    const adminUser = createMockUser({
+      is_superuser: true,
+    });
+
+    it("should render help link when `show-metabase-links: true`", () => {
+      setup({ user: adminUser, showMetabaseLinks: true });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.getByText("Learn how to create segments"),
+      ).toBeInTheDocument();
+    });
+
+    it("should not render help link when `show-metabase-links: false`", () => {
+      setup({ user: adminUser, showMetabaseLinks: false });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create segments"),
+      ).not.toBeInTheDocument();
+    });
+  });
+
+  describe("Non-admins", () => {
+    const user = createMockUser();
+    it("should not render help link", () => {
+      setup({ user });
+
+      expect(
+        screen.getByText("Segments are interesting subsets of tables"),
+      ).toBeInTheDocument();
+      expect(
+        screen.queryByText("Learn how to create segments"),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/reference/segments/SegmentList/tests/setup.tsx b/frontend/src/metabase/reference/segments/SegmentList/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e24638ea71bff4b5d9920cd2e415e34aa8b5ffaa
--- /dev/null
+++ b/frontend/src/metabase/reference/segments/SegmentList/tests/setup.tsx
@@ -0,0 +1,38 @@
+import type { TokenFeatures, User } from "metabase-types/api";
+import {
+  createMockTokenFeatures,
+  createMockUser,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { SegmentList } from "../SegmentList";
+
+export interface SetupOpts {
+  user: User;
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  user,
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) => {
+  const state = createMockState({
+    currentUser: createMockUser(user),
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<SegmentList />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/reference/segments/SegmentListContainer.jsx b/frontend/src/metabase/reference/segments/SegmentListContainer.jsx
index 47fb171140aece70c9617c6e59ceaa485e88791a..bbf8a376fbfdf6ab5206ebfd4e81bea80cac768d 100644
--- a/frontend/src/metabase/reference/segments/SegmentListContainer.jsx
+++ b/frontend/src/metabase/reference/segments/SegmentListContainer.jsx
@@ -5,7 +5,7 @@ import { connect } from "react-redux";
 
 import BaseSidebar from "metabase/reference/guide/BaseSidebar";
 import SidebarLayout from "metabase/components/SidebarLayout";
-import SegmentList from "metabase/reference/segments/SegmentList";
+import { SegmentList } from "metabase/reference/segments/SegmentList";
 
 import * as metadataActions from "metabase/redux/metadata";
 import * as actions from "metabase/reference/reference";
diff --git a/frontend/src/metabase/selectors/whitelabel/index.ts b/frontend/src/metabase/selectors/whitelabel/index.ts
index 8314df567c0e1695b0e38d595c52f9d02f68de4a..111715e600678c50315949cfd35240da5e642974 100644
--- a/frontend/src/metabase/selectors/whitelabel/index.ts
+++ b/frontend/src/metabase/selectors/whitelabel/index.ts
@@ -16,3 +16,7 @@ export function getApplicationName(state: State) {
 export function getCanWhitelabel(state: State) {
   return PLUGIN_SELECTORS.canWhitelabel(state);
 }
+
+export function getShowMetabaseLinks(state: State) {
+  return PLUGIN_SELECTORS.getShowMetabaseLinks(state);
+}
diff --git a/frontend/src/metabase/selectors/whitelabel/tests/common.unit.spec.ts b/frontend/src/metabase/selectors/whitelabel/tests/common.unit.spec.ts
index 4b71c2697dffda8827e9fd3eba3fa3fb2a0d1103..66128307fb97fd700d58cdc227713319aa2ed43e 100644
--- a/frontend/src/metabase/selectors/whitelabel/tests/common.unit.spec.ts
+++ b/frontend/src/metabase/selectors/whitelabel/tests/common.unit.spec.ts
@@ -1,6 +1,7 @@
 import {
   getApplicationName,
   getIsWhiteLabeling,
+  getShowMetabaseLinks,
   getWhiteLabeledLoadingMessage,
   getCanWhitelabel,
 } from "..";
@@ -61,3 +62,17 @@ describe("getCanWhitelabel (OSS)", () => {
     expect(getCanWhitelabel(getState())).toBe(false);
   });
 });
+
+describe("getShowMetabaseLinks (OSS)", () => {
+  it("should return true when show-metabase-links is true", () => {
+    const { getState } = setup({ showMetabaseLinks: true });
+
+    expect(getShowMetabaseLinks(getState())).toBe(true);
+  });
+
+  it("should return true when show-metabase-links is false", () => {
+    const { getState } = setup({ showMetabaseLinks: false });
+
+    expect(getShowMetabaseLinks(getState())).toBe(true);
+  });
+});
diff --git a/frontend/src/metabase/selectors/whitelabel/tests/enterprise.unit.spec.ts b/frontend/src/metabase/selectors/whitelabel/tests/enterprise.unit.spec.ts
index 27ac486bc451d9394bc7bbd404373b3c1e54fe19..44c7cc39bf1b8e7fd0c7b432e3ab0fd7e540dfb9 100644
--- a/frontend/src/metabase/selectors/whitelabel/tests/enterprise.unit.spec.ts
+++ b/frontend/src/metabase/selectors/whitelabel/tests/enterprise.unit.spec.ts
@@ -2,6 +2,7 @@ import {
   getApplicationName,
   getCanWhitelabel,
   getIsWhiteLabeling,
+  getShowMetabaseLinks,
   getWhiteLabeledLoadingMessage,
 } from "..";
 import type { SetupOpts } from "./setup";
@@ -66,3 +67,17 @@ describe("getCanWhitelabel (EE without token)", () => {
     expect(getCanWhitelabel(getState())).toBe(false);
   });
 });
+
+describe("getShowMetabaseLinks (EE without token)", () => {
+  it("should return true when show-metabase-links is true", () => {
+    const { getState } = setup({ showMetabaseLinks: true });
+
+    expect(getShowMetabaseLinks(getState())).toBe(true);
+  });
+
+  it("should return true when show-metabase-links is false", () => {
+    const { getState } = setup({ showMetabaseLinks: false });
+
+    expect(getShowMetabaseLinks(getState())).toBe(true);
+  });
+});
diff --git a/frontend/src/metabase/selectors/whitelabel/tests/premium.unit.spec.ts b/frontend/src/metabase/selectors/whitelabel/tests/premium.unit.spec.ts
index f688b9d82f5ccfe806514b07877b63f36ad01798..cc843ede3b81037a1c6d7bd3d85c9bcf4805795e 100644
--- a/frontend/src/metabase/selectors/whitelabel/tests/premium.unit.spec.ts
+++ b/frontend/src/metabase/selectors/whitelabel/tests/premium.unit.spec.ts
@@ -2,6 +2,7 @@ import {
   getApplicationName,
   getCanWhitelabel,
   getIsWhiteLabeling,
+  getShowMetabaseLinks,
   getWhiteLabeledLoadingMessage,
 } from "..";
 import type { SetupOpts } from "./setup";
@@ -65,10 +66,24 @@ describe("getApplicationName (EE with token)", () => {
   });
 });
 
-describe("getCanWhitelabel (EE without token)", () => {
+describe("getCanWhitelabel (EE with token)", () => {
   it("should return true", () => {
     const { getState } = setup();
 
     expect(getCanWhitelabel(getState())).toBe(true);
   });
 });
+
+describe("getShowMetabaseLinks (EE with token)", () => {
+  it("should return true when show-metabase-links is true", () => {
+    const { getState } = setup({ showMetabaseLinks: true });
+
+    expect(getShowMetabaseLinks(getState())).toBe(true);
+  });
+
+  it("should return false when show-metabase-links is false", () => {
+    const { getState } = setup({ showMetabaseLinks: false });
+
+    expect(getShowMetabaseLinks(getState())).toBe(false);
+  });
+});
diff --git a/frontend/src/metabase/selectors/whitelabel/tests/setup.tsx b/frontend/src/metabase/selectors/whitelabel/tests/setup.tsx
index 2bf0ad55d24f45ab55bf6e670ec578bf4d2acc98..68e12ba125b91775a4518889581704f5172186fe 100644
--- a/frontend/src/metabase/selectors/whitelabel/tests/setup.tsx
+++ b/frontend/src/metabase/selectors/whitelabel/tests/setup.tsx
@@ -10,6 +10,7 @@ import type { LoadingMessage, TokenFeatures } from "metabase-types/api";
 export interface SetupOpts {
   loadingMessage?: LoadingMessage;
   applicationName?: string;
+  showMetabaseLinks?: boolean;
   tokenFeatures?: Partial<TokenFeatures>;
   hasEnterprisePlugins?: boolean;
 }
@@ -17,6 +18,7 @@ export interface SetupOpts {
 export function setup({
   loadingMessage = "doing-science",
   applicationName = "Metabase",
+  showMetabaseLinks = true,
   tokenFeatures = {},
   hasEnterprisePlugins = false,
 }: SetupOpts = {}) {
@@ -25,6 +27,7 @@ export function setup({
       "loading-message": loadingMessage,
       "application-name": applicationName,
       "token-features": createMockTokenFeatures(tokenFeatures),
+      "show-metabase-links": showMetabaseLinks,
     }),
   });
 
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditEmailSidebar.jsx b/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditEmailSidebar.jsx
index ea5417ad4a346362af39a424c93fe58a6fa11084..42207690951045b5d31fdde0a6344ee4a2a8403d 100644
--- a/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditEmailSidebar.jsx
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditEmailSidebar.jsx
@@ -14,7 +14,7 @@ import RecipientPicker from "metabase/pulse/components/RecipientPicker";
 import SendTestPulse from "metabase/components/SendTestPulse";
 import DeleteSubscriptionAction from "./DeleteSubscriptionAction";
 import DefaultParametersSection from "./DefaultParametersSection";
-import CaveatMessage from "./CaveatMessage";
+import { CaveatMessage } from "./CaveatMessage";
 import Heading from "./Heading";
 import { CHANNEL_NOUN_PLURAL } from "./constants";
 
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditSlackSidebar.jsx b/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditSlackSidebar.jsx
index 06733084ed730e0bcd4f8e2e11cb629cda9e06ad..890ec5e45761c50425cf0a9d5d56270d68c479d2 100644
--- a/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditSlackSidebar.jsx
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/AddEditSlackSidebar.jsx
@@ -12,7 +12,7 @@ import { dashboardPulseIsValid } from "metabase/lib/pulse";
 
 import { PLUGIN_DASHBOARD_SUBSCRIPTION_PARAMETERS_SECTION_OVERRIDE } from "metabase/plugins";
 import SlackChannelField from "../SlackChannelField";
-import CaveatMessage from "./CaveatMessage";
+import { CaveatMessage } from "./CaveatMessage";
 import Heading from "./Heading";
 import DeleteSubscriptionAction from "./DeleteSubscriptionAction";
 import DefaultParametersSection from "./DefaultParametersSection";
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage.jsx b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage.jsx
deleted file mode 100644
index f36874a08bf6d43a3a6967be4f9e5160edc1c745..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage.jsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { t } from "ttag";
-
-import MetabaseSettings from "metabase/lib/settings";
-import ExternalLink from "metabase/core/components/ExternalLink";
-import { CaveatText } from "./CaveatMessage.styled";
-
-function CaveatMessage() {
-  return (
-    <CaveatText>
-      {t`Recipients will see this data just as you see it, regardless of their permissions.`}
-      &nbsp;
-      <ExternalLink
-        className="link"
-        target="_blank"
-        href={MetabaseSettings.docsUrl("dashboards/subscriptions")}
-      >
-        {t`Learn more`}
-      </ExternalLink>
-      .
-    </CaveatText>
-  );
-}
-
-export default CaveatMessage;
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/CaveatMessage.jsx b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/CaveatMessage.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..67cbee4c4fa7df4dccaf111568148385ffb0bcb4
--- /dev/null
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/CaveatMessage.jsx
@@ -0,0 +1,28 @@
+import { t } from "ttag";
+
+import MetabaseSettings from "metabase/lib/settings";
+import ExternalLink from "metabase/core/components/ExternalLink";
+import { useSelector } from "metabase/lib/redux";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { CaveatText } from "./CaveatMessage.styled";
+
+export function CaveatMessage() {
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+  return (
+    <CaveatText>
+      {t`Recipients will see this data just as you see it, regardless of their permissions.`}
+      {showMetabaseLinks && (
+        <>
+          &nbsp;
+          <ExternalLink
+            className="link"
+            target="_blank"
+            href={MetabaseSettings.docsUrl("dashboards/subscriptions")}
+          >
+            {t`Learn more.`}
+          </ExternalLink>
+        </>
+      )}
+    </CaveatText>
+  );
+}
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage.styled.tsx b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/CaveatMessage.styled.tsx
similarity index 100%
rename from frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage.styled.tsx
rename to frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/CaveatMessage.styled.tsx
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/index.ts b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ea3addb607a8da1926bbb645b975271d262853f6
--- /dev/null
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/index.ts
@@ -0,0 +1 @@
+export { CaveatMessage } from "./CaveatMessage";
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/common.unit.spec.ts b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8d5ee152f2b7a306eb6dc7f06191c4f75305fb2e
--- /dev/null
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/common.unit.spec.ts
@@ -0,0 +1,26 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("CaveatMessage (OSS)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Recipients will see this data just as you see it, regardless of their permissions.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Recipients will see this data just as you see it, regardless of their permissions.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/enterprise.unit.spec.ts b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c1ca8b8cf71eb3444924b1a459c635aae1f70c80
--- /dev/null
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/enterprise.unit.spec.ts
@@ -0,0 +1,31 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("CaveatMessage (EE without token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Recipients will see this data just as you see it, regardless of their permissions.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+
+  it("should show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Recipients will see this data just as you see it, regardless of their permissions.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/premium.unit.spec.ts b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4302784110fbe888e8f7e081eca40f745848da6f
--- /dev/null
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/premium.unit.spec.ts
@@ -0,0 +1,35 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("CaveatMessage (EE with token)", () => {
+  it("should show a help link when `show-metabase-links: true`", () => {
+    setup({ showMetabaseLinks: true });
+
+    expect(
+      screen.getByText(
+        "Recipients will see this data just as you see it, regardless of their permissions.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Learn more.")).toBeInTheDocument();
+  });
+
+  it("should not show a help link when `show-metabase-links: false`", () => {
+    setup({ showMetabaseLinks: false });
+
+    expect(
+      screen.getByText(
+        "Recipients will see this data just as you see it, regardless of their permissions.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.queryByText("Learn more.")).not.toBeInTheDocument();
+  });
+});
diff --git a/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/setup.tsx b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..209b765b3438e88113890d6ebf40a3d23fd3274a
--- /dev/null
+++ b/frontend/src/metabase/sharing/components/AddEditSidebar/CaveatMessage/tests/setup.tsx
@@ -0,0 +1,32 @@
+import type { TokenFeatures } from "metabase-types/api";
+import { createMockTokenFeatures } from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { CaveatMessage } from "../CaveatMessage";
+
+export interface SetupOpts {
+  showMetabaseLinks?: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts = {}) => {
+  const state = createMockState({
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<CaveatMessage />, { storeInitialState: state });
+};
diff --git a/frontend/src/metabase/ui/components/overlays/Popover/use-popover.ts b/frontend/src/metabase/ui/components/overlays/Popover/use-popover.ts
index 8bc8bf3badd347faf47d465e6ab1223b8ab62462..6bd39ade120c487ba04bf970ec9f06e64effc785 100644
--- a/frontend/src/metabase/ui/components/overlays/Popover/use-popover.ts
+++ b/frontend/src/metabase/ui/components/overlays/Popover/use-popover.ts
@@ -112,7 +112,7 @@ export function usePopover(options: UsePopoverOptions) {
 
   return {
     floating,
-    controlled: options.opened !== null,
+    controlled: typeof options.opened === "boolean",
     opened: _opened,
     onClose,
     onToggle,
diff --git a/frontend/src/metabase/visualizations/register.js b/frontend/src/metabase/visualizations/register.js
index dafce70eef7fdc6ffba1d6d131b750e462bf942c..fb43b77924077c4234e71b457a7c15d159e65c0c 100644
--- a/frontend/src/metabase/visualizations/register.js
+++ b/frontend/src/metabase/visualizations/register.js
@@ -18,7 +18,7 @@ import RowChart from "./visualizations/RowChart";
 import PieChart from "./visualizations/PieChart";
 import AreaChart from "./visualizations/AreaChart";
 import ComboChart from "./visualizations/ComboChart";
-import MapViz from "./visualizations/Map";
+import { Map } from "./visualizations/Map";
 import ScatterPlot from "./visualizations/ScatterPlot";
 import Funnel from "./visualizations/Funnel";
 import Gauge from "./visualizations/Gauge";
@@ -42,7 +42,7 @@ export default function () {
   registerVisualization(RowChart);
   registerVisualization(ScatterPlot);
   registerVisualization(PieChart);
-  registerVisualization(MapViz);
+  registerVisualization(Map);
   registerVisualization(Funnel);
   registerVisualization(ObjectDetail);
   registerVisualization(PivotTable);
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/CustomMapFooter.tsx b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/CustomMapFooter.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..8d0d7e23d28b87bc7eb4e8547aecad3334116993
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/CustomMapFooter.tsx
@@ -0,0 +1,42 @@
+import { t } from "ttag";
+import Link from "metabase/core/components/Link";
+import ExternalLink from "metabase/core/components/ExternalLink";
+import { Icon } from "metabase/ui";
+import { getUserIsAdmin } from "metabase/selectors/user";
+import { useSelector } from "metabase/lib/redux";
+import { getDocsUrl } from "metabase/selectors/settings";
+import { getShowMetabaseLinks } from "metabase/selectors/whitelabel";
+import { CustomMapContent } from "../Maps.styled";
+
+export function CustomMapFooter() {
+  const isAdmin = useSelector(getUserIsAdmin);
+  const docsUrl = useSelector(state =>
+    getDocsUrl(state, { page: "configuring-metabase/custom-maps" }),
+  );
+  const showMetabaseLinks = useSelector(getShowMetabaseLinks);
+
+  const content = (
+    <CustomMapContent>
+      {t`Custom map`}
+      <Icon name="share" />
+    </CustomMapContent>
+  );
+
+  if (isAdmin) {
+    return (
+      <Link to="/admin/settings/maps" aria-label={t`Custom map`}>
+        {content}
+      </Link>
+    );
+  }
+
+  if (showMetabaseLinks) {
+    return (
+      <ExternalLink aria-label={t`Custom map`} href={docsUrl}>
+        {content}
+      </ExternalLink>
+    );
+  }
+
+  return null;
+}
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/index.ts b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cf1f06c0ee3ffbe0450f32ee545bc27e13e110d6
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/index.ts
@@ -0,0 +1 @@
+export { CustomMapFooter } from "./CustomMapFooter";
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/common.unit.spec.ts b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/common.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..514472030426381168550376e5fb6f053bee828e
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/common.unit.spec.ts
@@ -0,0 +1,60 @@
+import { screen } from "__support__/ui";
+import { setup } from "./setup";
+
+describe("CustomMapFooter (OSS)", () => {
+  describe("admin users", () => {
+    it("should show an admin settings link `show-metabase-links: true`", () => {
+      setup({ isAdmin: true, showMetabaseLinks: true });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "http://localhost/admin/settings/maps",
+      );
+    });
+
+    it("should show an admin settings link `show-metabase-links: false`", () => {
+      setup({ isAdmin: true, showMetabaseLinks: false });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "http://localhost/admin/settings/maps",
+      );
+    });
+  });
+
+  describe("non admin users", () => {
+    it("should show a help link when `show-metabase-links: true`", () => {
+      setup({ isAdmin: false, showMetabaseLinks: true });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "https://www.metabase.com/docs/latest/configuring-metabase/custom-maps.html",
+      );
+    });
+
+    it("should show a help link when `show-metabase-links: false`", () => {
+      setup({ isAdmin: false, showMetabaseLinks: false });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "https://www.metabase.com/docs/latest/configuring-metabase/custom-maps.html",
+      );
+    });
+  });
+});
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/enterprise.unit.spec.ts b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/enterprise.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..58b4b9143d819784fabf6debae89c9d637127c2e
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/enterprise.unit.spec.ts
@@ -0,0 +1,65 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({ hasEnterprisePlugins: true, ...opts });
+}
+
+describe("CustomMapFooter (EE without token)", () => {
+  describe("admin users", () => {
+    it("should show an admin settings link `show-metabase-links: true`", () => {
+      setup({ isAdmin: true, showMetabaseLinks: true });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "http://localhost/admin/settings/maps",
+      );
+    });
+
+    it("should show an admin settings link `show-metabase-links: false`", () => {
+      setup({ isAdmin: true, showMetabaseLinks: false });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "http://localhost/admin/settings/maps",
+      );
+    });
+  });
+
+  describe("non admin users", () => {
+    it("should show a help link when `show-metabase-links: true`", () => {
+      setup({ isAdmin: false, showMetabaseLinks: true });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "https://www.metabase.com/docs/latest/configuring-metabase/custom-maps.html",
+      );
+    });
+
+    it("should show a help link when `show-metabase-links: false`", () => {
+      setup({ isAdmin: false, showMetabaseLinks: false });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "https://www.metabase.com/docs/latest/configuring-metabase/custom-maps.html",
+      );
+    });
+  });
+});
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/premium.unit.spec.ts b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/premium.unit.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1fcb9794b28cdc0081c97ca55a667d62288c1816
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/premium.unit.spec.ts
@@ -0,0 +1,64 @@
+import { screen } from "__support__/ui";
+import { setup as baseSetup } from "./setup";
+import type { SetupOpts } from "./setup";
+
+function setup(opts: SetupOpts) {
+  baseSetup({
+    hasEnterprisePlugins: true,
+    tokenFeatures: { whitelabel: true },
+    ...opts,
+  });
+}
+
+describe("CustomMapFooter (EE with token)", () => {
+  describe("admin users", () => {
+    it("should show an admin settings link `show-metabase-links: true`", () => {
+      setup({ isAdmin: true, showMetabaseLinks: true });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "http://localhost/admin/settings/maps",
+      );
+    });
+
+    it("should show an admin settings link `show-metabase-links: false`", () => {
+      setup({ isAdmin: true, showMetabaseLinks: false });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "http://localhost/admin/settings/maps",
+      );
+    });
+  });
+
+  describe("non admin users", () => {
+    it("should show a help link when `show-metabase-links: true`", () => {
+      setup({ isAdmin: false, showMetabaseLinks: true });
+
+      const customMapOption = screen.getByRole("link", {
+        name: "Custom map",
+      });
+      expect(customMapOption).toBeInTheDocument();
+      expect(customMapOption).toHaveProperty(
+        "href",
+        "https://www.metabase.com/docs/latest/configuring-metabase/custom-maps.html",
+      );
+    });
+
+    it("should not show a help link when `show-metabase-links: false`", () => {
+      setup({ isAdmin: false, showMetabaseLinks: false });
+
+      expect(
+        screen.queryByRole("link", { name: "Custom map" }),
+      ).not.toBeInTheDocument();
+    });
+  });
+});
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/setup.tsx b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/setup.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..3fbcdd06f7bbb3eb2f29cb559a9a0882b48e08d5
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/CustomMapFooter/tests/setup.tsx
@@ -0,0 +1,42 @@
+import { Route } from "react-router";
+import type { TokenFeatures } from "metabase-types/api";
+import {
+  createMockTokenFeatures,
+  createMockUser,
+} from "metabase-types/api/mocks";
+import { createMockState } from "metabase-types/store/mocks";
+import { setupEnterprisePlugins } from "__support__/enterprise";
+import { mockSettings } from "__support__/settings";
+import { renderWithProviders } from "__support__/ui";
+import { CustomMapFooter } from "../CustomMapFooter";
+
+export interface SetupOpts {
+  isAdmin: boolean;
+  showMetabaseLinks: boolean;
+  hasEnterprisePlugins?: boolean;
+  tokenFeatures?: Partial<TokenFeatures>;
+}
+
+export const setup = ({
+  isAdmin,
+  showMetabaseLinks = true,
+  hasEnterprisePlugins,
+  tokenFeatures = {},
+}: SetupOpts) => {
+  const state = createMockState({
+    currentUser: createMockUser({ is_superuser: isAdmin }),
+    settings: mockSettings({
+      "show-metabase-links": showMetabaseLinks,
+      "token-features": createMockTokenFeatures(tokenFeatures),
+    }),
+  });
+
+  if (hasEnterprisePlugins) {
+    setupEnterprisePlugins();
+  }
+
+  renderWithProviders(<Route path="*" component={CustomMapFooter} />, {
+    storeInitialState: state,
+    withRouter: true,
+  });
+};
diff --git a/frontend/src/metabase/visualizations/visualizations/Map.jsx b/frontend/src/metabase/visualizations/visualizations/Map/Map.jsx
similarity index 90%
rename from frontend/src/metabase/visualizations/visualizations/Map.jsx
rename to frontend/src/metabase/visualizations/visualizations/Map/Map.jsx
index f56aafee57a872d56a4b1568e390bd2b4355637e..b0c1a7f9e3a075ab140cca77ab322b4332e64cf3 100644
--- a/frontend/src/metabase/visualizations/visualizations/Map.jsx
+++ b/frontend/src/metabase/visualizations/visualizations/Map/Map.jsx
@@ -1,14 +1,9 @@
 /* eslint-disable react/prop-types */
 import { Component } from "react";
-import { connect } from "react-redux";
 import { t } from "ttag";
 import _ from "underscore";
 import { ChartSettingsError } from "metabase/visualizations/lib/errors";
 
-import Link from "metabase/core/components/Link";
-import ExternalLink from "metabase/core/components/ExternalLink";
-import { Icon } from "metabase/ui";
-
 import { isSameSeries } from "metabase/visualizations/lib/utils";
 import {
   metricSetting,
@@ -18,7 +13,6 @@ import {
 import { columnSettings } from "metabase/visualizations/lib/settings/column";
 
 import MetabaseSettings from "metabase/lib/settings";
-import { getUserIsAdmin } from "metabase/selectors/user";
 
 const PIN_MAP_TYPES = new Set(["pin", "heat", "grid"]);
 
@@ -37,15 +31,14 @@ import {
   isState,
   isCountry,
 } from "metabase-lib/types/utils/isa";
-import LeafletGridHeatMap from "../components/LeafletGridHeatMap";
-import PinMap from "../components/PinMap";
+import LeafletGridHeatMap from "../../components/LeafletGridHeatMap";
+import PinMap from "../../components/PinMap";
 import ChoroplethMap, {
   getColorplethColorScale,
-} from "../components/ChoroplethMap";
-
-import { CustomMapContent } from "./Maps.styled";
+} from "../../components/ChoroplethMap";
+import { CustomMapFooter } from "./CustomMapFooter";
 
-export default class Map extends Component {
+export class Map extends Component {
   static uiName = t`Map`;
   static identifier = "map";
   static iconName = "pinmap";
@@ -357,28 +350,3 @@ export default class Map extends Component {
     }
   }
 }
-
-const mapStateToProps = (state, props) => {
-  return {
-    isAdmin: getUserIsAdmin(state, props),
-  };
-};
-
-const CustomMapFooter = connect(mapStateToProps)(function CustomMapFooter({
-  isAdmin,
-}) {
-  const content = (
-    <CustomMapContent>
-      {t`Custom map`}
-      <Icon name="share" />
-    </CustomMapContent>
-  );
-
-  return isAdmin ? (
-    <Link to="/admin/settings/maps">{content}</Link>
-  ) : (
-    <ExternalLink href="https://www.metabase.com/docs/latest/configuring-metabase/custom-maps">
-      {content}
-    </ExternalLink>
-  );
-});
diff --git a/frontend/src/metabase/visualizations/visualizations/Maps.styled.tsx b/frontend/src/metabase/visualizations/visualizations/Map/Maps.styled.tsx
similarity index 100%
rename from frontend/src/metabase/visualizations/visualizations/Maps.styled.tsx
rename to frontend/src/metabase/visualizations/visualizations/Map/Maps.styled.tsx
diff --git a/frontend/src/metabase/visualizations/visualizations/Map/index.ts b/frontend/src/metabase/visualizations/visualizations/Map/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f774b75d21c1aacc596c2ced392047b5920a2ce2
--- /dev/null
+++ b/frontend/src/metabase/visualizations/visualizations/Map/index.ts
@@ -0,0 +1 @@
+export { Map } from "./Map";
diff --git a/frontend/src/types/global.d.ts b/frontend/src/types/global.d.ts
index 94f716aac6e1f9d132f4fab25b6c8efab3828eb8..682c997e8f6a7181e61ddb87a785f387f4ff5d3f 100644
--- a/frontend/src/types/global.d.ts
+++ b/frontend/src/types/global.d.ts
@@ -10,3 +10,10 @@ declare module "*.svg" {
   // eslint-disable-next-line import/no-default-export -- deprecated usage
   export default content;
 }
+
+// This allows importing CSS from TypeScript files
+declare module "*.css" {
+  const content: any;
+  // eslint-disable-next-line import/no-default-export -- deprecated usage
+  export default content;
+}
diff --git a/resources/sample-database.db.mv.db b/resources/sample-database.db.mv.db
index f8bac250c3c4f22f3c2a35eac556c7e8105f0d50..1ac5a197074e605ff32a85554d209e76ac50780e 100644
Binary files a/resources/sample-database.db.mv.db and b/resources/sample-database.db.mv.db differ
diff --git a/src/metabase/public_settings.clj b/src/metabase/public_settings.clj
index 29c54bba3b6e5b21e609fcff651215890075c16d..437e806653125f9ed3cf0dfe38eae9b90eb0aa3b 100644
--- a/src/metabase/public_settings.clj
+++ b/src/metabase/public_settings.clj
@@ -471,7 +471,6 @@
     "Keyword setting to control whitelabeling of the help link. Valid values are `:metabase`, `:hidden`, and "
     "`:custom`. If `:custom` is set, the help link will use the URL specified in the `help-link-custom-destination`, "
     "or be hidden if it is not set."))
-  :default    :default
   :type       :keyword
   :audit      :getter
   :visibility :public
@@ -507,6 +506,14 @@
                  (validate-help-url new-value-string)
                  (setting/set-value-of-type! :string :help-link-custom-destination new-value-string))))
 
+(defsetting show-metabase-links
+  (deferred-tru (str "Whether or not to display Metabase links outside admin settings."))
+  :type       :boolean
+  :default    true
+  :visibility :public
+  :audit      :getter
+  :feature    :whitelabel)
+
 (defsetting enable-password-login
   (deferred-tru "Allow logging in by email and password.")
   :visibility :public
diff --git a/test/metabase/public_settings_test.clj b/test/metabase/public_settings_test.clj
index 963c48715be49f99743dd340546e75c0a458e77e..4e0ea383c14d4666e5cc13886f30d301eae8e88b 100644
--- a/test/metabase/public_settings_test.clj
+++ b/test/metabase/public_settings_test.clj
@@ -216,30 +216,31 @@
                  (public-settings/start-of-week))))))))
 
 (deftest help-link-setting-test
-  (mt/with-premium-features #{:whitelabel}
-    (testing "When whitelabeling is enabled, help-link setting can be set to any valid value"
-      (public-settings/help-link! :metabase)
-      (is (= :metabase (public-settings/help-link)))
+  (mt/discard-setting-changes [help-link]
+    (mt/with-premium-features #{:whitelabel}
+      (testing "When whitelabeling is enabled, help-link setting can be set to any valid value"
+        (public-settings/help-link! :metabase)
+        (is (= :metabase (public-settings/help-link)))
 
-      (public-settings/help-link! :hidden)
-      (is (= :hidden (public-settings/help-link)))
+        (public-settings/help-link! :hidden)
+        (is (= :hidden (public-settings/help-link)))
 
-      (public-settings/help-link! :custom)
-      (is (= :custom (public-settings/help-link))))
+        (public-settings/help-link! :custom)
+        (is (= :custom (public-settings/help-link))))
 
-    (testing "help-link cannot be set to an invalid value"
-      (is (thrown-with-msg?
-           Exception #"Invalid help link option"
-           (public-settings/help-link! :invalid)))))
+      (testing "help-link cannot be set to an invalid value"
+        (is (thrown-with-msg?
+             Exception #"Invalid help link option"
+             (public-settings/help-link! :invalid)))))
 
-  (mt/with-premium-features #{}
-    (testing "When whitelabeling is not enabled, help-link setting cannot be set, and always returns :metabase"
-      (is (thrown-with-msg?
-           clojure.lang.ExceptionInfo
-           #"Setting help-link is not enabled because feature :whitelabel is not available"
-           (public-settings/help-link! :hidden)))
+    (mt/with-premium-features #{}
+      (testing "When whitelabeling is not enabled, help-link setting cannot be set, and always returns :metabase"
+        (is (thrown-with-msg?
+             clojure.lang.ExceptionInfo
+             #"Setting help-link is not enabled because feature :whitelabel is not available"
+             (public-settings/help-link! :hidden)))
 
-      (is (= :metabase (public-settings/help-link))))))
+        (is (= :metabase (public-settings/help-link)))))))
 
 (deftest validate-help-url-test
   (testing "validate-help-url accepts valid URLs with HTTP or HTTPS protocols"
@@ -350,3 +351,22 @@
            Exception
            #"This field must be a relative URL."
            (public-settings/landing-page! "file:///path/to/resource")))))
+
+(deftest show-metabase-links-test
+  (mt/discard-setting-changes [show-metabase-links]
+    (mt/with-premium-features #{:whitelabel}
+      (testing "When whitelabeling is enabled, show-metabase-links setting can be set to boolean"
+        (public-settings/show-metabase-links! true)
+        (is (= true (public-settings/show-metabase-links)))
+
+        (public-settings/show-metabase-links! false)
+        (is (= false (public-settings/show-metabase-links)))))
+
+    (mt/with-premium-features #{}
+      (testing "When whitelabeling is not enabled, show-metabase-links setting cannot be set, and always returns true"
+        (is (thrown-with-msg?
+            clojure.lang.ExceptionInfo
+            #"Setting show-metabase-links is not enabled because feature :whitelabel is not available"
+            (public-settings/show-metabase-links! true)))
+
+        (is (= true (public-settings/show-metabase-links)))))))