Business Intelligence
How to Embed Dashboards in Your SaaS Product
How to put dashboards and an AI analyst inside your SaaS product so each customer sees only their own data, with the API request, tenant scope and chart rendering.
Javier BonillaCo-founder & CTO
To embed dashboards in a SaaS product, first decide whether every viewer may see the same numbers. If they may, an iFrame of a published dashboard is enough. If each customer must see only their own data, call an API from your server with the signed-in customer's id on every request, and draw the answer in your own front end.
Embedding is a tenancy problem before it's a charting problem. Any library can draw a bar chart. The work is making sure every answer comes from the asking customer's rows and nobody else's. With Querio's Embedded API it takes five steps:
- Connect the data and write down what it means.
- Create an API token and keep it on your server.
- Send each question with the customer's id as its scope.
- Draw the returned table and chart in your own components.
- Test it, then watch production traffic.
Should you embed with an iFrame or an API?
The choice comes down to who will see the numbers.
Querio's share iFrame puts a public board on your page: open Share > Embedded, copy the iframe and paste it in. Anyone who can load that page sees the board, and its public link works on its own too. The generated iframe is 100% wide and 600 pixels tall, and Make private takes down both the iframe and the public link at once. That's fine for numbers everyone may see, like a status page or a public benchmark. For customer data it's the wrong tool.
Once the numbers differ by customer, the customer has to travel with every request. In Querio that's the Embedded API. Your server asks the question on the customer's behalf, Querio answers from that customer's rows, and your product draws the result. The API also lets customers ask the next question, which a fixed dashboard can't.
"Being able to ask about your own shipments and get an answer immediately is a completely different experience from waiting on a CSM. Our brands love it."
Emma, Product Manager at Passport, on Querio Embedded
For a wider look at the trade-offs, including MCP, see iFrame vs API vs MCP.

Step 1: How do you get the data and its meaning ready?
Connect the datasource your product already runs on, then write context for it: what each table holds, what the columns mean, how tables join, and the business rules, like which orders count as shipped. You write it in the Context tab of Querio's Control Center.
Skip this and the AI agent guesses joins, and two customers can get two different answers to the same question. In Querio that context is files in a GitHub repo your team owns, so a change to a definition goes through a pull request next to your code. Every customer gets the same definition of "active account", and you can see who changed it and when.
Done looks like: the Context tab in the Control Center lists your tables, columns, joins and business rules.
Step 2: Where should the API token live?
Create a token in Querio under Embedded > API Tokens. Store it with your other server secrets. The Embedded API takes it as a bearer token in the Authorization header, with no client ID or secret.
Keep it out of front-end code: anything in your JavaScript bundle is public. If a token leaks, rotate it.
Done looks like: your server can call the API, and searching your built front end for the token finds nothing.
Step 3: How do you scope a question to one customer?
Your customers don't need a Querio login. They sign in to your product the way they already do, SSO or not, and your server starts a conversation for them with scope.customer_id set from your own session. The API uses scope variables like customer_id for row-level security. Here's the request from the Embedded API reference (API v2):
curl -X POST https://app.querio.ai/api/v2/embed/{customer_slug}/conversations \
-H "Authorization: Bearer <your_token>" \
-H "Content-Type: application/json" \
-d '{
"prompt": "How many shipments happened in the last 30 days",
"datasourceSlug": "your_datasource_slug",
"model": "claude-sonnet-5-5",
"scope": {
"customer_id": "your_customer_id"
},
"environment": "production",
"tags": {
"user_id": "your_user_id"
}
}'
Two ids look alike here, and they aren't. customer_slug in the URL is yours: it maps to your Querio workspace and agent configuration. customer_id in the scope is your customer, the tenant whose rows the answer may use. When that customer follows up with "Which carrier was slowest?", your server sends it as a new turn in the same conversation, which keeps the same scope, and they keep asking without starting over.
Never take customer_id from the browser, where a curious user can change it. Read it from the session on your server.
The model field picks the AI model that answers. It defaults to claude-sonnet-5-5, and the reference lists other Claude, GPT and Gemini models you can set per request. That lets you keep a faster model for quick lookups and a stronger one for a customer's harder question, without changing anything else in the call.
tags are yours to fill. Put your own user id in them, as the example does, and you can list a customer's past conversations later, filtered by those tags, so a user can pick up an earlier answer instead of asking again.
Done looks like: the same question, asked for two test customers, returns two different numbers, each matching that customer's data.
Step 4: How do the answers show up in your product?
An answer comes back in parts. A text part is plain text you show as is. A data-table part points to a table you fetch page by page: 20 rows by default and up to 10,000 per page, with search, sort and filters. A data-chart part points to a chart as a Vega-Lite spec.
Vega-Lite is an open JSON format for charts. You draw the spec with its vega-embed library and pass your own config with your fonts and colors.

Done looks like: a table and a chart from one answer sit in your app and use your type and colors.
Step 5: How do you test before customers see it?
The Control Center has a testing area. A test run shows the request Querio will receive and the shape of the response, so you build your front end against the real response shape. Send test traffic with "environment" set to something other than "production" and filter on it later.
After launch, production requests in the Control Center show what customers are asking. You can also see usage by user and the prompts behind each conversation. Use them to find questions the context doesn't cover yet, then add that context in Step 1's repo.
Done looks like: your test runs return the parts your components expect, and your first production questions show up with the right tags.
Can embedded dashboards match your product's branding?
Yes. With the Embedded API we send data and a chart spec, not a finished picture, so tables sit in your own components and charts use your fonts and colors, like the two products in the figure above. The Embedded add-on also includes white label.
What does Querio's embedded analytics cost?
Embedded is an add-on to any Querio plan, from $1,500 a month, with 7,500 AI credits a month. A credit is one call to an AI model, and a quick question takes a handful. So don't fire a prompt on every page load just to draw the same chart. Keep fixed views cached, and spend credits on the questions customers actually ask.
Where to go next
If you're planning a first release, How to Add AI Analytics to Your SaaS Product in a Week lays out a one-week pilot. For how tenants stay apart at the data layer, read row-level security for multi-tenant SaaS analytics.