The AI Cost & Value Realization Tracker is a self-contained HTML dashboard that gives your MSP or consulting practice a single pane of glass for tracking AI tool spend, adoption rates, productivity gains, and estimated savings — all in one file with no server required.
You can be up and running in under five minutes. The file is entirely self-contained — no npm, no build step, no server.
Work through these items in order to get from sample data to production-ready reporting.
Four top-line cards give at-a-glance status. All values recalculate automatically when you edit table data or click Recalculate.
| Card | What It Shows | How It's Calculated |
|---|---|---|
| Monthly Spend AMBER | Sum of all monthly $ values across the active view | SUM(monthly) across all rows in activeData() |
| Active Users TEAL | Average adoption rate across all rows | AVG(active%) across all rows |
| Cost Per User BLUE | Monthly cost divided by active seats | totalMonthly / (totalSeats × avgActive%) |
| Annual Projection RED | Current burn extrapolated to 12 months | totalMonthly × 12, compared to ANNUAL_BUDGET |
+8% month-over-month for spend and +5% for users. Once you wire a backend with historical data, replace the kpi-spend-delta and kpi-users-delta DOM updates in recalcAll() with real prior-month comparisons.The wide card below the KPIs is your budget consumption view. It shows how far through the annual budget you are at the current monthly run rate, with forward projections.
| Field | Description |
|---|---|
| Monthly Burn Rate | Large number on the left — total monthly spend across all active rows. |
| Budget Consumed bar | Horizontal bar showing (monthly × 12) ÷ ANNUAL_BUDGET as a percentage. Animates on load. |
| Q1 Projection | Monthly × 3. Useful for quarterly business reviews. |
| Q2 Projection | Monthly × 6. Half-year run rate. |
| Annual Budget | The ANNUAL_BUDGET constant — update this in the script to match your org's actual number. |
| Remaining | ANNUAL_BUDGET minus (monthly × 12). Shows positive if under budget, negative if over. |
ANNUAL_BUDGET is set to $48,000. This is the first thing you should update before showing the dashboard to anyone. Find const ANNUAL_BUDGET = 48000; near the top of the <script> block.The main chart overlays two different metrics that normally wouldn't share an axis — cost in dollars and adoption as a percentage. Three datasets are plotted simultaneously.
getChartData() with your own trend model.getChartData(months). To use real data, fetch a time-series endpoint and populate the costData and userPct arrays directly, one entry per month in chronological order. The chart expects null for future months in the actuals datasets and null for past months in the projection dataset.The SVG gauge gives instant visual feedback on whether your AI investments are generating more value than they cost. The needle and arc both animate when data changes.
| Gauge Zone | ROI Range | Interpretation |
|---|---|---|
| Red Zone | -100% to 0% | Costs exceed estimated savings. Investigate adoption gaps or recalibrate savings estimates. |
| Amber Zone | 0% to ~75% | Breaking even or modest positive return. Typical in early adoption phases (months 1–3). |
| Green Zone | 75% to 200% | Strong return. AI tools delivering 1.75–3× their cost in productivity value. |
| Blue Zone | 200%+ | Exceptional ROI. Verify savings estimates are not overstated before presenting to leadership. |
Est Savings = (Avg Hours Saved/Week × 52 × Avg Hourly Rate) × Active Users. Use manager estimates for hours saved, and fully-loaded labor cost (salary + benefits) for hourly rate.The main data entry surface of the dashboard. All underlined fields are directly editable. Changes propagate to KPI cards, burn rate, gauge, and chart immediately.
| Column | Editable | Notes |
|---|---|---|
| Name | Yes | Client name, department, or tool name depending on active view. |
| Tool | No | Badge showing copilot / openai / other. Change by editing the tool field in the data array. |
| Seats | Yes | Total licensed seats for this row. Used to calculate Cost Per User KPI. |
| Monthly $ | Yes | Total monthly spend for this row. Core input for all cost calculations. |
| Active % | Display only | Rendered from the active field. Edit via the data array or backend. Color-coded: teal ≥70%, amber ≥50%, red below 50%. |
| Prod Gain % | Yes | Manually reported productivity improvement. Used for avg productivity gain in gauge stats. |
| Est Savings $ | Yes | Dollar value of productivity gains. Key input for ROI calculation. |
Qualitative observations that numbers can't capture. This panel is intentionally low-friction — type and press Enter. Notes persist for the session and appear newest-first.
Adoption Gap — clients or depts below 50% with a known reason.
Quick Win — a client or team that achieved ROI breakeven early.
Risk — compliance concerns, data governance questions, license issues.
Next Step — actions to increase adoption or expand to new teams.
All data is stored in three JavaScript arrays near the top of the script block. Each array drives one of the three table view modes.
// CLIENT VIEW — one object per managed client let tableData = [ { name: 'Apex Manufacturing', // Display name tool: 'copilot', // 'copilot' | 'openai' | 'other' seats: 25, // Total licensed seats monthly: 875, // Monthly spend in USD active: 72, // Active user % (0–100) prodGain: 18, // Reported productivity gain % savings: 2100, // Estimated monthly savings USD }, // ... more rows ];
tableData = Client view | deptData = Department view | toolData = Tool rollup view. All three use the same seven-field schema. The active view is determined by currentView and the activeData() function which returns the correct array.The dashboard is designed so that replacing static data with live API calls requires changes in exactly one place — the data arrays — with no other UI modifications needed.
async function init() { updatePeriod(); // Replace this block with your real endpoint const res = await fetch('https://your-api/ai-costs'); const json = await res.json(); // Map API response to the expected schema tableData = json.clients.map(c => ({ name: c.clientName, tool: c.primaryTool, // normalize to 'copilot'|'openai'|'other' seats: c.licensedSeats, monthly: c.monthlySpendUsd, active: c.adoptionPct, prodGain: c.productivityGainPct ?? 0, savings: c.estimatedSavingsUsd ?? 0, })); renderTable(); renderNotes(); buildChart(); recalcAll(); }
// Replace getChartData() with your real time-series async function loadChartHistory(months) { const res = await fetch(`/api/ai-costs/monthly?months=${months}`); const history = await res.json(); // [{month:'Jan 25', cost:3200, active:58}, ...] const labels = history.map(h => h.month); const costData = history.map(h => h.cost); const userPct = history.map(h => h.active); const projData = [...new Array(history.length).fill(null), costData.at(-1) * 1.04, costData.at(-1) * 1.08]; return { labels, costData, userPct, projData }; }
monthly, product quantity to seats, and pull adoption metrics from your RMM or M365 usage reports. The TrendStart Finder agent can feed the active field once adoption tracking is in place.All calculations performed in recalcAll(). These are equivalent to Power BI DAX measures if you replicate this logic there.
ROI % = DIVIDE( [Total Est Savings] - [Total Monthly Cost], [Total Monthly Cost] ) * 100. The CSV export provides a clean fact table to import as a Power BI data source.The Export CSV button downloads the currently active view (Client, Dept, or Tool) as a flat CSV file. Columns match the seven fields in the data schema.
Name,Tool,Seats,Monthly $,Active %,Prod Gain %,Est Savings $ Apex Manufacturing,copilot,25,875,72,18,2100 Ridgeline Legal,copilot,12,420,58,12,840 ...
onchange fetch to the editable inputs in buildRow().
.tool-badge.yourtool rule with the desired border and text color. In buildRow(), the badge class is set directly from the tool field, so any value you put there will render as a badge — just add the matching CSS class.
getChartData(), find the line: projData.push(Math.round(baseMonthly * (1 + j * 0.04)));. The 0.04 is 4% per month. Change it to your expected monthly growth rate. For example, 0.02 = 2% per month growth.
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | Yes | Display label for the row. Any string. Shown in table Name column and exported to CSV. |
| tool | string | Yes | Must be one of: copilot, openai, other. Controls badge color. Add CSS for additional values. |
| seats | integer | Yes | Total licensed seats regardless of usage. Used to calculate Cost Per User KPI. |
| monthly | integer | Yes | Monthly spend in USD. Core value driving all cost calculations. Do not use annual figures here. |
| active | integer 0–100 | Yes | Percentage of licensed seats that are actively using the tool. Pull from M365 admin, RMM telemetry, or manual survey. |
| prodGain | integer 0–100 | Recommended | Reported productivity improvement percentage. Used for avg productivity gain display. Safe to default to 0 until you have data. |
| savings | integer | Recommended | Estimated monthly dollar savings from productivity gains. Used directly in ROI calculation. Default to 0 if unknown — ROI gauge will show cost-only state. |
savings: 0 on all rows. The dashboard will show ROI at -100% (cost only, no savings), which is an honest starting point. Add savings estimates row by row as you collect data from clients and managers. The gauge will move as you fill in the numbers.