Skip to content

[OpenSpec] portal-traffic-reporting #447

Description

@github-actions

⚠️ OpenSpec-managed issue — this content is automatically synced
from the openspec/ directory. Manual edits will be overwritten on next sync.

Artifacts

Summary

Phase 4a of portal traffic analytics (phase 0: portal-traffic-analytics,
phase 1: portal-traffic-visitors-and-geo, phase 3:
portal-traffic-outcomes). The earlier phases count and judge; this one
lets a reader slice the figures, get them without opening the page, take
them elsewhere, and feed them from places a browser tag cannot reach.

  1. Segments. A portal saves filters over visits in traffic.segments
    (a device type, a channel, a region, a campaign, whether a goal was
    met). The aggregation writes one extra daily record per segment, with
    segment set, beside the "all visits" record. The Traffic page gets a
    segment selector every widget follows, and a segment's record is
    deleted when the segment is.
  2. Roll-ups. A portal with traffic.rollupOf sums the daily records
    of the portals it names, computed after theirs. It never has visitors
    of its own: the collector refuses its events. The page says "Roll-up
    of N portals" so a reader knows the visitors are a sum.
  3. Scheduled reports and alerts. traffic.reports names reports
    (daily, weekly, monthly) sent by mail, HTML and plain text, with the
    period's figures against the period before and a link to the Traffic
    page; traffic.alerts names thresholds (above, below, percent change)
    that fire once per day or week. An hourly job decides what is due; a
    Nextcloud user also gets an in-app notification, rendered by this
    app's Notifier.
  4. Reporting API and export. The daily records are documented as the
    read API, and GET /api/traffic/export (admin) downloads them as CSV
    (one row per portal-day-segment, the scalar metrics) or JSON. The
    Traffic page's Export button downloads exactly what the page shows.
  5. Server-side tracking and log import. POST /api/traffic/server
    accepts the collector's envelope plus a remoteAddress and
    userAgent per batch or per event, guarded by a per-portal bearer
    token that occ portaliq:traffic:token mints and shows once (the
    portal keeps the hash). occ portaliq:traffic:import-log reads an
    Apache or Nginx access log (combined or JSON) as page views, skipping
    assets and bots, through the same ingest step a beacon takes.
  6. Script errors. The client sends js_error (message, source file
    without its query string, line, column, stack hash; never the stack)
    when the portal enabled it; the rollup carries errors[] and a
    Script errors widget lists them.

Specs

Tasks

  • 1.1 TrafficSegments: definitions (unknown dimension or operator refused at configuration time), per-session matching (is, isNot, contains, startsWith, AND-combined; visitorType, userRef-present, goal:<id> derived), filter; unit tests per operator.
  • 1.2 Aggregation: one record per portal-day for all visits plus one per segment (segment set), stale segment records deleted; TrafficEventStore::findDailyRows, dailyBetween, deleteDaily.
  • 1.3 TrafficRollupSum: a roll-up portal's day as the sum of its members' "all visits" records, merged by key, rates re-derived; computed after the ordinary portals; the ingest refuses a roll-up portal's events (rollup-portal); unit tests for the sums, no double count, a member without data.
  • 1.4 Store and page: segment selector on the overview, every widget reads the selected segment's rows; "Roll-up of N portals" note.
  • 2.1 TrafficReportDefinitions (reports, alerts, roll-up members), TrafficReportPeriods (yesterday, the ISO week that ended, the previous month; the current day or week for an above alert), TrafficReportNumbers (fold, metric, percent change).
  • 2.2 TrafficReportService: due once per period key, recorded in app config before delivery; alerts fire once per period; TrafficReportJob hourly.
  • 2.3 TrafficReportMail (subject, sections with each number against the period before, plain text) and TrafficReportDelivery (IMailer HTML template + plain, IUserManager address lookup, INotificationManager for user recipients); Notification\Notifier registered in Application.
  • 2.4 Unit tests: due-ness, the mail's numbers, an alert that fires once per period and again the next, the delivery per recipient kind.
  • 3.1 TrafficExport (CSV one row per portal-day-segment with the scalar metrics, JSON whole) and TrafficReportController::export (admin, NoCSRFRequired for the navigated download); the Export button on the overview.
  • 3.2 TrafficServerToken (mint with ISecureRandom, sha256 stored on the portal, hash_equals verify), occ portaliq:traffic:token <portal> shown once, TrafficController::server (401 on a wrong or missing token, per-event remoteAddress and userAgent).
  • 3.3 TrafficLogParser (combined and JSON, assets and bots skipped, UTC timestamps), TrafficLogImporter (per-visitor batches, duplicates within the import dropped, allowOld so the validator keeps old timestamps), occ portaliq:traffic:import-log <portal> <file> --format --host.
  • 3.4 Client: js_error on window error with message, source without query, line, column, stack hash; TrafficErrorStats and errors[] on the rollup; TrafficErrors widget.
  • 3.5 Schemas: portal.traffic.segments, rollupOf, reports, alerts, serverToken; js_error in the event enums; portalTrafficDaily.segment, rollupOf, members, errors; versions bumped (register 0.20.0, portal 0.5.0, portalTrafficDaily 0.4.0, portalTrafficEvent 0.3.0); every new string catalogued.
  • 4.1 docs/operations/traffic-analytics.md: segments, roll-ups, reports, alerts, the read API and the export, the server API and the token, the log import, script errors.
  • 4.2 Seed: a third portal rollup-tilburg-venray with rollupOf: [open-tilburg, open-venray].
  • 4.3 E2E tests/e2e/traffic-reporting.spec.ts on the throwaway instance, one test per scenario.

Synced from openspec/changes/portal-traffic-reporting by OpenSpec workflow
App: portaliq

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions