Article

How to Add an AI Analytics Assistant to a React SaaS App (2026)

Learn how to add an AI analytics assistant to a React SaaS app with server-side tenant identity, grounded SQL, chart generation, and two SDK paths in 2026.

QueryPanel Team
16 min read
AI analyticsAI assistantReactSaaSembedded analyticstenant isolationNL-to-SQLimplementation

To add an AI analytics assistant to a React SaaS app, treat it as a customer-facing product system, not a chat box connected to a model. The browser needs a useful interface, but the trusted work belongs behind it: resolve the customer on your server, carry tenant identity into every analytics request, ground business language in your schema, verify generated SQL, and return an answer customers can inspect and keep using.

Published July 20, 2026. Competitor approaches and product behavior were checked against current public material and the QueryPanel SDK source on that date.


Short answer: most SaaS teams should start with a complete, headful React experience instead of assembling a chat interface, chart renderer, dashboard editor, and persistence layer separately. QueryPanel's headful React SDK provides a Notion-like dashboard workspace with an AI assistant for tenant-level customization. Choose the headless Node SDK when the interface itself is your differentiator or when query execution and result handling must stay inside your backend.

Whichever path you choose, the same boundary applies: the browser may display analytics, but it must not decide which tenant the user belongs to. Resolve that identity from your authenticated server session and mint or use tenant-scoped credentials there.

Key takeaways

  • Choose the product experience before choosing the model. A complete workspace and a custom chat endpoint create different engineering work.
  • Tenant identity starts on the server. A tenantId from a React prop, URL, or local state is not an authorization boundary.
  • Grounding is more than sending table names to an LLM. Useful assistants need schema annotations, glossary terms, known-good SQL examples, and session context.
  • An answer is not finished when SQL runs. Customers need a clear rationale, a useful chart or table, stable follow-up context, and predictable empty and error states.
  • Test broad questions against two seeded tenants. "Show all revenue" is a better isolation test than a prompt that already names the customer.
  • Start headful for speed; go headless for control. Do not pay the custom-UI cost unless the product needs it.

Choose the product experience before choosing the AI model

The first architecture decision is not OpenAI versus Anthropic, or one SQL-generation technique versus another. It is what the customer should be able to do after receiving an answer.

Consider three requests:

  1. "Why did usage fall last week?"
  2. "Turn that into a chart and add it to my dashboard."
  3. "Save a version for the finance team with a different date range."

A chat endpoint can handle the first request. The next two require dashboard state, editing, permissions, and persistence. If those behaviors are on the roadmap, starting with a bare assistant API often creates a second project immediately after the first one ships.

Use this decision table before writing integration code:

Product requirementHeadful React SDKHeadless Node SDK
Complete dashboard workspaceIncludedYou build it
AI-assisted chart and dashboard customizationIncluded in the embedded experienceYou design the workflow
Native route inside a React applicationYesYes, with your own components
Full control over every UI stateModerateMaximum
Customer-specific saved dashboard forksBuilt into the embed flowYou own persistence and permissions
Query execution through your own backend callbackNot the default embed pathYes
Fastest route to a usable customer experienceBest fitMore engineering work

This is the practical difference between headful speed and headless control. It is a product choice, not a maturity ladder. Some teams stay headful. Others need a custom surface from day one.

Reference architecture for a tenant-safe AI analytics assistant

The safe request path begins before the analytics SDK receives a question.

There are six distinct responsibilities in this flow:

  1. Your application authenticates the user. QueryPanel does not replace your product login.
  2. Your backend resolves tenant identity. Use the same trusted account or workspace mapping that protects the rest of your application.
  3. The analytics request carries that tenant context. In the headful path, the Node SDK signs an RS256 JWT containing organizationId and tenantId. In the headless path, your backend passes tenantId to qp.ask(...).
  4. The query pipeline retrieves relevant schema and business context. The model should not infer your business vocabulary from column names alone.
  5. Generated SQL is validated and executed with the configured tenant rules. The browser never supplies the final security decision.
  6. The customer receives a product response. That may be a saved dashboard edit, a chart, a table, or a follow-up answer in the same session.

