# How to Build Customer-Facing Analytics for B2B SaaS

> A guide to customer-facing analytics 2026 for B2B SaaS: the options, the tradeoffs, and the MCP-native way to put interactive charts inside an AI agent.

Your B2B customers want to see their data. Usage metrics, billing summaries, conversion funnels, performance dashboards. Every customer expects analytics inside your product. They shouldn't have to ask your support team for a CSV export.

The question isn't whether to ship customer-facing analytics. It's how.

Most teams start with one of two approaches. They embed a BI tool (Metabase, Looker, Power BI) and fight with multi-tenancy, iframe styling, and paid embedding licenses. Or they build custom charts from scratch and spend months maintaining SQL queries, API endpoints, and frontend components that nobody asked for.

Both approaches burn engineering time on the wrong problem. You end up building analytics infrastructure instead of your product.

And there's a surface most of these tools miss entirely: the AI agent. Customers increasingly want to ask questions about their data inside Claude or ChatGPT and get a chart back. That's a different problem from embedding a dashboard, and it's where `@bonnard/mcp-charts` fits, covered later in this post.

## Why embedded BI tools fall short

Embedding a BI tool sounds fast. Drop in an iframe, connect to your database, ship it. In practice, the friction shows up quickly.

### Multi-tenancy is an afterthought

Most BI tools were built for internal teams, not B2B products serving hundreds of tenants. Multi-tenancy is either missing, manual, or gated behind an enterprise license.

[Metabase](/vs-metabase) requires the Enterprise license ($500+/month) for row-level permissions and sandboxed embedding. The open-source version has basic embedding but no tenant isolation. You end up writing middleware to filter queries by tenant, which is exactly the custom infrastructure you were trying to avoid.

Looker's embedded analytics requires an enterprise contract. Power BI Embedded uses capacity-based pricing that gets expensive at scale. Tableau's embedding story is Salesforce-priced.

Even when multi-tenancy is available, it's usually dashboard-level or role-based, not per-query structural enforcement. You're trusting the BI tool to filter correctly on every query. One misconfiguration and Customer A sees Customer B's data.

### Styling and UX limitations

An iframe is a foreign element in your product. It looks like a foreign element. Matching your brand's fonts, colors, spacing, and interaction patterns inside an embedded BI tool ranges from difficult to impossible. Your customers notice.

White-label analytics means your customers shouldn't know they're using a third-party tool. Most embedded BI solutions make this hard. The ones that make it easy charge for it.

### You're locked to dashboards

Embedded BI gives you dashboards. That's one surface. But your customers might also want:

- An API to pull metrics into their own tools
- AI agents that answer questions about their data
- Scheduled email reports
- Webhook alerts when metrics cross thresholds
- CSV/Excel exports for their finance team

Each of these requires a different integration, often with different tools and different metric definitions. The dashboard shows one number. The API returns a different one. The export uses yet another query. The metrics drift.

## Why building from scratch is worse

The alternative: skip the BI tool and build it yourself. Custom SQL queries, custom API endpoints, custom React charts.

This works for the first dashboard. Then the second. By the tenth, you're maintaining a bespoke analytics platform. Every new metric means a new SQL query, a new API endpoint, a new frontend component, and a new set of tests. Your data engineers are writing API handlers instead of defining metrics. Your frontend engineers are debugging chart edge cases instead of building product features.

The real cost isn't the initial build. It's the ongoing maintenance:

- **Metric drift.** Revenue is calculated differently in the dashboard, the API, and the export. Nobody notices until a customer complains.
- **No caching layer.** Every API call hits the warehouse. Response times grow with data volume. Your customers experience slow dashboards at month-end when they need them most.
- **Security is DIY.** You build tenant filtering yourself. You test it yourself. You hope you didn't miss an edge case.
- **No schema evolution.** Adding a new dimension means updating every query, endpoint, and component that touches the affected metric. A one-line change in business logic cascades into a multi-day project.

