Skip to main content

Embed Dashboards

Embedding dashboards

Introduction

Rill Cloud provides the ability to embed dashboards as components in your own application using iframes, with a few different options:

  • Embedding individual dashboards as standalone iframes
  • Embedding individual dashboards with the ability to navigate to other dashboards (that exist in the same project)
  • Embedding the dashboard list page present in a Rill project (with the ability to select and navigate between dashboards)

When embedding Rill, a service token for the backend will need to be generated to request an authenticated iframe URL via the Rill APIs. Afterwards, the iframe URL can be passed to your frontend application for rendering. Here's a high-level diagram of what this flow looks like:

Create a service token

Use the Rill CLI to create a service token for your current organization using the following command:

rill service create <service_name>
info

See our CLI reference docs for more details on managing a service account and token.

caution

The service account provides admin-level access to your organization and should be handled confidentially. Therefore, the service account itself should not be integrated directly in a fronted or other user-facing code that can be exposed publicly.

Backend: Build an iframe URL

You should implement an API on your backend that uses the service token to retrieve and return an iframe URL from Rill's API (which is hosted on admin.rilldata.com).

There are multiple reasons why the iframe URL must be constructed on your backend:

  • To avoid leaking your master Rill service token in the browser
  • To allow you to use your own authentication and authorization logic to restrict access to the dashboard
  • To allow you to optionally use your backend's context about the authenticated user to include user attributes in the iframe URL for enforcement of row-level security policies

Here are examples of how to get an iframe URL using different languages:

curl -X POST --location 'https://admin.rilldata.com/v1/organizations/<org-name>/projects/<project-name>/iframe' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <rill-svc-token>' \
--data-raw '{
"resource": "<dashboard-name>",
"user_email":"<user-email>"
}'

The API accepts the following parameters:

ParameterDescriptionRequired
resourceThe name of the dashboard to embedNo (if not specified, navigation should be set to true)
navigationBoolean whether to enable navigation and allow users to navigate to other dashboards (false will hard embed and allow access to a single dashboard; true allows navigation)No (defaults to false)
themeIf themes are being used, the specific theme to pass to the embedded dashboardNo (set to the name of the theme)
user_idThe id of the user to embed the dashboard forNo (only one of user_id, user_email, or attributes should be passed in)
user_emailThe email of the user to embed the dashboard forNo (only one of user_id, user_email, or attributes should be passed in)
attributesJson payload to be put in the access token, used to pass attributes to the dashboard for enforcing policies. When using this make sure to pass all the attributes used in your security policy like email, domain and admin and any other custom attributes such as tenantId, customerId, etc.No (It is also possible to add custom attributes here)
ttl_secondsThe time to live for the iframe URLNo (Default: 86400)
Embedding the project vs embedding an individual dashboard

One of the most common differences between how developers may wish to iframe Rill is whether they wish to embed at the project level or individual dashboard level. This behavior can be controlled through the combination of the resource and navigation properties!

If you wish to embed a single dashboard only, your payload might look like:

{
// simply provide a resource
resource: 'dashboardName'
}

If you wish to still embed a dashboard but allow navigation between dashboards, then your payload should include both parameters:

{
// enable navigation and provide a resource
resource: 'dashboardName',
navigation: true
}

Finally, if you wish to embed the project list view of dashboards instead (what you see when you first open a project in Rill Cloud), then you can simply omit the resource and appropriately set navigation in your payload:

{
// enable navigation and do NOT provide a resource
navigation: true
}

The response of the above POST request will then contain an iframeSrc value that can be used to embed the dashboard / set of dashboards in your application. It will also contain a ttlSeconds value, which indicates how long the iframe URL will be valid for. After the TTL has elapsed, the iframe URL needs be refreshed as the underlying access token being used will no longer be valid (for security purposes). Here's an example response:

{
"iframeSrc": "https://ui.rilldata.com/-/embed?access_token=<token>&instance_id=<id>&kind=MetricsView&resource=<dashboard-name>&runtime_host=<runtime_host>&state=&theme=",
"runtimeHost": "<runtime_host>",
"instanceId": "<id>",
"accessToken": "<token>",
"ttlSeconds": 86400
}

Frontend: Embed the dashboard

Your frontend should request an iframe URL from your backend API (which you set up in the previous step) and use the iframeSrc value of the response to render an HTML <iframe> element:

<iframe title="rill-dashboard" src="<iframeSrc>" width="100%" height="100%" />

Appendix

React Example

Depending on how your app is written and the language being used, you can then use the resulting iframe URL to embed and display Rill dashboards accordingly. Please find below a basic example of how to fetch and render a dashboard in React:

import React, { useEffect, useState } from 'react';

export default function RillDashboard() {
const [isLoading, setLoading] = useState(true);
const [iframeSrc, setIframeSrc] = useState('');
const [error, setError] = useState('');

useEffect(() => {
fetch(`<YOUR BACKEND HOST>/api/rill/iframe`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => response.json())
.then(({ iframeSrc, error }) => {
if (error !== undefined) {
setError(error);
} else {
setIframeSrc(iframeSrc);
}
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}, []);

if (isLoading) return <p>Loading...</p>;
if (error) return <p>Failed with error: {error}</p>;

return (
<iframe title="rill-dashboard"
src={iframeSrc}
width="100%"
height="1000"
/>
);
};

Next.js Example

You can find a different end-to-end example of embedding a Rill dashboard in a Next.js project in this sample Github repo.