QueryPanel's API verifies the JWT signature server-side with RS256 and creates the authenticated organization and tenant context from verified claims. The React SDK talks to the QueryPanel API directly; it does not route customer analytics through the QueryPanel admin application.

Path A: ship the complete workspace with the headful React SDK

The headful path fits teams that want customers to view, edit, and save dashboards without building the entire analytics interface themselves.

First, initialize the Node SDK on your server. The workspace ID passed to the constructor becomes the JWT's organizationId. Keep the private key on the server.

import { QueryPanelSdkAPI } from "@querypanel/node-sdk";

export const qp = new QueryPanelSdkAPI(
  "https://api.querypanel.io",
  process.env.QUERYPANEL_PRIVATE_KEY!,
  process.env.QUERYPANEL_WORKSPACE_ID!,
);

Next, create an endpoint that uses your existing application session. requireCustomerSession is deliberately app-specific: it represents the authorization code your product already trusts.

// app/api/analytics/embed-token/route.ts
import { qp } from "@/lib/querypanel";

export async function GET(request: Request) {
  const customer = await requireCustomerSession(request);

  const jwt = await qp.createJwt({
    tenantId: customer.tenantId,
    userId: customer.userId,
  });

  return Response.json({ jwt });
}

Notice what is absent: no tenant query parameter, no tenant picker, and no private key in the browser. The server derives both IDs from the authenticated customer session.

The React route can now fetch that token and render the workspace:

"use client";

import { useEffect, useState } from "react";
import { QuerypanelEmbedded } from "@querypanel/react-sdk";

export function CustomerAnalyticsPage() {
  const [jwt, setJwt] = useState<string | null>(null);

  useEffect(() => {
    fetch("/api/analytics/embed-token")
      .then((response) => {
        if (!response.ok) throw new Error("Could not load analytics access");
        return response.json();
      })
      .then((data) => setJwt(data.jwt));
  }, []);

  if (!jwt) return <p>Loading analytics…</p>;

  return (
    <QuerypanelEmbedded
      dashboardId="customer-analytics-dashboard-id"
      apiBaseUrl="https://api.querypanel.io"
      jwt={jwt}
      allowCustomization
    />
  );
}

With allowCustomization, the current SDK can create a customer-specific dashboard fork and save edits without changing the original deployed dashboard. That matters when the assistant is expected to do more than answer one question: customers can keep useful work instead of starting from an empty chat on every visit.

Use the headful route when the job is "give customers an analytics workspace." If the job is narrower—such as adding one question box to an existing workflow—the headless route may fit better.

Path B: build a custom assistant with the headless Node SDK

The headless path keeps your backend between the browser and the analytics workflow. You build the input, streaming or loading behavior, chart layout, history, and error recovery.

After attaching a database and syncing its schema on the server, an application route can call qp.ask(...) with the tenant resolved from the session:

// app/api/analytics/ask/route.ts
import { qp } from "@/lib/querypanel";

export async function POST(request: Request) {
  const customer = await requireCustomerSession(request);
  const { question, querypanelSessionId } = await request.json();

  const result = await qp.ask(question, {
    tenantId: customer.tenantId,
    userId: customer.userId,
    database: "analytics",
    pipeline: "v2",
    chartType: "vizspec",
    querypanelSessionId,
    debug: false,
  });

  return Response.json({
    rows: result.rows,
    chart: result.chart,
    rationale: result.rationale,
    querypanelSessionId: result.querypanelSessionId,
  });
}

The returned querypanelSessionId lets a later question such as "now show only Europe" reuse the previous turn's context. debug: false keeps the rationale suitable for customers instead of exposing database paths and dialect details.

