When embedding multiple dashboards, it’s inefficient to fetch new tokens for each load. Instead, you can:
This reduces server load and improves user experience.
Create a backend API that connects to your Bold BI server and retrieves available dashboards.
/*
backend/getDashboards.js
Requires: express, crypto, https, http, url
Install express: npm install express
*/
const express = require("express");
const bodyParser = require("body-parser");
const crypto = require("crypto");
const fetch = require("node-fetch");
const path = require("path");
const app = express();
app.use(bodyParser.json());
// Config
const serverUrl = "<Bold BI Server URL>";
const siteIdentifier = "<Site Identifier>";
const embedSecret = "<Embed Secret>";
const userEmail = "<User Email>";
// Generate a token to fetch the dashboard list
async function getServerToken() {
const url = `${serverUrl}/api/${siteIdentifier}/token`;
const params = new URLSearchParams();
params.append("grant_type", "embed_secret");
params.append("username", userEmail);
params.append("embed_secret", embedSecret);
const response = await fetch(url, {
method: "POST",
body: params,
headers: { "Content-Type": "application/x-www-form-urlencoded" }
});
if (!response.ok) {
throw new Error(`Server token request failed: ${response}`);
}
return await response.json();
}
// ----------------- Dashboard List -----------------
app.get("/getDashboardList", async (req, res) => {
try {
const token = await getServerToken();
const url = `${serverUrl}/api/${siteIdentifier}/v5.0/dashboards`;
const response = await fetch(url, {
headers: { Authorization: `${token.token_type} ${token.access_token}` }
});
if (!response.ok) throw new Error(`Dashboard request failed: ${response.status}`);
const data = await response.json();
res.json(data.Data);
} catch (err) {
console.error("Error fetching dashboards:", err.message);
res.status(500).send("Error fetching dashboards");
}
});
Your backend should generate a reusable embed token instead of creating one for every dashboard. This token remains valid until it expires, reducing server calls and improving performance.
Note: Your backend is responsible for signing the request with the Embed Secret and calling the Embed Authorize API. Bold BI validates this signature and issues the embed token. Refer to the official documentation for full details on the signing process and token generation.
Call your backend API to get the list of dashboards and display them in a sidebar.
async function Init() {
const response = await fetch("/getDashboardList");
const dashboards = await response.json();
renderSidebar(dashboards);
}
function renderSidebar(dashboards) {
const panel = document.getElementById("panel");
panel.innerHTML = "";
dashboards.forEach(d => {
const div = document.createElement("div");
div.textContent = d.Name;
div.className = "dashboard-item";
div.onclick = () => requestDashboardToken(d.Id);
panel.appendChild(div);
});
if (dashboards.length) {
requestDashboardToken(dashboards[0].Id);
}
}
When a dashboard is clicked, request an access token from your backend and render it using the Bold BI SDK.
async function requestDashboardToken(dashboardId) {
try {
const response = await fetch("/tokenGeneration", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ dashboardId })
});
if (!response.ok) throw new Error(`HTTP error ${response.status}`);
const { access_token } = await response.json();
if (access_token) {
renderDashboard(dashboardId, access_token);
} else {
alert("Access token not found");
}
} catch (error) {
console.error("Error fetching token:", error.message);
alert("Error fetching token: " + error.message);
}
}
function renderDashboard(dashboardId, access_token) {
const dashboard = BoldBI.create({
serverUrl: "<Bold BI Server URL>",
dashboardId: "<Dashboard Id>",
embedContainerId: "<Embed Container Id>",
embedToken: "<Embed token generated from backend server>"
});
dashboard.loadDashboard();
}