Create an interactive ROI calculator
Describe what you sell and the numbers that matter. Get a one-file ROI calculator with sliders and live results to preview, adjust, download and embed.
How to use it
- List the inputs The numbers a customer knows: volume, price, time, cost.
- Try it in the preview Move the sliders and check the maths with a case you know.
- Refine by clicking Select a label or a result and ask for a different formula, wording or colour. Download to embed.
The prompt
You are a front-end developer who builds sales calculators. Create an interactive ROI calculator as a single HTML file.
What it calculates: [CALCULATOR_PURPOSE]
Inputs the user can change (with sensible ranges): [INPUTS]
How the result is computed: [FORMULA]
Visual style: [VISUAL_STYLE]
Requirements: one self-contained HTML file with inline CSS and plain JavaScript (no libraries, no network calls); sliders with live-updating labels; the headline result large and coloured by good or bad; two or three supporting numbers; works from 360 px wide; a one-line note about assumptions. Guard against division by zero and nonsense values.
Reply with the complete file in one code block and list the assumptions you made. When I ask for changes, return the whole file.
Example result
A two-panel calculator: sliders on the left, live results on the right. The net saving turns red when the tool costs more than it saves, and the payback line handles the zero case.
Assumptions: automated tickets take no agent time; setup cost is fixed at €5,000.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Support automation ROI</title>
<style>
body { margin:0; font-family: system-ui, sans-serif; background:#f3f5f9; color:#1b2433; }
.box { max-width:720px; margin:32px auto; padding:0 16px; }
h1 { font-size:26px; margin:0 0 4px; }
.sub { color:#5b6678; margin:0 0 24px; }
.grid { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.panel { background:#fff; border-radius:16px; padding:22px; box-shadow:0 6px 24px rgba(27,36,51,.08); }
label { display:block; font-size:14px; margin:14px 0 4px; }
label span { float:right; font-weight:600; }
input[type=range] { width:100%; accent-color:#2b6cff; }
.result { font-size:40px; font-weight:700; color:#0a8f5b; margin:6px 0; }
.row { display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid #eef0f4; font-size:15px; }
.note { font-size:13px; color:#5b6678; margin-top:14px; }
@media (max-width:640px){ .grid{grid-template-columns:1fr} }
</style>
</head>
<body>
<div class="box">
<h1>Support automation ROI</h1>
<p class="sub">Move the sliders to match your team. Results update instantly.</p>
<div class="grid">
<div class="panel">
<label>Tickets per month <span id="v-tickets">2,000</span></label>
<input id="tickets" type="range" min="200" max="20000" step="100" value="2000">
<label>Minutes per ticket <span id="v-minutes">9</span></label>
<input id="minutes" type="range" min="2" max="30" value="9">
<label>Cost per agent hour (€) <span id="v-rate">28</span></label>
<input id="rate" type="range" min="10" max="80" value="28">
<label>Share of tickets automated <span id="v-share">35%</span></label>
<input id="share" type="range" min="5" max="80" value="35">
<label>Tool cost per month (€) <span id="v-tool">900</span></label>
<input id="tool" type="range" min="0" max="5000" step="50" value="900">
</div>
<div class="panel">
<div>Net saving per month</div>
<div class="result" id="net">€0</div>
<div class="row"><span>Hours saved</span><b id="hours">0</b></div>
<div class="row"><span>Gross saving</span><b id="gross">€0</b></div>
<div class="row"><span>Tool cost</span><b id="toolcost">€0</b></div>
<div class="row"><span>Payback on a €5,000 setup</span><b id="payback">—</b></div>
<p class="note">Assumes automated tickets take no agent time. Real results vary.</p>
</div>
</div>
</div>
<script>
const ids = ['tickets','minutes','rate','share','tool'];
const el = id => document.getElementById(id);
const eur = n => '€' + Math.round(n).toLocaleString('en-US');
function update() {
const [tickets, minutes, rate, share, tool] = ids.map(id => Number(el(id).value));
el('v-tickets').textContent = tickets.toLocaleString('en-US');
el('v-minutes').textContent = minutes;
el('v-rate').textContent = rate;
el('v-share').textContent = share + '%';
el('v-tool').textContent = tool.toLocaleString('en-US');
const hours = tickets * (share / 100) * minutes / 60;
const gross = hours * rate;
const net = gross - tool;
el('hours').textContent = Math.round(hours).toLocaleString('en-US');
el('gross').textContent = eur(gross);
el('toolcost').textContent = eur(tool);
el('net').textContent = eur(net);
el('net').style.color = net >= 0 ? '#0a8f5b' : '#c0392b';
el('payback').textContent = net > 0 ? (5000 / net).toFixed(1) + ' months' : 'never at these numbers';
}
ids.forEach(id => el(id).addEventListener('input', update));
update();
</script>
</body>
</html>