In this path, the SDK receives generated SQL and executes it through the database adapter or callback configured on your server. QueryPanel receives schema context for generation; credentials and result rows remain in your infrastructure. Chart generation receives field and value-type information rather than raw result values.

The tradeoff is ownership. Your team must define what happens when:

  • the question is ambiguous
  • the query returns no rows
  • SQL execution fails
  • a chart type is not suitable
  • a follow-up session expires or changes tenant
  • a customer wants to save the result

These are product states, not edge cases. The headful SDK already has opinions about many of them; headless gives you the freedom and the responsibility to make your own.

Ground answers with schema context, glossary terms, and gold queries

An LLM can read invoice_total and guess that it means revenue. Your finance team may define revenue as paid invoice subtotal minus refunds, excluding tax, using the settlement date. The column name cannot resolve that difference.

Useful grounding has at least four layers:

Context layerExampleWhat it prevents
SchemaTables, columns, types, relationshipsInvented fields and invalid joins
Annotations"ip_country is the customer country dimension"Business terms mapped to the wrong column
Glossary"Active workspace means activity within 28 days"Conflicting metric definitions
Gold queriesApproved SQL for revenue, churn, or feature adoptionRe-deriving important logic on every prompt

Start with one datasource, one tenant field, and five questions your customers already ask. Verify each answer before adding more schema surface. This is usually faster than indexing every table and discovering later that the assistant has too many plausible paths.

For a deeper production checklist covering repair loops, cost controls, Postgres, ClickHouse, and MCP, use NL-to-SQL in Production in 2026. For the complete React and Postgres setup, including schema sync and database attachment, follow the tenant-safe embedded analytics tutorial.

Test tenant boundaries, wrong answers, saved views, and follow-up questions

Do not approve the feature because it answers a curated demo prompt. Build a small test matrix that exercises the states customers will create accidentally.

TestInputPass condition
Broad tenant question"Show all revenue"Only the authenticated tenant's rows contribute
Tenant-switch attemptBrowser changes a tenant-like valueAccess does not change
Two seeded tenantsSame question from Tenant A and Tenant BEach gets its own visibly different result
Ambiguous metric"Show active customers"Assistant uses the approved definition or asks for clarification
Wrong column language"Break down by country"Knowledge maps the term to the intended field
Follow-up"Now show the previous quarter"Session context remains with the same tenant
Saved customizationAdd or edit a chart, then reloadThe customer fork persists without changing the original
Empty resultFilter to a period with no dataUI explains the empty state instead of rendering a broken chart
Execution failureForce an invalid or expensive query in stagingError is contained, logged, and does not expose credentials

Run the isolation tests with synthetic records that are impossible to confuse—for example, Tenant A has exactly 11 orders and Tenant B has exactly 29. A subtle leak is much easier to catch when the expected totals are deliberately different.

For customer-facing copy, return a business rationale rather than SQL mechanics. Keep engineer-level detail in admin or debug tools. Customers need to understand the answer; they do not need table names, tenant-filter narration, or engine-specific syntax.

How Cube, Embeddable, ThoughtSpot, Toucan, and Luzmo approach the problem

Competitor publishing in 2026 agrees on one point: the model is not the whole product. The disagreement is where the governing layer and customer experience should live.

PublisherCurrent AI angleUseful idea for SaaS teamsQueryPanel's distinct emphasis
CubeAdd AI analytics on top of a semantic layer, signed security context, governed metrics, and cachingTreat AI analytics as data architectureStart with a product-ready headful React workspace when teams do not already operate a warehouse semantic layer
EmbeddableProduction failures come from the data and output layers as well as the modelSeparate reliability, correctness, and trust failuresCombine trainable schema context with a choice between a complete workspace and headless execution
ThoughtSpotAgentic analytics moves from answering questions toward taking actionsEvaluate the workflow after the insight, not only the answerLet customers create and customize persistent dashboard views inside the SaaS product
ToucanAI embedded analytics adds natural-language exploration and proactive insight to customer-facing dashboardsMulti-tenant behavior and white-label UX belong in the evaluationMake the React/headful versus Node/headless tradeoff explicit before implementation
LuzmoAI data analysis is moving from specialist workflows to in-product, natural-language accessPut analysis where customers make decisionsGround questions against existing SaaS databases without making a warehouse migration the entry requirement

