独立开发者的零成本用户反馈方案
用 Tally + Cloudflare Worker + GitHub Issues 搭建零成本全球用户反馈系统,从用户提交到研发工单全程自动化。
引言
用户反馈是独立开发者产品迭代的生命线,但搭建反馈系统往往面临三大难题:
- 成本压力:专业反馈工具免费版额度极低,付费版成本不菲
- 全球覆盖:国内工具海外用户打不开,海外工具国内用户访问慢
- 研发脱节:反馈数据沉淀在第三方平台,需要手动同步到 GitHub 工单
我在 DouXia 项目中落地了一套零成本、全球覆盖、与研发流程无缝打通的方案。
方案对比
当前常见方案
| 方案 | 成本 | 国内访问 | 海外访问 | 研发协同 |
|---|---|---|---|---|
| 付费反馈工具 | 高 | 一般 | 一般 | 好 |
| Google Forms | 免费 | 不可用 | 极佳 | 差 |
| 腾讯兔小巢 | 免费版 100 条/月 | 极佳 | 不可用 | 差 |
| 完全自建 | 服务器成本 | 自托管 | 自托管 | 最好 |
推荐方案
本文方案组合三个免费工具,形成生产级反馈流水线:
- Tally:无提交量限制,全球 CDN 覆盖
- Cloudflare Worker:日限 10 万请求免费额度
- GitHub Issues:公开仓库免费,原生开发者工作流
架构总览
App 反馈按钮 → Tally 表单(WebView)→ Webhook → Cloudflare Worker → GitHub Issues
核心组件
- Tally 表单:自定义反馈收集,支持隐藏字段传递设备元数据
- Cloudflare Worker:轻量 Serverless 函数,接收 Webhook 并创建 GitHub Issue
- GitHub Issues:反馈数据结构化沉淀,与 Bug 修复、需求迭代无缝打通
设计原则
- 不绑定企业生态:仅依赖通用工具,迁移成本极低
- 异步优先:Webhook 不阻塞用户体验
- 数据可追溯:每条反馈有唯一 ID,用户可追踪处理状态
- 隐私优先:设备信息哈希化处理,不收集个人隐私
代码实现
App 端集成
const feedbackId = generateUUID()
const params = new URLSearchParams({
device_id: hashDeviceInfo(),
os_type: getOS(),
app_type: 'desktop',
feedback_id: feedbackId
})
const url = `https://tally.so/r/your-form-id?${params.toString()}`
openWebView(url)
Cloudflare Worker
Lookup 路由 (/lookup):
addEventListener('fetch', event => {
const url = new URL(event.request.url)
const feedbackId = url.searchParams.get('feedback_id')
const html = `
<h1>反馈提交成功!</h1>
<p>您的反馈 ID:${feedbackId}</p>
<a href="https://github.com/repo/issues?q=FeedbackID:${feedbackId}">
查看处理进度
</a>
`
event.respondWith(new Response(html, { headers: { 'Content-Type': 'text/html' } }))
})
Webhook 路由 (/webhook):
async function handleWebhook(request) {
const data = await request.json()
await fetch(`https://api.github.com/repos/repo/issues`, {
method: 'POST',
headers: {
'Authorization': `token ${GITHUB_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: `Feedback: ${data.feedback_id}`,
body: `设备类型: ${data.os_type}\n描述: ${data.description}`
})
})
return new Response('OK', { status: 200 })
}
关键技术要点
异步竞态问题
问题:Tally 的 Webhook 是异步请求,页面跳转速度远快于 GitHub Issue 创建速度。
解决方案:使用静态 GitHub 搜索链接,用户点击时 Issue 必然已创建完成。
隐藏字段传参规则
问题:Tally 隐藏字段仅在页面首次加载时读取 URL 参数,刷新后参数丢失。
解决方案:WebView 禁用刷新手势,Worker 读取 Referer 请求头作为兜底。
Webhook 返回值限制
问题:Webhook 返回的 302 或 JSON 无法影响 Tally 的行为。
解决方案:使用 Tally 内置的提交后跳转功能。
效果对比
| 指标 | 实施前 | 实施后 |
|---|---|---|
| 开发时间 | 2+ 天 | 1-2 小时 |
| 月成本 | $50+ | $0 |
| 反馈响应 | 数小时 | 实时 |
| 全球覆盖 | 部分 | 完全 |
复现步骤
- 注册 Tally 账号,创建反馈表单
- 配置 Cloudflare Worker,部署
/lookup和/webhook路由 - 设置 Worker 环境变量:
GITHUB_TOKEN、GITHUB_REPO - 在 Tally 表单中配置 Webhook 和提交后跳转地址
- 在 App 中添加反馈按钮,打开携带设备参数的 Tally 链接
总结
这套零成本反馈方案解决了独立开发者面临的三大难题:成本、全球覆盖、研发集成。方案已在 DouXia 项目中稳定运行,建议独立开发者从这个最小配置开始尝试。