Case Study

Embedded Analytics and Dashboard Reporting

Interactive dashboards with database access controls and scoped views inside another application.

The platform has two kinds of user. Analysts build datasets, charts and dashboards in a workspace that gives them visual controls and a SQL editor. Everyone else opens a chosen dashboard inside the client's own application, signed in with the account they already hold there.

This embedded analytics case study covers the link we built between those two views. Part of that work is how the host application hands a viewer's access scope to an embedded report.

The challenge

An embedded dashboard still runs queries against real data. The viewer's permissions have to reach that query, down to the rows the person is allowed to read. Hiding a chart or a menu does not solve the problem, because the data request is still there.

The same reporting code handles three kinds of work. It answers a request while someone waits. It runs longer queries in the background, and it sends scheduled reports on a timer. Each route finishes at its own time. All three still need the same query and the same permission rules.

What we built

Analysts define metrics and start from tables or saved queries, then combine charts with filters on a dashboard. The platform keeps these definitions in its own metadata database, while the chart values come from the connected databases through adapters.

For an embedded view, the host application's server asks for a short-lived guest token. That token names the resources the viewer may use and the row filters that apply to them. Scheduled reports follow a separate path. A headless browser captures the dashboard, and an execution log records each run.

Technical approach

Each chart request names the dataset it needs. From there it sets the columns, grouping and filters that shape the result. The backend checks the cache and builds the SQL. It applies the row filters, then runs the finished query through the database adapter. Longer queries can go through Celery on the same path, and result caching still has to be turned on in the deployment configuration.

Guest-token revocation relies on a version number kept in the metadata database. An issuance record holds the issuer, the resource scope and a hash of the token. It leaves out the raw token and the text of the row-filter clause, so the audit trail never stores them.

The platform checks SQL permissions twice. One check runs before the template expands. Expansion can change the statement that will actually run, so a second check runs afterwards as well. Tenant isolation still depends on the configured access policies and the deployment design.

Shared business commands sit behind the API routes and background tasks. A scheduled report therefore reuses that shared logic rather than keeping a copy of its own. Its state and execution log stay available for review.

Project success

The same reporting content works in the analytics workspace and inside the client's application. Each embedded view gets a signed token. That token carries the permitted resource and row scope into the view. Analysts keep their visual and SQL workflows. Operators can open the report records and issuance records to check how access or delivery behaved.

Technology stack

Backend

Python, Flask, Flask-AppBuilder

Data access

SQLAlchemy, SQLGlot, Pandas

Frontend

React, TypeScript, Redux, ECharts

Background processing

Celery, Redis

Report capture

Playwright

Embedded access

Signed guest tokens, row-level filters

Recognize the pattern?

If one of these looks like your situation, the discovery call is where we find out how close.