You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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.
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.
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.
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.
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.
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 windowerror 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
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 onelets a reader slice the figures, get them without opening the page, take
them elsewhere, and feed them from places a browser tag cannot reach.
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
segmentset, beside the "all visits" record. The Traffic page gets asegment selector every widget follows, and a segment's record is
deleted when the segment is.
traffic.rollupOfsums the daily recordsof 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.
traffic.reportsnames 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.alertsnames 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.
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.
POST /api/traffic/serveraccepts the collector's envelope plus a
remoteAddressanduserAgentper batch or per event, guarded by a per-portal bearertoken that
occ portaliq:traffic:tokenmints and shows once (theportal keeps the hash).
occ portaliq:traffic:import-logreads anApache or Nginx access log (combined or JSON) as page views, skipping
assets and bots, through the same ingest step a beacon takes.
js_error(message, source filewithout its query string, line, column, stack hash; never the stack)
when the portal enabled it; the rollup carries
errors[]and aScript errors widget lists them.
Specs
Tasks
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.segmentset), stale segment records deleted;TrafficEventStore::findDailyRows,dailyBetween,deleteDaily.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.TrafficReportDefinitions(reports, alerts, roll-up members),TrafficReportPeriods(yesterday, the ISO week that ended, the previous month; the current day or week for anabovealert),TrafficReportNumbers(fold, metric, percent change).TrafficReportService: due once per period key, recorded in app config before delivery; alerts fire once per period;TrafficReportJobhourly.TrafficReportMail(subject, sections with each number against the period before, plain text) andTrafficReportDelivery(IMailer HTML template + plain, IUserManager address lookup, INotificationManager for user recipients);Notification\Notifierregistered inApplication.TrafficExport(CSV one row per portal-day-segment with the scalar metrics, JSON whole) andTrafficReportController::export(admin,NoCSRFRequiredfor the navigated download); the Export button on the overview.TrafficServerToken(mint withISecureRandom, sha256 stored on the portal,hash_equalsverify),occ portaliq:traffic:token <portal>shown once,TrafficController::server(401 on a wrong or missing token, per-eventremoteAddressanduserAgent).TrafficLogParser(combined and JSON, assets and bots skipped, UTC timestamps),TrafficLogImporter(per-visitor batches, duplicates within the import dropped,allowOldso the validator keeps old timestamps),occ portaliq:traffic:import-log <portal> <file> --format --host.js_erroronwindowerrorwith message, source without query, line, column, stack hash;TrafficErrorStatsanderrors[]on the rollup;TrafficErrorswidget.portal.traffic.segments,rollupOf,reports,alerts,serverToken;js_errorin 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.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.rollup-tilburg-venraywithrollupOf: [open-tilburg, open-venray].tests/e2e/traffic-reporting.spec.tson the throwaway instance, one test per scenario.Synced from
openspec/changes/portal-traffic-reportingby OpenSpec workflowApp:
portaliq