Skip to main content
Cookie 同意是每个公开网站都要做的工作,但几乎所有 indie 都拖到买家法务团队 flag 才补。vibestrap ship 了一个能直接跑的 banner,所以你不用在”快上线”和 “day-one 合规”之间二选一:
  • 🍪 默认 opt-in —— 分析脚本(Google Analytics、Microsoft Clarity、 PostHog)等用户点 Accept 后才加载。同意前不收集任何数据。
  • ⚖️ 全球统一合规框架 —— 一套”您的隐私选择”机制覆盖 GDPR(欧盟/英国)、 CCPA / CPRA(加州)、LGPD(巴西)、PIPL(中国);banner 或页脚一键退出。
  • 🧹 撤回时清理 —— 用户先 Accept 后 Decline 了 analytics,我们会把已经 设的 cookie 清掉。GDPR 第 7(3) 条。
  • 🌍 双语 —— en / zh 跟 vibestrap 现有 i18n 一致,不需要额外语言检测。
  • 🎨 两按钮 banner —— 只有 Accept / Reject,没有第三个”自定义”按钮。 分类粒度控制放在页脚的 “Cookie 偏好” 链接里(Hick’s 定律:选项越少决策越快)。
  • 🛠️ 基于 vanilla-cookieconsent (9k+ stars, MIT)。通过 CSS 变量轻松改皮肤。
架构有意分成三层:

前置条件

  • 无需安装 —— vanilla-cookieconsent 已经是依赖。
  • siteConfig.cookieConsent.enable 默认 true(banner 默认开启)。

一步步配置

1. 在 src/config/site.ts 确认开启

2. 验证 analytics 门控

src/analytics/analytics.tsx 里脚本被分成两组:
allowAnalytics 只有用户点了 Accept(或者之前 12 个月内已同意)才是 true 如果你加了新 analytics provider 或换了一个,把 siteConfig.cookieConsent.revision 加 1。所有之前同意过的用户会再看到 banner,可以在新政策下重新同意。这是 GDPR 最佳实践。

4. 在浏览器里验证

dev 模式下 banner 故意跳过,免得开发时每次刷新都被 banner 砸脸(看 cookie-consent.tsx 里的 process.env.NODE_ENV 检查)。要看真 banner:
你应该看到:
  • 首次访问右下角弹出 toast
  • 两个按钮:Accept all / Reject all
  • 底部链接:Privacy Policy · Cookie Policy · Your Privacy Choices

用户旅程 —— 每个场景都对齐业界标杆

下面这张矩阵把每个常见用户流映射到 vibestrap 的行为以及 Stripe / Microsoft / Vercel / Cloudflare / Linear / OpenAI 同等场景的行为。实现处处对齐业界—— 没有任何独家或反直觉的设定。 默认有效期 395 天(约 13 个月),跟下列对齐:
  • Stripe (13 个月)
  • Microsoft (13 个月)
  • Cloudflare (13 个月)
这是英国 ICO 和法国 CNIL 推荐的上限 —— 足够长让回访用户不被反复打扰, 足够短保证同意”新鲜”。选更短窗口(Vercel / Linear / Notion 用 6 个月)也合规; 我们选 13 个月是为了对齐最严肃的参考实现。要调整,改 siteConfig.cookieConsent.expiresAfterDays

自定义 banner 文案

所有 banner 文字在 messages/{en,zh}.jsonCookieConsent namespace。 改标题、按钮、描述就改这些 key —— 两个文件同步改(i18n audit 会抓 drift)。

自定义 banner UI

vanilla-cookieconsent 暴露了大约 30 个 CSS 变量(颜色、圆角、阴影、字体)。 override 这些变量,或加自定义 CSS 层:
要完全替换 UI 也行 —— 但默认已经是 Linear / Stripe 风格的 toast,基本够用。

撤回入口

GDPR 第 7(3) 条要求撤回同意必须跟给同意一样容易。vibestrap 在页脚 Legal section 渲染了一个 Cookie Preferences 链接,点击重新打开 modal。 由 src/components/cookie-consent/cookie-preferences-link.tsx 挂载,自动接 好 —— 不要删掉。

常见坑

  1. dev 看不到 banner。这是有意的 —— dev 模式短路到”全部同意”,所以你 测 analytics 不会被 banner 烦。用 pnpm build && pnpm start 看真 banner。
  2. 加了新 tracker 忘了 bump revision。已有用户不会被重新询问,会在旧 同意下被新 tracker 跟踪(旧同意没覆盖新 tracker)。加新 tracker 的同一个 PR 必须 bump siteConfig.cookieConsent.revision
  3. Decline 后 analytics 还在加载。检查 src/analytics/analytics.tsx 里 的脚本渲染是不是真的在 allowAnalytics 后面 —— 加新 tracker 时容易忘。 约定:任何会下 cookie 的都门控,cookie-free 的(Vercel / Plausible / Umami)无条件渲染。
  4. banner 渲染出破碎 HTML。如果你自定义了 banner footer 字符串(隐私 政策、隐私选择链接),确保 HTML 合法 —— 库会 raw 渲染。
  5. 语言不匹配。banner 读 <html lang="…">(由 next-intl 设置)。如果 你的自定义 layout 设了别的 lang,banner 会 fallback 到英文。

“您的隐私选择” —— 全球统一框架

banner footer 链接到 /privacy#privacy-choices,这是隐私政策里全球统一 的退出权利章节,涵盖所有访问者的退出权:GDPR(欧盟/英国)、CCPA / CPRA (加州)、LGPD(巴西)、PIPL(中国)。退出机制对每个访问者都一样 (banner、页脚链接或邮件);章节里再点名每个地区的具名权利 (比如加州的”Do Not Sell My Personal Information”),让搜这个法定术语 的监管也能找到。 这跟 Apple、Microsoft、Stripe 的做法一致 —— 它们都从加州专属的 “Do Not Sell” 抬头转向了全球统一的”Your Privacy Choices”框架, 下挂各地具名子权利。如果你重点做加州市场,想给 opt-out 加专门的表单页, 可以建一个 /privacy/privacy-choices 页;内联章节是 indie 阶段的默认。 如果你完全 cookie-free(只用 Vercel Analytics / Plausible / Umami),不想 要 banner,设:
这仍然挂载 React Context(useConsent() 还能用),但把每个用户当成”已同意 全部”处理。banner UI 完全跳过。

官方资源