Introduction This article demonstrates how to create a fully custom HTML tooltip for Bar, Column, Line, and Area chart widgets in Sisense. By default, Sisense's native tooltip shows only the hovered data point's value and series name. This script goes further by embedding three advanced analytics utilities directly inside the tooltip: Pulling hidden data from the raw query result (e.g. a "Target" column that is not plotted on the chart). Calculating % of Series Total on the fly, so users can instantly see each bar's share of the whole. Calculating the difference from the previous bar (period-over-period growth), with conditional colour formatting. This is ideal for executive dashboards, sales performance charts, or any scenario where users need richer context without leaving the chart. The solution is tested on Sisense 2026.1.2 and works for both cloud and on-premise deployments. Step-by-Step Guide 1. Prepare your environment Open an existing dashboard that contains a Bar, Column, Line, or Area Widget, or create a new one. Make sure your data panel includes: At least one dimension (e.g. Month, Region) on the X-axis. At least one measure (e.g. Revenue, Sales) as the plotted value. Optionally, an unplotted column in your data panel (e.g. "Target") that you want to surface inside the tooltip. This column does not need to be visible on the chart – it just needs to be present in the data panel. 2. Open the widget script editor Click the three-dot menu on the widget → Edit Script . 3. Configure the script flags At the top of the script, two configuration flags control the tooltip behaviour: const HIDE_NATIVE_SISENSE_TOOLTIP = true;
const HIDE_ALL_TOOLTIPS = false; Set HIDE_NATIVE_SISENSE_TOOLTIP = true to completely replace Sisense's default tooltip with the custom one. Set it to false if you want both to coexist. Set HIDE_ALL_TOOLTIPS = true only if you want to suppress all tooltips entirely (custom and native) for some reason, and feel free to define a custom condition for this to be true. 4. Paste the full script: /**
* Script: Custom Tooltip for Bar & Column Charts
*
* Demonstrates 3 Utilities:
* 1. Pulling hidden data from the raw query (e.g., "Target" column)
* 2. Calculating % of Series Total on the fly
* 3. Calculating Difference from Previous Bar (Period-over-Period growth)
*/
// --- CONFIGURATION ---
// Set to TRUE to completely overwrite Sisense's native point events
// and hide the default Sisense tooltip, ensuring ONLY the custom tooltip below shows.
// Set to FALSE to keep Sisense's native events alongside the custom tooltip.
const HIDE_NATIVE_SISENSE_TOOLTIP = true;
// Set to true if you want to completely hide ALL tooltips (default or custom) when hovering.
const HIDE_ALL_TOOLTIPS = false;
widget.on('processresult', function (w, args) {
if (!args.rawResult || !args.rawResult.values) return;
// Optional: Completely disable tooltips if the flag is true
if (HIDE_ALL_TOOLTIPS) {
if (!args.result.tooltip) args.result.tooltip = {};
args.result.tooltip.enabled = false;
args.result.plotOptions = args.result.plotOptions || {};
args.result.plotOptions.series = args.result.plotOptions.series || {};
args.result.plotOptions.series.states = { hover: { enabled: false } };
return;
}
// UTILITY 1: GET HIDDEN DATA
// Get the column indices from the raw query results.
// Replace "Target" with an actual unplotted column name in your data panel.
const headers = args.rawResult.headers || [];
const targetColIndex = headers.indexOf("Target");
// Loop through each data point in the chart's series and attach the raw results metadata
let rowIndex = 0;
args.result.series.forEach(series => {
series.data = series.data.map(point => {
return (typeof point === "object" && point !== null) ? Object.assign({}, point) : { y: point };
});
series.data.forEach(point => {
const row = args.rawResult.values[rowIndex];
rowIndex++;
if (row) {
// Attach custom target value to the 'point' object
point.customTarget = targetColIndex !== -1 ? parseFloat(row[targetColIndex].data) : null;
}
});
});
// Step 3: Enable and configure styling for the basic tooltip wrapper
if (!args.result.tooltip) {
args.result.tooltip = {};
}
args.result.tooltip.enabled = true;
args.result.tooltip.useHTML = true;
args.result.tooltip.shared = false;
args.result.tooltip.backgroundColor = '#ffffff';
args.result.tooltip.borderColor = '#cccccc';
args.result.tooltip.borderRadius = 8;
args.result.tooltip.borderWidth = 1;
args.result.tooltip.style = {
color: '#333',
fontSize: '13px',
fontFamily: 'Arial, sans-serif'
};
// Step 4: Define the custom HTML layout returning function
args.result.tooltip.formatter = function () {
var category = this.x;
var value = this.y;
var color = this.color;
var seriesName = this.series.name;
// UTILITY 2: CALCULATE % OF TOTAL
// Find the total sum of this specific series
var seriesTotal = 0;
this.series.data.forEach(function(p) {
if (p.y) seriesTotal += p.y;
});
var percentOfTotal = seriesTotal > 0 ? ((value / seriesTotal) * 100).toFixed(1) + '%' : 'N/A';
// UTILITY 3: DIFFERENCE FROM PREVIOUS BAR (e.g. Month over Month)
var currentIndex = this.point.index;
var diffHtml = '<span style="color: #999;">N/A (First Data Point)</span>';
if (currentIndex > 0) {
var prevValue = this.series.data[currentIndex - 1].y;
var diffValue = value - prevValue;
var diffPercent = prevValue !== 0 ? ((diffValue / prevValue) * 100).toFixed(1) : 0;
// Conditional Formatting for the difference
var isPositive = diffValue >= 0;
var diffColor = isPositive ? '#28a745' : '#dc3545'; // Green for growth, Red for decline
var diffIcon = isPositive ? '▲' : '▼';
diffHtml = `<span style="color: ${diffColor}; font-weight: bold;">
${diffIcon} ${Math.abs(diffValue).toLocaleString()} (${diffPercent}%)
</span> <span style="color: #666; font-size: 11px;">vs Previous</span>`;
}
// Build HTML strictly.
var html = `<div style="padding: 12px; min-width: 200px;">`;
// Header
html += `<strong style="font-size: 14px; border-bottom: 2px solid ${color}; padding-bottom: 4px; display: inline-block; margin-bottom: 10px;">${category}</strong><br>`;
// Main Value
html += `<div style="margin-bottom: 8px;">`;
html += `<span style="color: #666;">${seriesName}: </span>`;
html += `<b style="font-size: 16px;">${value.toLocaleString()}</b>`;
html += `</div>`;
// Advanced Analytics Section
html += `<div style="background-color: #f8f9fa; border-radius: 4px; padding: 8px; font-size: 12px; border: 1px solid #eee;">`;
// Inject Utility 2 (% of Total)
html += `<div style="margin-bottom: 4px;"><span style="color: #666;">% of Series Total:</span> <b>${percentOfTotal}</b></div>`;
// Inject Utility 3 (Difference from previous)
html += `<div style="margin-bottom: 4px;">${diffHtml}</div>`;
// Inject Utility 1 (Hidden Target Column)
if (this.point.customTarget !== null && !isNaN(this.point.customTarget)) {
var targetDiff = value - this.point.customTarget;
var targetStatus = targetDiff >= 0 ? '<span style="color:#28a745;">Met Target</span>' : '<span style="color:#dc3545;">Missed Target</span>';
html += `<hr style="margin: 6px 0; border: none; border-top: 1px dashed #ccc;" />`;
html += `<div><span style="color: #666;">Target:</span> <b>${this.point.customTarget.toLocaleString()}</b> (${targetStatus})</div>`;
}
html += `</div></div>`; // End Analytics box & container
return html;
};
// Step 5: Optionally clear native Sisense tooltips based on the configuration flag
args.result.plotOptions = Object.assign({}, args.result.plotOptions || {});
if (HIDE_NATIVE_SISENSE_TOOLTIP) {
args.result.plotOptions.series = {
turboThreshold: 0,
marker: { enabled: true, states: { hover: { enabled: true, radiusPlus: 3, lineWidthPlus: 1 } } },
states: { hover: { enabled: true, halo: { size: 10, opacity: 0.3 } } }
};
} else {
args.result.plotOptions.series = Object.assign({}, args.result.plotOptions.series || {});
args.result.plotOptions.series.turboThreshold = 0;
}
}); 5. Adapt the script to your data There are two places you may need to customise: Hidden column name (Utility 1): Replace "Target" in the line below with the exact column title as it appears in your data panel: const targetColIndex = headers.indexOf("Target"); If you don't have a hidden target column, this utility is safely ignored – the tooltip will simply not render the Target section. Tooltip colours: The green (#28a745) and red (#dc3545) colours used for growth/decline indicators can be changed to match your brand palette. 6. Click Apply and test Save the script and hover over any bar or column in the chart. The custom tooltip will appear showing: The category label underlined with the series colour. The raw value in large text. A shaded analytics box containing: % of Series Total – the bar's share of the full series sum. vs Previous – the absolute and percentage change from the prior bar, with a green ▲ or red ▼ indicator. Target comparison (if a Target column is present) – the target value and a Met/Missed status label. Conclusion By hooking into the processresult event, this script transforms a standard Sisense charts into a self-contained analytics panel – surfacing hidden data, share-of-total context, and period-over-period trends all within a single hover interaction. The three utilities demonstrated here are modular: you can use any one of them independently, combine all three, or extend the pattern to add further metrics such as rolling averages or budget variance. This approach is particularly powerful for executive dashboards where users need instant context without drilling into separate views. References/Related Content Sisense JavaScript API Reference Highcharts Tooltip Formatter Documentation Disclaimer:This post outlines a potential custom workaround for a specific use case or provides instructions regarding a specific task. The solution may not work in all scenarios or Sisense versions, so we strongly recommend testing it in your environment before deployment. If you need further assistance with this, please let us know.