Files
astro-website/openspec/changes/archive/2026-02-10-custom-events-umami/design.md
Santhosh Janardhanan af112a713c
Some checks failed
ci / site (push) Has been cancelled
Initial commit - but way too late.
2026-02-10 00:22:18 -05:00

4.0 KiB

Context

The site currently tracks a limited set of Umami custom events (CTAs and outbound links). This change expands measurement so every clickable item can be uniquely identified and analyzed in Umami, with a consistent set of event properties across pages.

We need this to understand what users do on the site (what they click, where they go) and to support iteration on acquisition/conversion.

Constraints:

  • Tracking must be safe when analytics is disabled or misconfigured (no runtime errors).
  • Tracking should not block navigation or degrade performance.
  • We should avoid collecting PII; event properties should be categorical/structural (ids, placements, destinations).

Goals / Non-Goals

Goals:

  • Define a site-wide click tracking taxonomy for unique identification of click targets.
  • Ensure every clickable item (at minimum: links and buttons) emits a Umami custom event with a unique, consistent set of properties.
  • Keep the instrumentation low-friction: adding a new clickable should require adding a small, predictable set of data attributes.
  • Preserve existing CTA and outbound tracking semantics, but align them with the taxonomy so dashboards can segment consistently.

Non-Goals:

  • Deep product analytics (funnels, sessions, heatmaps) beyond Umami custom events.
  • Tracking form input content or any user-provided personal data.
  • Implementing a server-side analytics proxy.

Decisions

1) Centralized click listener with data attributes

Decision: Keep a single document-level click handler (event delegation) that inspects the clicked element and its ancestors for tracking metadata (data attributes).

Rationale: Minimizes per-component JS and avoids hydration. It is robust for both static and dynamically inserted content and does not require wiring on every component.

Alternatives considered:

  • Per-component tracking calls: more code duplication and higher chance of missed instrumentation.
  • Framework-level router hooks: not applicable for a static-first site and does not cover outbound navigation.

2) Taxonomy: stable ids + placement + destination

Decision: Standardize on a minimal required property set for every tracked click:

  • action (event name or action type; e.g., click)
  • target_id (stable identifier for the clickable element; unique within the site)
  • placement (where it appears; e.g., nav, hero, section_header, content_card)
  • target_url (destination URL for links; optional for buttons)
  • Optional: target_domain, source (youtube/podcast/instagram for content cards), label

Rationale: This allows segmentation by page region and click target, and provides "where users are going" without needing full URL logging everywhere.

3) Event naming strategy

Decision: Use a primary generic event name for click tracking (e.g., click) and reserve specialized event names (e.g., cta_click) only when they provide value or already exist.

Rationale: A single event name makes dashboards simpler. Specialized names can be preserved for backwards compatibility, but taxonomy properties must be consistent either way.

4) Uniqueness rules

Decision: Require every clickable item to define a stable target_id that is unique across the site (or unique within a namespace) and deterministic between builds.

Rationale: Prevents ambiguous metrics and supports comparing performance over time.

5) Safety and performance

Decision: Tracking MUST be best-effort:

  • Never throw errors if window.umami is missing
  • Never block navigation (no awaited network calls)
  • Avoid attaching large payloads; keep properties small and categorical

Risks / Trade-offs

  • [Over-instrumentation complexity] -> Provide a clear taxonomy and reusable helpers/components for common clickables.
  • [Inconsistent ids] -> Document required id rules and add simple lint/test checks later (optional).
  • [Umami limitations] -> Keep properties to a small set and ensure they map cleanly to Umami filters.
  • [Privacy concerns] -> Prohibit PII in event properties; prefer domains/ids over full URLs where appropriate.