Skip to content
This repository was archived by the owner on Aug 11, 2026. It is now read-only.
This repository was archived by the owner on Aug 11, 2026. It is now read-only.

feat(visitor-analytics): collect admin and public visitor telemetry in middleware #620

Description

@ahliweb

Context

Issue #618 adds the visitor analytics schema and #619 adds the helper layer. This issue wires analytics collection into the request lifecycle.

AWCMS-Mini already uses src/middleware.ts as the request-level choke point for correlation ID propagation, security headers, admin route guarding, and SSR context resolution. Visitor analytics should hook into that flow carefully without making analytics writes a critical dependency for admin/public page rendering.

Objective

Collect lightweight visitor telemetry for admin and public requests, updating visitor presence and inserting visit events while preserving offline/LAN behavior and fail-open safety.

Scope

Modify:

  • src/middleware.ts

Add application service:

  • src/modules/visitor-analytics/application/collector.ts

Collector behavior:

  • Runs only when VISITOR_ANALYTICS_ENABLED=true.
  • Collects /admin/* when VISITOR_ANALYTICS_COLLECT_ADMIN=true.
  • Collects public page requests when VISITOR_ANALYTICS_COLLECT_PUBLIC=true.
  • Does not collect API requests unless VISITOR_ANALYTICS_COLLECT_API=true.
  • Skips static assets, build assets, health checks, and documentation/spec static files using helpers from feat(visitor-analytics): add visitor identity, user-agent, and human/bot classification helpers #619.
  • Resolves tenant for admin from the existing SSR context.
  • Resolves tenant for public routes using existing public tenant resolution/fallback behavior where available.
  • Creates or updates awcms_mini_visitor_sessions.
  • Inserts awcms_mini_visit_events.
  • Updates last_seen_at for presence.
  • Uses Astro.locals.correlationId or equivalent request correlation ID.
  • Uses parsed user-agent/device/browser fields from feat(visitor-analytics): add visitor identity, user-agent, and human/bot classification helpers #619.
  • Uses hashed visitor/IP identifiers by default.
  • Stores raw IP/user-agent only if explicitly enabled by visitor analytics config.

Recommended online presence rule:

last_seen_at >= now() - make_interval(secs => VISITOR_ANALYTICS_ONLINE_WINDOW_SECONDS)

Recommended write-throttle behavior:

  • Avoid updating the same visitor session on every request if the last update is very recent.
  • Use a small in-process or DB-safe guard if needed, but do not sacrifice correctness or tenant isolation.
  • Event insert can remain append-only; session update should be bounded.

Out of scope

  • Dashboard API endpoints.
  • Admin UI.
  • Online Cloudflare/geolocation enrichment beyond local/basic IP resolution.
  • Rollup/purge jobs.
  • Changing authentication behavior.

Acceptance criteria

  • Admin user opening /admin appears as active admin presence.
  • Public page visitor appears as active public presence.
  • Public/admin online counts can be derived from last_seen_at and area.
  • Static assets and internal paths are not counted as pageviews.
  • Collector failure is fail-open: request still returns the intended page/API response.
  • Collector errors are logged as warning with correlation ID and without sensitive data.
  • No request body, cookies, authorization headers, passwords, tokens, or raw query-string secrets are stored.
  • No external provider call is made from request collection.
  • Offline/LAN deployments work without internet and without extra provider credentials.
  • Existing admin auth behavior remains unchanged.
  • Tests cover admin route, public route, skipped asset, disabled config, and collector error path.
  • bun test passes.
  • bun run check passes.

Security and privacy notes

  • Analytics writes must never become a critical availability dependency.
  • Raw visitor detail must remain controlled by explicit config and later read permission.
  • Public anonymous visitors must not receive a login identifier snapshot.
  • Do not mutate auth/session semantics except where strictly necessary to observe authenticated state.
  • Ensure tenant context is always set before tenant-scoped analytics writes.

Dependencies

Depends on #617, #618, and #619.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions