Adds a first-party analytics system with no third-party trackers and no persistent per-visitor identifiers: events are grouped into sessions via a daily-rotating pseudonymous hash (IP+UA+host, HMAC-salted, never stored raw). - New "Analytics" section in the Payload admin, gated by a canViewAnalytics permission on Users, following the existing custom-admin-view pattern used by the calendar feature - Sessions, page views, unique visitors, top/entry/exit pages, events, device/browser breakdown, date range filter with period comparison - Raw events and daily aggregate rollups as their own collections, with configurable retention and a cron endpoint that rolls up before purging - Cookie consent banner (necessary/preferences/statistics) with categories and copy editable from a new CMS global; a track() helper that is a complete no-op without statistics consent, so nothing is ever sent before a visitor opts in - track() calls wired into the booking flow, contact form, and navigation
49 lines
1.7 KiB
TypeScript
49 lines
1.7 KiB
TypeScript
import { cache } from "react";
|
|
import { getCMS } from "@/lib/payload/getPayload";
|
|
import type { About, AktuellesIntro, AngeboteIntro, Booking, BookingSetting, Contact, CookieSetting, Home, SeoSetting } from "@/payload-types";
|
|
|
|
export const getHomeGlobal = cache(async (): Promise<Home> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "home" });
|
|
});
|
|
|
|
export const getAboutGlobal = cache(async (): Promise<About> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "about" });
|
|
});
|
|
|
|
export const getAngeboteIntroGlobal = cache(async (): Promise<AngeboteIntro> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "angebote-intro" });
|
|
});
|
|
|
|
export const getAktuellesIntroGlobal = cache(async (): Promise<AktuellesIntro> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "aktuelles-intro" });
|
|
});
|
|
|
|
export const getContactGlobal = cache(async (): Promise<Contact> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "contact" });
|
|
});
|
|
|
|
export const getBookingGlobal = cache(async (): Promise<Booking> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "booking" });
|
|
});
|
|
|
|
export const getBookingSettingsGlobal = cache(async (): Promise<BookingSetting> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "booking-settings" });
|
|
});
|
|
|
|
export const getSEOSettingsGlobal = cache(async (): Promise<SeoSetting> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "seo-settings" });
|
|
});
|
|
|
|
export const getCookieSettingsGlobal = cache(async (): Promise<CookieSetting> => {
|
|
const payload = await getCMS();
|
|
return payload.findGlobal({ slug: "cookie-settings" });
|
|
});
|