# Calculator embeds reference

> Every attribute, event and setting for the seller net sheet and mortgage embeds, how leads are sent, and what a strict security policy must allow.

The seller net sheet and the mortgage calculator are two custom HTML elements, `<bna-net-sheet>` and `<bna-mortgage>`. One script defines both. The [builder](https://brokerandagent.com/tools/embed) writes the code for you; this page is for anyone who wants to set it by hand or wire it into their own site.

They don't need an account. Leads are optional, and the lead form needs the widget key of a Broker & Agent website.

## The snippet

```html
<script src="https://brokerandagent.com/embed/v1.js" async></script>
<bna-net-sheet states="FL" agent="Jordan Lee">
  Seller net sheet calculator by <a href="https://brokerandagent.com/tools/seller-net-sheet-calculator">Broker &amp; Agent Solutions</a>
</bna-net-sheet>
```

- **The script** can sit anywhere on the page and load `async`. Pasting it twice is harmless: the elements are only defined once.
- **The text inside the element** becomes the credit line under the calculator. Keep it as it is.
- **Several calculators** can share a page and one script.

## Attributes

Attributes are plain HTML, so the snippet stays readable. Changing `theme`, `accent`, `radius`, `font`, `size`, `button-color`, `sticky` or `sticky-top` after the page loads redraws the calculator; set the rest before the element is added to the page.

### Both calculators

| Attribute | Values | Default |
| --- | --- | --- |
| `theme` | `light` or `dark` (a neutral graphite) | `light` |
| `accent` | Any hex color, like `#3FB8AD`. Text on accent buttons turns dark or light for contrast. | Teal |
| `radius` | Corner radius, `0` to `32` (px). At 18 or more, buttons become pills. | `20` |
| `size` | `large` (every field, plus a ring or chart), `compact` (the core fields), or `button` (one button that opens the large calculator in a dialog, or a sheet on a phone) | `large` |
| `button-text` | The button's words, for `size="button"` | “Estimate my net proceeds” or “Estimate my payment” |
| `button-color` | A hex color for the button, for `size="button"` | The accent |
| `font` | `inherit` (the page's own font) or `system` | `inherit` |
| `heading` | The title, or `none` to hide it | The calculator's name |
| `agent` | Your name, used in the lead form's words | None |
| `states` | One state locks it and hides the picker (`FL`); a list shows only those, in that order (`FL,GA,AL`) | All states and DC |
| `state` | Where it starts | The first in `states`, or none (the visitor chooses) |
| `lead` | `off` hides the lead form | On when a widget key is found |
| `cta-href`, `cta-label` | A button to your own page instead of the form. Always wins over the form. | None |
| `key` | Your website's widget key, for a page without the widget snippet (see Leads) | Found on the page |
| `sticky` | `off` stops the result staying in view beside the fields | On |
| `sticky-top` | The result's gap from the top of the window, in px | 16px below your fixed header, found on its own |

### `<bna-net-sheet>`

| Attribute | Values | Default |
| --- | --- | --- |
| `county` | A county in the chosen state, for its local taxes | None |
| `price` | Sale price, in dollars | `450000` |
| `payoff` | Loan payoff, in dollars | `210000` |
| `listing` | Listing agent's commission, percent | `3` |
| `buyer-agent` | Buyer's agent compensation, percent | `2.5` |

Commissions are negotiable. Set the numbers you actually use.

### `<bna-mortgage>`

| Attribute | Values | Default |
| --- | --- | --- |
| `price` | Home price, in dollars | `400000` |
| `down` | Down payment, percent | 20 conventional, 3.5 FHA, 0 VA |
| `rate` | Interest rate, percent | `6.5` |
| `term` | `30`, `20` or `15` (years) | `30` |
| `loan` | `conventional`, `fha` or `va` (large size only) | `conventional` |

## Leads

The lead form appears when the calculator finds your website's widget key. It looks, in order:

1. a `key` attribute on the element;
2. the `data-key` on the widget snippet's tag (`widget.js`, the script that runs the website assistant), if it's on the page;
3. the snippet's own `window.__baWidget.lead()`, if the snippet was added another way.

With none of those, there's no lead form at all, and the calculator still works on any site.

When a visitor presses **Send**, the calculator posts to our public lead endpoint with:

- their name, email and phone;
- a one-line summary of their numbers, as the note;
- `intent`: `sell` for the net sheet, `buy` for the mortgage calculator;
- the page they were on and the referrer;
- whether they agreed to texts, when they typed a phone number (the consent box appears then).

The lead lands in **Site Manager → Leads** as a website contact, and the agent gets an email. The widget key follows your site's domain lock in Site Manager settings: with no domains listed, a key works anywhere, so list yours.

## Events

Both events bubble and cross the shadow boundary, so you can listen on the element or on `document`.

| Event | When | `detail` |
| --- | --- | --- |
| `bna-lead` | A lead was sent | `{ calculator }`, the element's tag name |
| `bna-cta` | The visitor pressed the `cta-href` button | `{ calculator, summary, at }` |

```js
document.addEventListener('bna-lead', (e) => {
  analytics.track('Calculator lead', { calculator: e.detail.calculator });
});
```

### Carrying the numbers to your own form

With `cta-href`, the numbers never go in the link, where they would land in analytics and server logs. Instead, on click the calculator saves them in the visitor's own browser, and your contact page can pick them up:

```js
const saved = JSON.parse(sessionStorage.getItem('bna:numbers') || 'null');
if (saved && Date.now() - saved.at < 30 * 60 * 1000) {
  document.querySelector('textarea[name=message]').value = saved.summary;
}
```

## Security settings

If your site sends a `Content-Security-Policy` header, allow:

| Directive | Add | Why |
| --- | --- | --- |
| `script-src` | `https://brokerandagent.com` | Loads the script |
| `connect-src` | `https://workspace.brokerandagent.com` | Sends leads (only with a lead form) |
| `style-src` | `'unsafe-inline'` | The calculator styles itself inside its own shadow root |

## Frameworks and single-page apps

The elements are standard custom elements, so they work in React, Vue, Svelte or plain HTML. Load the script once, then render the tag with string attributes. Elements added later, after a route change for example, set themselves up when they're attached. In React, attach event listeners through a ref rather than an `on…` prop.

## How it behaves

- **Isolated.** Each calculator draws inside a shadow root: your CSS can't break it, and its CSS can't reach your page.
- **Responsive.** It sizes to its container, not the window, and moves to two columns at 680px wide.
- **Light.** About 32 KB compressed, most of it the state rules. It loads after your page and sets no cookies.
- **Private until sent.** Numbers a visitor types stay in their browser. Only pressing **Send** sends anything, and only then does it save a visitor ID in their browser, the same one the widget snippet uses, so a calculator lead joins that visitor's history.
- **Accessible.** Every field works from the keyboard, the result is announced to screen readers, and motion stops for visitors who ask their device for less.
- **Current.** It uses the same state rules as our calculators, so tax changes reach your page with no new code.

## Versions

`v1.js` is a promise: attributes can be added, never renamed or removed. A breaking change would ship as `v2.js`, and `v1.js` keeps working.

---

Source: https://brokerandagent.com/developers/embeds
