Files
mintel.me/apps/web/src/domain/umami-payload.ts
T
mmintel a54df524c7
Build & Deploy / 🔍 Prepare (push) Successful in 5s
Build & Deploy / 🏗️ Build (push) Successful in 6m31s
Build & Deploy / 🚀 Deploy (push) Successful in 19s
Build & Deploy / 🩺 Smoke Test (push) Successful in 5s
Build & Deploy / 🔔 Notify (push) Successful in 2s
feat(analytics): record pageviews server-side only
Umami never received data: the client-side path (browser beacon to
/stats/api/send) has been dead in production. Pageviews are now
classified and recorded entirely on the server in the request proxy;
no tracking script ships to the browser anymore.

- Pure domain decision (decidePageview) filters real page views from
  assets, infrastructure paths, prefetches and bot user agents
- Pure payload builder maps facts onto the Umami send contract as an
  unnamed event, with the client identity travelling in headers
- proxy.ts wires request facts into the domain and fires the send
  without delaying the response; configured via UMAMI_WEBSITE_ID and
  UMAMI_API_ENDPOINT
- Removes the dead client analytics stack (components, adapters,
  /stats proxy route) and its layout mount
2026-10-04 12:24:13 +02:00

36 lines
866 B
TypeScript

/**
* Maps page view facts onto the Umami /api/send contract.
* A page view is an unnamed event: no `name`, no `data`.
* The client identity (user agent, IP) travels as request headers, not in
* the payload — see src/analytics/recordPageviewToUmami.ts.
*/
import type { PageviewFacts } from "./pageview-decision";
export type UmamiSendBody = {
readonly type: "event";
readonly payload: {
readonly website: string;
readonly hostname: string;
readonly language: string;
readonly referrer: string;
readonly url: string;
};
};
export function buildUmamiPageviewBody(
facts: PageviewFacts,
websiteId: string,
): UmamiSendBody {
return {
type: "event",
payload: {
website: websiteId,
hostname: facts.hostname,
language: facts.language,
referrer: facts.referrer,
url: facts.url,
},
};
}