Plain HTML forms to Excel
One action attribute, zero backend. Your static site's form posts to a permanent endpoint and every submission is inserted as a live row in your Excel table on OneDrive.
A plain HTML form is the most durable lead-capture mechanism on the web - no framework, no build step, nothing to rot. What it has never had is a way to reach Excel. Something has to receive the POST, screen it for spam, and insert the row, and until now that something was your own server code or a metered automation tool. SheetLink Forms is a hosted backend with a native Excel Online destination: point your form's action at a permanent endpoint of the shape https://sheetlinkforms.com/f/{token} and each submission is inserted into an Excel table in your OneDrive workbook.
The insert happens through Microsoft Graph, directly against the live workbook - these are real table rows, not a CSV you download and import. Open the file in Excel on the web or the desktop app and the row is already there; connect Power BI to the same workbook and your form feeds a live dashboard. An asynchronous worker handles delivery with automatic retries at 5 minutes, 30 minutes, and 2 hours, and every attempt is visible in a delivery log, so no lead's fate is ever a mystery. No other hosted form backend offers this - Formspree, Basin, and Formcarry all stop at Google Sheets or webhooks, leaving Excel to per-task Zapier or Power Automate flows.
Prefer Google Sheets for some forms? The same endpoint writes there too. SheetLink Forms is free during beta and invite-gated - join the waitlist, or watch the setup working on the live demo.
The best path for Plain HTML
The best path for a static site is also the simplest: set action to your endpoint and method to POST, and let the browser do the rest. The endpoint accepts standard urlencoded form posts (bodies capped at 256KB) and answers with a 303 redirect to a hosted thank-you page or any custom redirect URL you configure. No JavaScript required at all.
For more, add the optional sl.js embed. It upgrades the same form to an AJAX submit with inline success text, auto-injects the honeypot, adds a timing signal used in spam screening, and captures utm_source, utm_medium, utm_campaign, utm_term, and utm_content plus the gclid, wbraid, gbraid, fbclid, and msclkid click IDs - persisted in localStorage so attribution survives a visitor browsing several pages before submitting. Give your Excel table matching columns and those values land right alongside the lead.
1. Prepare an Excel table and connect your Microsoft account
In a workbook on OneDrive, create a table with the columns you want - select your header cells in Excel and press Ctrl+T. Then sign in to the SheetLink Forms dashboard, connect a Microsoft account (Microsoft 365 or a personal Microsoft account with OneDrive) via OAuth, and pick that workbook and table. SheetLink Forms syncs the column names from the table; the table's columns define the row shape, so there is no header seeding step on the Excel path - the table you built is the contract. If you would rather write to Google Sheets, that destination sits on the same screen. Either way you get a permanent endpoint at https://sheetlinkforms.com/f/{token}.
2. Point your form at the endpoint
Set action to the endpoint and method="POST". Name your inputs after your table's columns and mapping happens by itself - matching is case- and punctuation-insensitive, so Email, email, and E-mail all land in an Email column. When names and columns genuinely differ, set an explicit per-field mapping in the dashboard.
3. Add the honeypot input
Copy the _slhp input from the snippet above. It sits off-screen where no human ever sees it, so anything that fills it is a bot - the honeypot is the only signal that marks spam outright. Everything else that merely looks suspicious (rate-limit trips, content heuristics, timing anomalies) goes to quarantine for one-click review instead, so a false positive costs seconds, not a lead. Details in the docs.
4. Optionally add sl.js
Drop the script tag before </body>. It binds any form whose action points at /f/ (and any form marked data-sheetlink), converts it to an AJAX submit with inline success text, injects the honeypot for you, adds the timing signal, and captures UTM parameters and ad click IDs. Skip it and the plain 303-redirect flow keeps working unchanged.
5. Submit a test and open the workbook
Send a test submission, then open the workbook in Excel on the web or the desktop app - the row is inserted into the live table via Microsoft Graph, so it appears within seconds, no export or refresh dance. The delivery log in the dashboard shows each attempt, and a formula-injection guard escapes leading =, +, -, and @ characters so a hostile submission stays inert text in the cell. The full flow is on how it works.
FAQ
Is this really writing to my Excel file, or exporting a CSV?
Really writing. Each submission becomes a Microsoft Graph table-row insert against your workbook on OneDrive - the row exists in the actual file the moment delivery completes. There is no CSV stage, no import, no sync job. That also means Power BI can point at the workbook and turn your form into a live dashboard.
Does my Excel table need to exist before the first submission?
Yes. The table's columns define the row shape, and SheetLink Forms syncs column names from the table - so create it first with the columns you want. This is the one place the Excel path differs from Google Sheets, where an empty sheet gets its header row seeded from your first submission. On Excel, you author the columns; on Sheets, the product can.
Do I need any JavaScript at all?
No. A bare action + method="POST" form works with JavaScript disabled: the endpoint accepts the urlencoded post and answers with a 303 redirect to a thank-you page or your custom redirect URL. sl.js is strictly optional - it adds inline success handling and ad attribution, but the form never depends on it.
How is spam handled when I have no backend of my own?
Several layers run on the endpoint itself: the _slhp honeypot, per-form and per-IP rate limits, an optional per-form origin allowlist, content heuristics (link stuffing, disposable email domains, empty payloads) with a per-form strictness dial, the sl.js timing signal, and optional Cloudflare Turnstile. Suspicious submissions are quarantined for one-click review - approve and the row is inserted - and never silently dropped.
Can a submission break formulas elsewhere in my workbook?
No. A formula-injection guard escapes leading =, +, -, and @ in values before rows are written, so a pasted payload lands as inert text in its cell rather than executing as a formula.
What does it cost?
SheetLink Forms is free during beta; an invite is required, so join the waitlist. Planned post-beta pricing is a free tier around 50 submissions a month and a paid plan around $15-19/mo, unmetered. There are no per-submission or per-task fees, ever - the exact opposite of routing HTML forms to Excel through Zapier or Power Automate, where every row is a billed task.
Also on: Plain HTML · Next.js · Netlify-hosted sites · Carrd