This is not a claim that one architecture wins every evaluation. Cube is a natural fit when a governed semantic layer and warehouse are already the center of the stack. ThoughtSpot fits enterprise programs that want a broad agentic analytics platform. Embeddable, Toucan, and Luzmo each offer product-facing paths with different UI and governance choices.

QueryPanel's primary product is its headful React SDK with a Notion-like dashboard management system and AI assistant for tenant customization. QueryPanel also offers a headless Node SDK for custom UI implementations with zero-trust architecture, where customer data never leaves customer servers.

For a buyer-oriented comparison of these paths, see Best Embedded AI Assistant APIs for SaaS Dashboards. For the category distinction, read Generative BI vs Generative Embedded Analytics.

Do not ship the assistant until these checks pass

An AI analytics assistant is ready for customers when the system around the answer is ready.

  • Tenant identity comes from an authenticated server session.
  • The browser never receives the signing private key.
  • Broad prompts remain tenant-scoped.
  • Important metrics have definitions or gold query examples.
  • Generated SQL is validated before execution.
  • Empty, ambiguous, and failed queries have deliberate UI states.
  • Follow-up sessions cannot cross tenant or user boundaries.
  • Saved charts and customer dashboard forks keep the same tenant scope.
  • Customer rationales avoid internal schema and SQL detail.
  • Admins can reproduce and investigate a disputed answer.

If several boxes are open, narrow the launch. Ship one dashboard and five approved questions to one internal test tenant. A smaller trustworthy surface is more useful than an assistant that confidently answers everything.

FAQ

What is an AI analytics assistant for SaaS?

An AI analytics assistant lets customers ask questions about their own product data in natural language and receive answers as charts, tables, or explanations inside the SaaS application. Unlike an internal BI copilot, it must work across tenant boundaries, customer permissions, product UX, and saved customer state.

How do I add AI analytics to a React application?

Choose a headful or headless integration first. A headful React SDK supplies the dashboard and assistant experience. A headless SDK lets your backend ask questions and return structured results to components you build. In both cases, resolve tenant identity on the server rather than accepting it from React state.

Is an AI analytics assistant the same as an AI chatbot?

No. A chatbot returns messages. An analytics assistant also needs governed data access, query generation, execution controls, charts or tables, follow-up context, and a way to handle ambiguity. If customers can customize dashboards, it also needs persistence and permissions around those changes.

Does customer-facing AI analytics require a data warehouse?

No. A warehouse can be the right foundation when governed metrics already live there, but it should not be a universal prerequisite. QueryPanel can work with existing databases such as Postgres and supports a headless path where execution remains on customer infrastructure.

How should tenant isolation work for an embedded AI assistant?

Your backend should derive the tenant from the authenticated application session. The tenant context must then travel into query generation and execution so a broad question cannot escape its customer scope. Do not use a browser-provided tenant filter as the security boundary.

When should I choose headful instead of headless analytics?

Choose headful when you want the fastest route to a complete dashboard workspace, AI assistant, editing, and customer customization. Choose headless when you need a fully custom interface or strict control over the execution and result path and are prepared to build the surrounding product states.

How do I test whether an AI analytics answer is trustworthy?

Test known questions against seeded tenants, compare results with approved SQL, inspect ambiguous metric behavior, and verify that follow-up questions retain the correct session and tenant. Include empty results, schema changes, failed execution, saved views, and customer disputes in the test plan.


Want to add a tenant-safe AI analytics assistant to your React product without building the dashboard workspace from scratch? Start with QueryPanel's headful React experience and use the headless Node SDK when your product needs a fully custom interface and zero-trust execution boundaries.