{"slug": "how-to-build-customer-facing-analytics-for-b2b-saas", "title": "How to Build Customer-Facing Analytics for B2B SaaS", "summary": "A developer compares approaches to building customer-facing analytics for B2B SaaS, arguing that embedding BI tools like Metabase or Looker leads to multi-tenancy and branding issues, while building custom charts from scratch incurs high maintenance costs. The post introduces @bonnard/mcp-charts as a solution for AI agent surfaces where customers query data via Claude or ChatGPT.", "body_md": "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.\n\nThe question isn't whether to ship customer-facing analytics. It's how.\n\nMost 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.\n\nBoth approaches burn engineering time on the wrong problem. You end up building analytics infrastructure instead of your product.\n\nAnd 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`\n\nfits, covered later in this post.\n\nEmbedding a BI tool sounds fast. Drop in an iframe, connect to your database, ship it. In practice, the friction shows up quickly.\n\nMost 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.\n\n[Metabase](https://bonnard.dev/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.\n\nLooker'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.\n\nEven 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.\n\nAn 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.\n\nWhite-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.\n\nEmbedded BI gives you dashboards. That's one surface. But your customers might also want:\n\nEach 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.\n\nThe alternative: skip the BI tool and build it yourself. Custom SQL queries, custom API endpoints, custom React charts.\n\nThis 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.\n\nThe real cost isn't the initial build. It's the ongoing maintenance:\n\nThe 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.\n\nThe 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.\n\n`@bonnard/mcp-charts`\n\nis 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`\n\ntool you add to your MCP server that renders interactive charts from your query results, inside the agent.\n\nInstall the package and call `addCharts`\n\nwith your existing MCP server and a `runSql`\n\nfunction:\n\n``` js\nimport { addCharts } from \"@bonnard/mcp-charts\";\n\naddCharts(server, {\n  runSql: async (sql) => {\n    // Run the query against your database and return typed rows.\n    return await db.query(sql);\n  },\n});\n```\n\n`addCharts`\n\nregisters a `visualize`\n\ntool (and a `visualize_read_me`\n\ncompanion) on your server. The flow:\n\n`visualize`\n\nwith a query.`runSql`\n\nreturns rows.`ui://`\n\nwidget 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.\n\nNative adapters cover Postgres, BigQuery, Snowflake, Databricks, and DuckDB. You can also pass your own `runSql`\n\n. Bonnard never touches your database. Your code runs the query and returns the rows.\n\nThe `visualize`\n\ntool 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`\n\n, so when a query fails the agent knows what to try next. For how this is designed, see [how Bonnard builds agent-friendly MCPs](https://bonnard.dev/blog/how-bonnard-builds-agent-friendly-mcps).\n\n| Build from scratch | Embed BI tool | Charts in AI agent (MCP) | |\n|---|---|---|---|\nSurface |\nIn your product UI | In your product UI | Inside Claude or ChatGPT |\nTime to first chart |\n2-4 months | 1-2 weeks | A few lines (`addCharts` ) |\nWhat renders the chart |\nYour frontend code | The BI tool | The agent host (`ui://` widget) |\nWhere the query runs |\nYour code | The BI tool | Your `runSql` , your database |\nChart types |\nWhatever you build | Tool's library | line, bar, area, pie, scatter, funnel, waterfall, table |\nMaintenance burden |\nHigh (you own everything) | Medium (tool updates, iframes) | Low (one tool registration) |\nAI agent support |\nBuild from scratch | None | Native (`visualize` tool) |\n\nThese 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.\n\nEmbedded 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.\n\n`@bonnard/mcp-charts`\n\nis the adjacent option, not a member of the embedded BI category:\n\n**1. The chart lives in the agent.** When a customer asks a question in Claude or ChatGPT, the `visualize`\n\ntool renders an interactive `ui://`\n\nwidget right in the conversation. An embedded dashboard can't do that.\n\n**2. Your database stays yours.** Bonnard never touches your database. Your `runSql`\n\nruns the query and returns the rows. Bonnard infers the chart from the typed result.\n\n**3. Designed for the agent.** Compact summaries, row caps with completeness flags, typed schema, and instructive errors with a `next_step`\n\n. The tool is built for an agent to call, not only for a human to read.\n\nThe tradeoff: embedded BI tools render charts in your product UI, which is where many customers expect them. `@bonnard/mcp-charts`\n\nonly 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`\n\nfor the agent.\n\nInstall the package and register the tool on your MCP server:\n\n```\nnpm install @bonnard/mcp-charts\njs\nimport { addCharts } from \"@bonnard/mcp-charts\";\n\naddCharts(server, {\n  runSql: async (sql) => db.query(sql),\n});\n```\n\nThat registers the `visualize`\n\ntool (and `visualize_read_me`\n\n). 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`\n\n.\n\nRepo: [github.com/bonnard-data/mcp-charts](https://github.com/bonnard-data/mcp-charts). For the full walkthrough: [MCP charts](https://bonnard.dev/blog/mcp-charts). For the design principles: [how Bonnard builds agent-friendly MCPs](https://bonnard.dev/blog/how-bonnard-builds-agent-friendly-mcps).\n\nCustomer-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).\n\n[Embedded analytics](https://bonnard.dev/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.\n\n[Metabase](https://bonnard.dev/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`\n\nis a different surface entirely: it renders interactive charts inside an AI agent (Claude or ChatGPT) via a `visualize`\n\ntool on your MCP server. They are not substitutes. Use Metabase for an in-product dashboard, and `@bonnard/mcp-charts`\n\nfor charts in the agent.\n\nWhite-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.\n\nIt is letting your customers ask questions about their data inside an AI agent (Claude or ChatGPT) and get a chart back. `@bonnard/mcp-charts`\n\ncovers this with a `visualize`\n\ntool you add to your MCP server. The agent calls `visualize`\n\n, your `runSql`\n\nreturns rows, and Bonnard renders an interactive chart in the conversation. This is the 2026 surface that embedded BI tools do not address.\n\nYes, if you expose an MCP server. Add `@bonnard/mcp-charts`\n\nwith `addCharts(server, { runSql })`\n\n, and the agent can call `visualize`\n\nto render interactive charts from your query results in Claude or ChatGPT. Your `runSql`\n\nruns the query against your database, so Bonnard never touches your data. See [MCP](https://bonnard.dev/glossary/mcp) for how the protocol works.\n\nNative adapters cover [Postgres](https://bonnard.dev/integrations/postgres), [BigQuery](https://bonnard.dev/integrations/bigquery), [Snowflake](https://bonnard.dev/integrations/snowflake), [Databricks](https://bonnard.dev/integrations/databricks), and [DuckDB](https://bonnard.dev/integrations/duckdb). You can also pass your own `runSql`\n\nfunction to query anything that returns rows. Bonnard never connects to your database directly.\n\nIt is open source. Install it with `npm install @bonnard/mcp-charts`\n\n. Repo: [github.com/bonnard-data/mcp-charts](https://github.com/bonnard-data/mcp-charts).", "url": "https://wpnews.pro/news/how-to-build-customer-facing-analytics-for-b2b-saas", "canonical_source": "https://dev.to/maxbonnard/how-to-build-customer-facing-analytics-for-b2b-saas-h91", "published_at": "2026-07-16 15:25:42+00:00", "updated_at": "2026-07-16 15:37:56.685590+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "artificial-intelligence"], "entities": ["Metabase", "Looker", "Power BI", "Tableau", "Claude", "ChatGPT", "@bonnard/mcp-charts", "Salesforce"], "alternates": {"html": "https://wpnews.pro/news/how-to-build-customer-facing-analytics-for-b2b-saas", "markdown": "https://wpnews.pro/news/how-to-build-customer-facing-analytics-for-b2b-saas.md", "text": "https://wpnews.pro/news/how-to-build-customer-facing-analytics-for-b2b-saas.txt", "jsonld": "https://wpnews.pro/news/how-to-build-customer-facing-analytics-for-b2b-saas.jsonld"}}