快速回答:给托管在 GitHub Pages、Netlify、Vercel 或 Cloudflare Pages 的任意站点接上能收数据的联系表单——一个 action 地址搞定,无服务器、无数据库、免费。
页面一个下午就做好了,推到 GitHub Pages 或 Netlify 上,效果很漂亮——直到有人在联系表单里点了「发送」,然后什么都没有发生。页面只是文件,静态托管只会发文件;表单的 POST 需要一个落点,而「落点」恰恰是静态托管给不了的东西。
这里给出与平台无关的解法:站点的每个字节都保持静态,只把表单的 action 指向一个替你存提交的托管接口。一行 HTML,在任何宿主上都一样。
静态托管替你补不了的那一块
几家主流宿主对这个缺口的处理各不相同,而差别里全是坑:
- GitHub Pages —— 完全不管表单。
action必须指向站外,没有第二条路。 - Netlify ——
data-netlify="true"在构建期捕获表单。功能是真的,但只在留在 Netlify 时成立:哪天搬家,收下来的提交和垃圾过滤全留在原地。 - Vercel —— 静态文件免费;想接住一个 POST,得自己写并部署一个 serverless 函数。
- Cloudflare Pages —— 同样:不上 Worker,表单就没有去处。
四个选项里三个把你的数据焊死在一个平台上,剩下一个要你写服务端代码。第四个才是一行走到哪儿都能用的 URL。
两分钟接好
在 FormLM 上发布任意表单(哪怕一张空白采集表),你就得到一个接口:https://formlm.me/api/v3/share/<token>/form。把现成的 HTML 表单指过去:
<form action="https://formlm.me/api/v3/share/YOUR_TOKEN/form" method="POST"> <input name="name" placeholder="你的称呼" required> <input name="email" type="email" placeholder="邮箱" required> <textarea name="message" placeholder="想聊点什么?" required></textarea> <!-- 蜜罐:CSS 藏起来,机器人会填,真人看不见 --> <input name="company" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px"> <button type="submit">发送</button> </form>
整合到此为止:没有构建步骤,仓库里不用藏任何密钥,也没有函数要部署。name 属性就是存下来的字段——今天加一个输入框,明天的提交就带着新列。想让用户留在页内?把原生提交换成对同一接口 JSON 侧的几行 fetch,就地显示成功提示;存储的行为完全一致。
上线前先验一发
接口就是普通 HTTP,整个链路可以在终端里先跑通——不用浏览器,不用先部署:
curl -X POST "https://formlm.me/api/v3/share/YOUR_TOKEN/form" \ -d "name=冒烟测试&email=me@example.com&message=hello" curl "https://formlm.me/api/v3/share/YOUR_TOKEN/query?page=1&size=10"
记录以 JSON 返回;控制台里的数据界面把同样的提交做成人类可读的收件箱,CSV 导出一步到位。翻页循环、聚合汇总、定时导出这些长尾玩法,在《把表单数据交给程序:Query、Summary 与 CSV 工作流》里展开讲。
另外几条路为什么都不顺手
mailto:—— 打开访客的邮件客户端(如果他还留着),顺便把邮箱地址送给全网每一个爬虫。这是 1998 年的方案。- 内嵌 iframe 表单 —— 拖进来最快,但样式是别人的、品牌露出是别人的,你刚调好的页面布局也会被它搅乱。
- 自己写函数 —— 一个收 POST 的 serverless 函数确实不难;难的是围着它补的邮件管道、垃圾过滤、仪表盘、导出和可用性兜底。
- 托管接口 —— 标记语言归你,站点保持静态,存储、防垃圾、取数归别人。这就是本文推荐的这笔交易。
"「静态站点」描述的是页面怎么伺服,不是你的数据非得有多寒酸。离一个真收件箱,表单只差九个字符的 action——宿主照旧,让那行 URL 当后端。"
🛠️ 今晚就把联系表单上线
一个免费接口包下全部工作——整个方案里没有一台服务器:
- 接受原生 HTML POST —— GitHub Pages、Netlify、Vercel、Cloudflare Pages 或任何宿主都能用
- 免费套餐 —— 发布表单和收取提交都不设按次计费
- 收件箱 + 查询 + 汇总 + CSV —— 读的一侧随写的一侧一起交付
- 防滥用 —— 接口级频率限制,加上让垃圾提交一眼可辨的蜜罐写法
✅ 要点回顾
- 静态宿主只发文件;表单 POST 需要落点,四家主流宿主里只有 Netlify 给了一个——还把它焊在平台上
- 托管表单接口把「收提交」缩成一个 action URL,在所有宿主上通用
- 字段来自你的
name属性——输入框随便加,不存在表结构迁移 - 部署前用 curl 验链路;上线后在数据界面、查询接口或 CSV 里取数
- 藏一个蜜罐输入框:带值的提交就是机器人流量,读取时一眼识破、随手过滤
- 站点继续静态——只是数据不再无家可归
常见问题
GitHub Pages 能处理表单提交吗?
不能。GitHub Pages 只伺服静态文件,页面里的 POST 发出去没有落点。解法只有一行:把表单的 action 指向一个托管接口,比如 FormLM Data API。页面保持纯静态,提交存进服务端,随时能翻、能查、能导出。
我一直在用 Netlify Forms,为什么要找替代?
data-netlify="true" 只在站点由 Netlify 构建和伺服时有效。哪天迁到 GitHub Pages、Vercel 或自己的服务器,收下来的提交和垃圾过滤就一起留在了原地。用一个与平台无关的 action 地址,站点搬到哪儿,收件箱都跟着到哪儿。
表单必须配 JavaScript 才能用吗?
不必。接口直接接受原生 HTML 表单 POST,浏览器禁用脚本也能提交。想让用户留在页内、就地显示成功提示,再换几行 fetch 打到同一个接口——地址不变,令牌不变。
怎么挡住机器人刷表单?
每个接口都有频率限制,洪水式的刷提交会被挡下;再用一个 CSS 藏起来的蜜罐字段识破漏网的机器人——真人不会填它,带蜜罐值的提交在收件箱和查询结果里一眼就能认出来,读取时随手过滤。
