What It Does
ROI Calculator Pro is an interactive calculator builder for HubSpot CMS. Visitors adjust inputs — sliders, number fields, dropdowns, toggles — and see real-time results computed by a safe formula engine. Results animate with count-up effects. Calculator state is shareable via URL. An optional HubSpot form captures leads after they see their results. Everything is configured from the HubSpot editor — inputs, formulas, outputs, form settings, and the full visual design. No code required.
Content Tab
All user-facing text is configurable from the Content tab. Nothing is hardcoded.
Text Fields (11)
- Calculator Heading — the main title displayed at the top of the calculator
- Calculator Subheading — description text below the heading
- Show Heading — toggle to show/hide the entire header section
- Results Heading — small uppercase label above the results grid (e.g. "Projected Savings")
- Copy Link Text — button label for the share URL button (e.g. "Share Results")
- Copy Link Success — text shown after successful copy (e.g. "Link copied!")
- Currency Symbol — used for currency-formatted outputs (e.g. "$", "€", "£")
- Form Trigger Text — CTA button label when form trigger is set to "on CTA click"
- Form Section Heading — heading above the embedded HubSpot form
- Form Section Subheading — description below the form heading
- Form Thank You — message shown after form submission
Inputs Repeater (16 fields per input)
Each calculator input is defined in a repeater with full control over behavior and appearance:
- Field ID — unique snake_case identifier used in formulas (e.g. team_size, hourly_rate)
- Label — display name shown above the control
- Type — slider, number, dropdown, toggle, or read-only
- Default Value — initial value on page load
- Min / Max / Step — range constraints and increment (applies to slider and number)
- Prefix / Suffix — text around the displayed value (e.g. "$" prefix, "hrs" suffix)
- Tooltip — hover "?" icon with explanatory text
- Dropdown Options — comma-separated label:value pairs (e.g. "Starter — $29:29,Pro — $79:79")
- Toggle On/Off Values — numeric values for on/off states (e.g. 0.8 / 1 for a discount toggle)
- Toggle On/Off Text — labels shown next to the toggle (e.g. "20% discount" / "Monthly billing")
- Include in URL — whether this input’s value is encoded in the shareable URL
Outputs Repeater (9 fields per output)
- Field ID — unique identifier, also used for chaining (later outputs can reference earlier ones)
- Label — uppercase text below the computed value
- Formula — expression using {field_id} variables, arithmetic, functions
- Format — number (integer with commas), currency (symbol prefix), percent (% suffix), decimal (fixed places)
- Decimals — number of decimal places for currency/percent/decimal formats
- Prefix / Suffix — additional text around the formatted value
- Primary — marks the card with inverted colors and full-width span in multi-column grids
- Icon — FontAwesome 6 icon name (e.g. piggy-bank, chart-line, clock, dollar-sign)
Constants Repeater
Named numeric values available in all formulas. Useful for tax rates, base prices, or conversion factors that don’t need user input. Each constant has a name and a value.
Settings Tab
- Layout Direction — side by side (inputs left, results right) or stacked (inputs above, results below)
- Panel Ratio — 50/50, 60/40, 58/42, or 40/60. Controls the width split in side-by-side mode
- Results Columns — 1, 2, or 3 columns for the results grid. Primary cards always span full width
- Show Copy Link — show/hide the share URL button
- Animation — enable/disable count-up animation on result values
- Animation Duration — speed of the count-up in milliseconds (400–2000)
- Sticky Results on Mobile — pin results to the top of the viewport when scrolling on mobile
- Form Enabled — toggle HubSpot form integration
- Form ID — the HubSpot form ID to embed
- Form Trigger — when to show the form: on page load, after first interaction, or on CTA click
Style Tab — Full Reference
49 style fields organized into 6 groups. Every visual property is controlled from the editor — zero hardcoded colors, sizes, or spacing. All values are injected as CSS custom properties.
Container (7 fields)
- Max Width — overall module width in pixels (e.g. 800, 960, 1200)
- Container Padding — inner padding of the main card in pixels
- Container Background — background color + opacity (supports any hex + 0–100%)
- Container Border — border color + opacity. Applied as 1px solid to the outer card and as panel separators
- Container Radius — border-radius of the outer card in pixels
- Container Shadow — none, sm (subtle), md (medium), or lg (pronounced drop shadow)
- Panel Gap — spacing between the input and results panels in pixels. Also controls the padding/border-offset between panels
Colors (25 fields, each with color + opacity)
- Accent — primary brand color used for focus states, tooltip hover, and CTA fallback
- Heading / Subheading — calculator title and subtitle text colors
- Input Label / Input Value — label text and displayed value colors
- Slider Track / Fill / Thumb — the unfilled track, filled progress, and draggable thumb
- Input Border / Focus — border color for number inputs, dropdowns; focus ring color
- Toggle Off / On — switch background in off and on states
- Result Card BG / Border — background and border of regular result cards
- Result Value / Label / Icon — text color for the computed value, label, and icon
- Primary Card BG / Text — inverted background and text for primary result cards
- Tooltip BG / Text — tooltip bubble background and text colors
- CTA BG / Text / Hover BG — button default, text, and hover background
- Form Section BG — background for the form embed area
Typography (8 fields)
- Base Font — font picker (family + fallback). Applies to the entire module
- Heading Size — calculator title font size in pixels
- Subheading Size — subtitle font size
- Input Label Size — font size for input labels
- Input Value Size — font size for displayed values, number inputs, dropdowns, and toggle text
- Result Value Size — font size for the computed output value. Primary cards render at 1.15x this size
- Result Label Size — font size for the uppercase label below each result value. Also used for the results section heading
- CTA Font Size — font size for the form trigger button
Result Cards (4 fields)
- Card Radius — border-radius of each result card in pixels
- Card Padding — inner padding of each result card. Also used (scaled) for the form section
- Card Shadow — none, sm, or md. Applied to all result cards
- Card Hover — none, lift (translateY with shadow), or glow (accent border highlight)
Input Controls (5 fields)
- Input Group Gap — vertical spacing between input groups in pixels
- Input Radius — border-radius for number inputs, dropdowns, CTA button, and copy button
- Slider Thumb Size — diameter of the slider thumb in pixels. The slider element height matches this automatically
- Slider Track Height — thickness of the slider track in pixels. Rendered as a thin strip centered within the thumb-height element
- Tooltip Radius — border-radius of the tooltip bubble
Responsive (1 field)
- Tablet Breakpoint — pixel width below which side-by-side layouts stack vertically, results grids collapse to 2 columns (then 1 on phone at 480px), and container padding reduces
Formula Engine
Output values are computed by a safe recursive descent parser — no eval() or Function constructor. The parser supports:
- Arithmetic — +, -, *, /, % (modulo)
- Parentheses — grouping: ({a} + {b}) * {c}
- Unary minus — negative values: -{discount}
- Comparison — >, <, >=, <=, ==, != (returns 1 or 0)
- Ternary — condition ? value_if_true : value_if_false
- Functions — round(), floor(), ceil(), abs(), min(), max(), if(condition, then, else)
- Variables — {field_id} references any input, constant, or previously computed output
Output chaining: each output’s result is stored in state after calculation, so later outputs can reference earlier ones by their field ID. This allows building complex calculation chains without repeating formulas.
URL Sharing
Inputs with "Include in shareable URL" enabled write their current value to the page URL as query parameters. The Copy Results Link button copies the full URL. Recipients opening that link see the calculator initialized with the shared values and identical results. Parameters update in real time via history.replaceState() — no page reloads.
HubSpot Form Integration
Three trigger modes control when the embedded form appears:
- On Page Load — form section visible immediately
- After First Interaction — appears once the visitor adjusts any input
- On CTA Click — CTA button appears below results; clicking reveals the form
After submission, the form is replaced with a configurable thank-you message.
Technical Details
- Zero dependencies — vanilla JavaScript, no jQuery. Only external resource is FontAwesome 6 Free for result card icons (loaded via require_css, deduplicated by HubSpot)
- Safe parsing — recursive descent tokenizer + parser. No eval(), no Function(), no innerHTML. Only arithmetic, comparisons, and 7 whitelisted math functions
- Accessible — ARIA labels on all controls, role="switch" on toggles, visible focus indicators, keyboard navigable. Count-up animation respects prefers-reduced-motion
- Instance isolation — all CSS scoped via HubL docs. Multiple calculators on the same page work independently with separate state
- Template agnostic — works on website pages, landing pages, blog posts. No theme dependency. Ships its own complete stylesheet
- Cross-browser — slider styling handles both WebKit (-webkit-slider-thumb) and Firefox (-moz-range-thumb) with separate rules