3.9 KiB
MoreminiMore tracking
Tracking is enabled in production builds and omitted from the Astro development server so local previews do not pollute production data. Production starts with every non-essential Google Consent Mode signal denied. No analytics, advertising, or recorder script is requested until ConsentOS emits the verified consentos:consent-change event with the corresponding accepted category.
Installed tools
- ConsentOS — the loader follows a non-networking denied-default bootstrap and runs before any tracking tag. Its
analyticscategory gates GA4, Umami, and the recorder;marketinggates Meta Pixel. - Google Analytics 4 — measurement ID
G-74BHREDLC3. - Meta Pixel — pixel ID
418349260078648, including PageView event IDs. - Umami Analytics — website ID
b2e87a6c-0b64-43c8-bb09-e406ffca0af1. - Umami Recorder — 15% sample rate, strict masking, five-minute maximum sessions.
.contact-formis excluded through both the recorder block selector and rrweb'srr-blockclass.
If a visitor withdraws analytics or marketing consent after a tag was loaded, the page reloads after ConsentOS stores the new choice. The reloaded page stays tag-free for the withdrawn category. The Meta noscript fallback is intentionally omitted because it cannot be safely consent-gated without JavaScript.
Events
| Event | Trigger | Properties |
|---|---|---|
page_view / PageView |
Each production page load | Automatic page data |
contact_clicked / Contact |
Phone, email, or LINE link | method, location |
service_selected / ViewContent |
Service landing-page link | service_path, location |
form_started |
First focus inside a contact form | form_location |
form_submitted / Lead |
Contact API confirms a successful submission | form_location, shared random event ID for Meta deduplication |
No names, phone numbers, email addresses, form values, or other personally identifiable information are included in these client-side events.
Contact-form tracking
Each page uses the same short contact form. form_started is emitted once on the first focus. The client creates a UUID event ID for each validated submission and sends a boolean snapshot of the already-applied ConsentOS state. The same ID is retained across network or ambiguous-response retries; it rotates only after confirmed success or an actual edit to the form contents. form_submitted and the Meta standard Lead browser event are emitted only after /api/contact returns success. The browser event contains only the page or service location and reuses the same event ID as Meta CAPI for deduplication.
The contact endpoint sends email through Amazon SES first. Only after SES succeeds:
- With marketing consent and
META_ACCESS_TOKEN, Meta CAPI receivesLead, the shared event ID, server IP/user agent, validated_fbp/_fbc, and normalized name/contact values hashed with SHA-256. Thai phone numbers are normalized to country code66before hashing. Raw form values are not sent to Meta. - With analytics consent,
GA4_API_SECRET, and a safely retrieved GA client ID, Google Measurement Protocol receivesform_submitted, session/context identifiers, explicit advertising consent state, and no PII, hashes, or user properties. The browser helper skips its GA copy to avoid a duplicate event; Umami still receives the PII-free event.
Provider requests have short timeouts and are handled with Promise.allSettled, so missing tokens, upstream errors, or timeouts never change a successful form response. There is no public conversion relay route. Event IDs are UUID-v4 validated and retained in a bounded 15-minute pending/completed registry. Concurrent pending requests receive a processing response; a retry of a completed delivery receives success without sending a second email, while failed SES attempts release the ID for retry. Delivery and provider logs contain status only and never include form values, credentials, tokens, or upstream response bodies.