Tax & compliance
Cookie Consent Banner
Generated from docs/plan/core/cookie-consent-banner/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
A core feature that adds a GDPR-compliant cookie consent banner to storefronts, lets customers opt-in/out of analytics and marketing cookies, and prevents GA4/marketing-pixel code from running until consent is given. Merchants reduce GDPR violation risk to zero.
The problem
A Dutch merchant’s storefront has Google Analytics and Facebook Pixel running. Regulators say tracking without explicit consent violates GDPR (€20M fine for repeated violations). She has no consent mechanism. Adding one required 3 months of developer work. She wants a built-in banner that handles consent, blocks pixels until approved, and logs consent decisions.
What it does
- Consent banner UI: appears on first visit, asks for consent (analytics, marketing, necessary cookies)
- Cookie categories: necessary (essential), analytics (GA4), marketing (Facebook, Segment, etc.), preferences (language, theme)
- Opt-in/out: customer can choose which cookies to allow; banner respects choice (no dark patterns)
- Pixel blocking: GA4 pixel does NOT fire until customer consents to analytics
- Consent memory: merchant-side (cookie) and server-side (audit log) record of consent
- Consent withdrawal: customer can revoke consent anytime (via settings or banner re-visit)
- Audit trail: log all consent decisions (who, when, choice) for regulatory inspection
- Preset templates: GDPR-compliant banner copy (merchant can customize)
- Geolocation: show more restrictive banner in EU (opt-in), less restrictive outside EU (opt-out)
- Admin UI: consent statistics (% consented to analytics, % to marketing)
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- Cookie policy page generation—separate feature (privacy-policy-generator)
- ePrivacy Directive compliance (cookie law per country)—out of scope (GDPR only)
- TCF (Transparency & Consent Framework) integration—out of scope (complex, requires cert)
- Cookie deletion/purging—handled by browser; we just log decisions
- Age verification for cookies (e.g., under 16 = stricter)—out of scope
Data model
New: CookieConsent(id, customerId, analytics_allowed, marketing_allowed, timestamp, ip_address, user_agent). Stored in core settings/audit infrastructure, no schema migration.
API
- POST /cookie-consent/decide — customer submits consent choice (analytics=true/false, marketing=true/false)
- GET /cookie-consent/status/:customerId — return current consent state
- POST /cookie-consent/withdraw — customer revokes consent
- GET /cookie-consent/history — audit log of all consent decisions
- GET /cookie-consent/stats — % of visitors consented to analytics/marketing
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Cookie consent dashboard: banner appearance settings (text, colors), consent statistics (% consented to analytics, % to marketing), consent history (all decisions logged), audit report (downloadable for regulators)
The seam — why this is core
Core owns: banner UI, consent storage, audit trail. Paid pack owns: regional compliance variants, advanced privacy settings, cookie policy integration, EULA/terms management.
Core owns the interface + honest consent manager; GDPR compliance is infrastructure, not a per-country obligation requiring local expertise.
Dependencies
- customer/session system (must associate consent with user or session)
- Next.js storefront integration (banner must be rendered on every page)
- GA4 integration (pixel firing must be gated by consent)
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- First-time visitor sees cookie banner; clicking ‘Accept Analytics’ sets CookieConsent(analytics_allowed=true)
- GA4 pixel does NOT fire until customer clicks ‘Accept Analytics’ (logs prove pixel blocked before consent)
- Customer can withdraw consent; GA4 pixel stops firing immediately
- Consent is logged server-side (CookieConsent record) with timestamp, IP, user agent
- Consent statistics show: 60% consented to analytics, 40% to marketing (from last 1000 visitors)
- Banner copy is GDPR-compliant (no manipulative language, clear opt-in/out)
- Geolocation: EU visitor sees opt-in banner; US visitor sees opt-out banner (optional)
- Audit report (PDF) for regulator shows all consent decisions from Sept 2025 (proof of compliance)
Risks
Banner JavaScript breaks → pixel fires without consent → GDPR violation. Merchant uses dark patterns (pre-checked boxes, hard-to-find opt-out)—we should prevent this in template. Consent cookie expires → customer’s choice is forgotten → pixel fires again illegally. If merchant disables banner after enabling it, pixel fires without consent (regression). IP address logged in consent audit = privacy risk (must anonymize/hash).
Commercial context
| Suggested price | free (core) |
| Rival anchor | Shopify: $0 (via theme); Magento: included |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and ../../AI-GUIDE.md for how to work on this repository.