mirror of
https://github.com/fosrl/docs-v2.git
synced 2026-09-30 17:59:10 +02:00
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
/**
|
|
* Browser helpers for docs feedback. The visitor id is an anonymous random id kept in
|
|
* localStorage so a person can change their vote; nothing else identifies them.
|
|
*/
|
|
const VisitorKey = 'pg-visitor-id';
|
|
|
|
export function randomId() {
|
|
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) return crypto.randomUUID();
|
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
|
|
}
|
|
|
|
let fallbackVisitorId: string | undefined;
|
|
|
|
export function getVisitorId() {
|
|
try {
|
|
let id = localStorage.getItem(VisitorKey);
|
|
if (!id) {
|
|
id = randomId();
|
|
localStorage.setItem(VisitorKey, id);
|
|
}
|
|
return id;
|
|
} catch {
|
|
// storage unavailable (private mode): one id per page load
|
|
return (fallbackVisitorId ??= randomId());
|
|
}
|
|
}
|
|
|
|
export type Vote = -1 | 0 | 1;
|
|
|
|
/** fire-and-forget; analytics must never break the page */
|
|
export function sendEvent(url: string, body: Record<string, unknown>) {
|
|
void fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ ...body, visitorId: getVisitorId() }),
|
|
keepalive: true,
|
|
}).catch(() => undefined);
|
|
}
|
|
|
|
export function sendFeedback(kind: 'page' | 'message', body: Record<string, unknown>) {
|
|
sendEvent(`/api/feedback/${kind}`, body);
|
|
}
|