I run a small site for freelancers, Paid & Filed, and its most useful page is a free 1099 tax calculator that works out quarterly estimated tax. Bloggers, coworking spaces and accountants who write for freelancers kept wanting to put it on their own pages, so I made it embeddable.
The site is a static Next.js export served from a Cloudflare Worker: no backend, no API keys, no per-site accounts. Here's how the embed works within those limits.
The embed is just a second route
The calculator is one React component. The embeddable version is a separate route, /embed/quarterly-tax-calculator/, that renders the same component without the site header, footer or analytics:
export const metadata: Metadata = {
title: '1099 tax calculator for 2026',
robots: { index: false, follow: true },
};
export default function EmbeddedCalculator() {
return (
<div className="px-3 pb-5 pt-4">
<Calculator embedded />
<p className="mt-5 text-center text-[13px]">
Free <a href="https://paidandfiled.com/quarterly-tax-calculator/" target="_blank" rel="noopener">1099 tax calculator</a> by Paid & Filed.
</p>
<EmbedHeight />
</div>
);
}
Two decisions in there:
-
The embed route is
noindex. It's set in the page metadata and again as anX-Robots-Tagheader for/embed/*, so search engines send people to the real calculator page rather than a stripped-down duplicate.followstays on, so the links inside still count. - No trackers in the frame. A layout check turns off the analytics beacon and the ad-network tag on embed routes. Someone embedding a calculator shouldn't be adding third-party tracking to their own visitors without knowing it.
Auto-height without a library
Iframes don't size themselves to their content. A fixed height either cuts off the results or leaves a big gap, and this calculator changes height as you open sections.
The embedded page reports its height to the parent whenever it changes:
export function EmbedHeight() {
useEffect(() => {
const main = document.querySelector('main');
if (window.parent === window || !main) return; // not in a frame
const send = () =>
window.parent.postMessage({ pfHeight: Math.ceil(main.getBoundingClientRect().height) }, '*');
const ro = new ResizeObserver(send);
ro.observe(main);
send();
return () => ro.disconnect();
}, []);
return null;
}
It measures <main>, not document.body. Inside an iframe, the body is always at least as tall as the frame itself, so measuring it means the frame can grow but never shrink.
It posts to '*' because it can't know who embedded it, and that's fine here because the message is a single number and nothing sensitive.
The host page gets one line of script as part of the embed code:
<iframe src="https://paidandfiled.com/embed/quarterly-tax-calculator/"
title="1099 tax calculator for 2026" loading="lazy"
style="width:100%;height:1650px;border:0"></iframe>
<p style="font-size:14px">1099 tax calculator by <a href="https://paidandfiled.com/quarterly-tax-calculator/">Paid & Filed</a></p>
<script>
addEventListener('message', function (e) {
if (e.origin !== 'https://paidandfiled.com' || !e.data || !e.data.pfHeight) return;
document.querySelectorAll('iframe[src^="https://paidandfiled.com/embed/"]').forEach(function (f) {
if (f.contentWindow === e.source) f.style.height = e.data.pfHeight + 'px';
});
});
</script>
The receiving side is where the checks belong:
-
e.originmust be the calculator's origin, so another frame on the page can't resize things. -
f.contentWindow === e.sourcematches the message to the exact iframe that sent it, so two embeds on one page don't fight. - The script is optional. Without it the iframe keeps its fixed height and scrolls, which is ugly but works. Plenty of CMSs strip
<script>from posts, so the fallback matters.
The credit link is a plain brand link
The <p> under the iframe is an ordinary link in the host page that credits the tool by name. It's tempting to make that link anchor text like "best quarterly tax calculator", but Google's spam policies call out keyword-rich links in widgets and embeds that are distributed across many sites. A plain brand-name link is honest attribution, and the host can remove it or add rel="nofollow" if they prefer. The embed works the same either way.
Privacy is easy when there's no server
Because the calculator is pure client-side math on figures from the IRS, nothing the visitor types leaves the browser, inside the iframe or out. That's a big part of why people are comfortable embedding it: no data processing agreement, no cookie banner implications from the frame itself.
Result
The embed code lives in a copy box on the calculator page, free to use. If you've built embeddable widgets on static hosting and handled auto-height differently, I'd like to hear how in the comments.
Top comments (0)