The teams on Reddit asking ["Is embedded analytics for SaaS actually worth it vs building your own charts?"](https://www.reddit.com/r/analytics/comments/1pxjm1z/) are wrestling with exactly this tradeoff. There's no single right answer. The decision depends on how many surfaces you serve and whether your customers want charts in a dashboard, an API, or an AI agent.

## The AI agent surface: charts inside Claude and ChatGPT

The sections above cover the two classic customer-facing analytics options: embed a BI tool or build dashboards from scratch. There's a third surface that neither covers well: the AI agent. When your customer asks a question in Claude or ChatGPT and wants a chart back, an embedded dashboard doesn't help.

`@bonnard/mcp-charts` is the MCP-native option for that surface. It is not an embedded BI tool, a dashboard product, or a multi-tenant analytics platform. It is a `visualize` tool you add to your MCP server that renders interactive charts from your query results, inside the agent.

### How it works

Install the package and call `addCharts` with your existing MCP server and a `runSql` function:

```typescript
import { addCharts } from "@bonnard/mcp-charts";

addCharts(server, {
  runSql: async (sql) => {
    // Run the query against your database and return typed rows.
    return await db.query(sql);
  },
});
```

`addCharts` registers a `visualize` tool (and a `visualize_read_me` companion) on your server. The flow:

1. The agent calls `visualize` with a query.
2. Your `runSql` returns rows.
3. Bonnard infers the chart from the typed result.
4. It renders an interactive `ui://` widget in Claude or ChatGPT.

Chart types: line, bar, area, pie, scatter, funnel, waterfall, and table. Bar charts have stacked, grouped, horizontal, and 100% variants, and a donut is a pie variant. Axes, formatting, and gap-fill are determined automatically, so the same query produces the same chart.

Native adapters cover Postgres, BigQuery, Snowflake, Databricks, and DuckDB. You can also pass your own `runSql`. Bonnard never touches your database. Your code runs the query and returns the rows.

### Built for the agent, not only the human

The `visualize` tool returns compact summaries, row caps with completeness flags, and a typed schema so the agent can reason about the result. Errors are instructive and include a `next_step`, so when a query fails the agent knows what to try next. For how this is designed, see [how Bonnard builds agent-friendly MCPs](/blog/how-bonnard-builds-agent-friendly-mcps).

## Build vs. embed vs. charts in the agent

| | Build from scratch | Embed BI tool | Charts in AI agent (MCP) |
|---|---|---|---|
| **Surface** | In your product UI | In your product UI | Inside Claude or ChatGPT |
| **Time to first chart** | 2-4 months | 1-2 weeks | A few lines (`addCharts`) |
| **What renders the chart** | Your frontend code | The BI tool | The agent host (`ui://` widget) |
| **Where the query runs** | Your code | The BI tool | Your `runSql`, your database |
| **Chart types** | Whatever you build | Tool's library | line, bar, area, pie, scatter, funnel, waterfall, table |
| **Maintenance burden** | High (you own everything) | Medium (tool updates, iframes) | Low (one tool registration) |
| **AI agent support** | Build from scratch | None | Native (`visualize` tool) |

These are not competing for the same slot. Embedded BI and a from-scratch build put charts in your product UI. Charts in the agent put them inside Claude or ChatGPT. Many teams will do both.

## What makes the AI agent surface different

Embedded analytics tools (Metabase Embedded, Holistics, Explo, Luzmo, Reveal) give you dashboards inside your product. That's their scope. They're good at it. None of them render a chart inside an AI agent.

`@bonnard/mcp-charts` is the adjacent option, not a member of the embedded BI category:

**1. The chart lives in the agent.** When a customer asks a question in Claude or ChatGPT, the `visualize` tool renders an interactive `ui://` widget right in the conversation. An embedded dashboard can't do that.

**2. Your database stays yours.** Bonnard never touches your database. Your `runSql` runs the query and returns the rows. Bonnard infers the chart from the typed result.

**3. Designed for the agent.** Compact summaries, row caps with completeness flags, typed schema, and instructive errors with a `next_step`. The tool is built for an agent to call, not only for a human to read.

The tradeoff: embedded BI tools render charts in your product UI, which is where many customers expect them. `@bonnard/mcp-charts` only covers the agent surface. If your customers want both a dashboard and an in-agent chart, use an embedded BI tool for the dashboard and `@bonnard/mcp-charts` for the agent.

## Getting started

Install the package and register the tool on your MCP server:

```bash
npm install @bonnard/mcp-charts
```

```typescript
import { addCharts } from "@bonnard/mcp-charts";

addCharts(server, {
  runSql: async (sql) => db.query(sql),
});
```

That registers the `visualize` tool (and `visualize_read_me`). Connect your server in Claude or ChatGPT, and the agent can render charts from your query results. Native adapters cover Postgres, BigQuery, Snowflake, Databricks, and DuckDB, or pass your own `runSql`.

Repo: [github.com/bonnard-data/mcp-charts](https://github.com/bonnard-data/mcp-charts). For the full walkthrough: [MCP charts](/blog/mcp-charts). For the design principles: [how Bonnard builds agent-friendly MCPs](/blog/how-bonnard-builds-agent-friendly-mcps).

## Frequently asked questions

### What is customer-facing analytics?

Customer-facing analytics is analytics embedded in your product for your customers to use. Instead of internal dashboards for your team, the analytics are exposed to end users: your B2B customers, their teams, and their tools. The key challenges are multi-tenancy (each customer sees only their data), performance (customers expect fast load times), and consistency (the numbers should match across every surface).

### What is embedded analytics?

[Embedded analytics](/glossary/embedded-analytics) means integrating analytics capabilities directly into another application. This can be as simple as an iframe embedding a dashboard or as sophisticated as native React components querying a governed API. The term covers a range of approaches from basic chart embedding to full white-label analytics platforms.

### How is this different from Metabase embedding?

[Metabase](/vs-metabase) offers embedded dashboards via iframe or full-app embedding. The open-source version has basic embedding but no tenant isolation. The Enterprise version ($500+/month) adds row-level permissions and sandboxed embedding. Metabase renders charts in your product UI. `@bonnard/mcp-charts` is a different surface entirely: it renders interactive charts inside an AI agent (Claude or ChatGPT) via a `visualize` tool on your MCP server. They are not substitutes. Use Metabase for an in-product dashboard, and `@bonnard/mcp-charts` for charts in the agent.

### What is white-label analytics?

White-label analytics means your customers see your brand, not a third-party tool's brand. No "Powered by Metabase" footer. No foreign-looking iframe. The analytics feel native to your product. Most embedded BI tools charge for white-labeling, and the harder it is to match your design, the more obvious the third-party tool becomes. This is a property of in-product embedding, not of charts rendered inside an AI agent.

### What is customer-facing analytics for AI agents?

It is letting your customers ask questions about their data inside an AI agent (Claude or ChatGPT) and get a chart back. `@bonnard/mcp-charts` covers this with a `visualize` tool you add to your MCP server. The agent calls `visualize`, your `runSql` returns rows, and Bonnard renders an interactive chart in the conversation. This is the 2026 surface that embedded BI tools do not address.

### Can my customers get charts inside an AI agent?

Yes, if you expose an MCP server. Add `@bonnard/mcp-charts` with `addCharts(server, { runSql })`, and the agent can call `visualize` to render interactive charts from your query results in Claude or ChatGPT. Your `runSql` runs the query against your database, so Bonnard never touches your data. See [MCP](/glossary/mcp) for how the protocol works.

### What databases does @bonnard/mcp-charts work with?

Native adapters cover [Postgres](/integrations/postgres), [BigQuery](/integrations/bigquery), [Snowflake](/integrations/snowflake), [Databricks](/integrations/databricks), and [DuckDB](/integrations/duckdb). You can also pass your own `runSql` function to query anything that returns rows. Bonnard never connects to your database directly.

### How much does @bonnard/mcp-charts cost?

It is open source. Install it with `npm install @bonnard/mcp-charts`. Repo: [github.com/bonnard-data/mcp-charts](https://github.com/bonnard-data/mcp-charts).