Embedding Grafana dashboards into web applications using iframes is surprisingly straightforward, but the real magic lies in how you can control user access and data visibility without needing separate authentication systems for your embedded dashboards.
Let’s see it in action. Imagine you have a live web application where you want to display a critical operational dashboard from Grafana.
<!DOCTYPE html>
<html>
<head>
<title>My Application with Grafana</title>
</head>
<body>
<h1>Application Dashboard</h1>
<p>Here's our critical operational view:</p>
<iframe src="http://your-grafana-host:3000/d-solo/your-dashboard-id/your-dashboard-name?orgId=1&from=1678886400000&to=1678890000000&theme=light" width="800" height="600" frameborder="0"></iframe>
<p>More application content here...</p>
</body>
</html>
In this example, the src attribute of the iframe is the key. It points directly to a specific dashboard within your Grafana instance. The d-solo part indicates that we’re requesting a "solo" panel or dashboard view, optimized for embedding. The your-dashboard-id and your-dashboard-name are placeholders you’ll replace with the actual ID and slug of your Grafana dashboard. The orgId parameter specifies the Grafana organization. Crucially, from and to are Unix timestamps in milliseconds, allowing you to set a specific time range for the embedded dashboard. theme=light (or dark) controls the visual appearance.
The problem this solves is providing context-sensitive, real-time data visualizations to users of your web application without forcing them to navigate to a separate Grafana interface. Instead of users logging into Grafana, finding the dashboard, and then trying to correlate that data with what they see in your app, you bring the dashboard directly to them. This enhances user experience and operational awareness by integrating data directly into the workflows where it’s most relevant.
Internally, Grafana’s embedding mechanism works by serving a lightweight, stripped-down version of the dashboard. When you use the d-solo URL, Grafana knows not to render the full navigation, sidebars, or settings panels. It focuses solely on the dashboard panels themselves. The parameters in the URL are how you dynamically control the view:
orgId: Essential if you have multiple Grafana organizations.from/to: These are your time-series levers. You can dynamically generate these timestamps in your web application’s backend to show data relevant to the current view or a specific event. For instance, if a user is looking at logs for a specific error event, you can pass the start and end time of that error event tofromandto.panelId: If you only want to embed a single panel from a dashboard, you can append&panelId=your-panel-idto thed-soloURL. This is incredibly useful for embedding specific metrics.refresh: You can control the refresh interval of the embedded dashboard using&refresh=5s(for 5 seconds),&refresh=1m(for 1 minute), etc.var-<variable_name>: If your dashboard uses variables, you can pre-set them via the URL. For example, to set a variable namedservicetoapi-gateway, you’d use&var-service=api-gateway.
The most powerful, yet often overlooked, aspect of Grafana embedding is the ability to leverage Grafana’s "Public Dashboards" feature or, more commonly for authenticated embeds, its API keys and signed URLs for fine-grained access control. If your Grafana instance requires authentication, directly embedding a dashboard will result in a login prompt within the iframe. To avoid this and ensure users only see what they’re supposed to, you can generate API keys in Grafana and use them to fetch dashboard data server-side, then render it in your web app, or use specific embedding permissions. A more advanced technique involves creating signed URLs that embed a dashboard for a limited time or with specific user permissions, managed by your application’s backend. This allows you to grant access to a dashboard without giving the user direct Grafana login credentials, effectively using your application as the gatekeeper.
The next frontier is managing complex, dynamic embedding scenarios where you need to update the embedded dashboard’s time range or variables based on user interactions within your parent web application, often requiring JavaScript communication between the iframe and its parent.