import type { CollectionConfig } from "payload"; import { canViewAnalytics } from "@/access"; /** * One row per tracked event (page_view, booking_started, ...). Deliberately * append-only and never writable via the public/admin API - the only writer * is app/(payload)/api/analytics/track/route.ts, which uses the trusted * Local API (overrideAccess: true by default) to insert rows despite * `create` being locked to `() => false` here. The only deleter is the * cleanup cron (lib/analytics/cleanup.ts), same mechanism. * * No name/email/IP/UA is ever stored - see lib/analytics/salt.ts for how * `visitorHash` is derived without persisting anything identifying. */ export const AnalyticsEvents: CollectionConfig = { slug: "analytics-events", labels: { singular: "Messereignis", plural: "Messereignisse", }, admin: { group: "Auswertung", hidden: true, // High-volume, low-signal raw data - not meant for manual browsing. // The Analytics dashboard (a custom admin view) reads it programmatically. }, access: { create: () => false, read: canViewAnalytics, update: () => false, delete: () => false, }, timestamps: true, indexes: [{ fields: ["visitorHash", "createdAt"] }, { fields: ["createdAt"] }], fields: [ { name: "sessionId", type: "text", required: true, index: true, }, { name: "visitorHash", type: "text", required: true, // Daily-rotating pseudonymous hash (see lib/analytics/salt.ts) - never // a raw IP/UA, never stable across days, never exposed to the client. }, { name: "path", type: "text", required: true, index: true, }, { name: "eventName", type: "text", required: true, index: true, // Deliberately free-text, not a select/enum: new event names (see // lib/analytics/events.ts) never require a schema migration. defaultValue: "page_view", }, { name: "referrerHost", type: "text", // Hostname only (never a full URL/query string). document.referrer is // fixed for a tab's whole lifetime (it doesn't change on client-side // route transitions), so this naturally reflects how the visitor // originally arrived, sent unchanged with every event in the session. }, { name: "device", type: "select", options: [ { label: "Mobile", value: "mobile" }, { label: "Desktop", value: "desktop" }, { label: "Tablet", value: "tablet" }, ], }, { name: "browser", type: "select", options: [ { label: "Chrome", value: "chrome" }, { label: "Firefox", value: "firefox" }, { label: "Safari", value: "safari" }, { label: "Edge", value: "edge" }, { label: "Sonstige", value: "other" }, ], }, ], };