Update registration metrics¶
Note
Canonical source: guides/UPDATE_REGISTRATION_METRICS.md. Transcluded here for
the docs site. Edit the source file if anything is wrong.
with a New Convention Year
Run this at the end of each convention year (after the event is over and registration
is final) so the year-over-year comparison charts in register-metrics2 include the
just-finished event as a historical line.
The metrics dashboard compares the current (live) year against previous years of static reference data. Adding a finished year is a two-part change: (1) generate the reference JSON, and (2) tell the frontend to render it.
Prerequisites¶
A shell on a machine that can reach the database for the event you’re exporting (typically the server, or a local dev checkout pointed at the right DB).
The Python virtualenv active: commands below use
./.venv/bin/python.
1. Identify the event slug¶
The export is keyed by the Event.slug (its primary key).
./.venv/bin/python manage.py shell -c "from event.models import Event; print([e.slug for e in Event.objects.all()])"
Pick the slug of the event that just finished.
2. Export the year’s timeline¶
This regenerates the reference data in the exact format the charts consume:
{year}.json->[[dayIndexSinceOpened, perDayCount, cumulativeCount], ...]{year}-d.json->[["MM-DD", perDayCount, cumulativeCount], ...]
./.venv/bin/python manage.py register__export_reg_timeline \
--event <slug> \
--year <YYYY> \
--output-dir .examples/previous-years-reg-data \
--rebuild-combined
--yeardefaults to the year of the first registration; set it explicitly to label by the convention year (e.g.--year 2025).--rebuild-combinedregeneratesallPreviousYears.jsonandallPreviousYears-date.json(the files the app actually reads), ordered by year.Defaults to all registrations (matches the live unfiltered chart). Add
--paid-onlyif you only want paid registrations.
3. Put the files where the app reads them¶
The combined files must live on disk at ui/public/data/previous-years/. The app
serves that folder at the URL /static/ui/data/previous-years/ (that’s the path the
frontend requests), so don’t change where the files are placed.
Either copy them over from the template dir:
cp .examples/previous-years-reg-data/allPreviousYears.json ui/public/data/previous-years/
cp .examples/previous-years-reg-data/allPreviousYears-date.json ui/public/data/previous-years/
…or skip step 2’s copy entirely by exporting straight into the app assets:
./.venv/bin/python manage.py register__export_reg_timeline \
--event <slug> --year <YYYY> \
--output-dir ui/public/data/previous-years --rebuild-combined
4. Register the new year in the component¶
Open ui/src/app/apps/register/register-metrics2/register-metrics2.component.ts and
append the new year to the previousYears array, keeping it ascending:
private readonly previousYears: number[] = [2021, 2022, 2023, 2024, 2025];
This array’s order must match the combined file’s year order. Since --rebuild-combined
writes years sorted ascending, just keep the array ascending too.
5. Rebuild the frontend¶
The JSON lives under ui/public/, so it’s only picked up after a frontend build.
# Dev
export MIDSUMMER_PROD=false && ./render-ui-elements.sh && ./render-tenant-ui-elements.sh && ./entrypoint.sh
# Production
export MIDSUMMER_PROD=true && ./render-ui-elements.sh && ./render-tenant-ui-elements.sh && ./entrypoint.sh
6. Verify¶
Open Register → System → Metrics2 (route /app/register/system/metrics). The newly added
year should appear as a line on both:
Year-over-Year: Cumulative by Days Since Registration Opened
Year-over-Year: Cumulative by Calendar Date
The current (in-progress) year is always pulled live from the backend and rendered in blue.
Gotchas¶
Array order matters. The combined file’s outer array is ordered by year (index 0 = the earliest year). The component maps index ->
previousYears[index]. If the two fall out of sync, years will be mislabeled. Keep both ascending.The current year is never in these files. Only completed years belong in the reference data. The current cycle is read live; once it’s done, export it and it becomes a historical line for next year.
Timezone. The export groups days using Django’s default timezone, the same way the live metrics view does, so current-year and previous-year lines stay aligned. Don’t “fix” this by switching the export to the event timezone — it would desynchronize the two.
Rebuild is required. Updating the JSON without rebuilding the frontend will not show the new year.
No database changes. The command is read-only against registrations and only writes JSON files — safe to re-run any time.