Add public PageView tracking for portal analytics (#4)
Deploy Beta / unit-tests (push) Successful in 12s
Deploy Beta / docker (push) Successful in 22s
Deploy Beta / deploy-beta (push) Successful in 5m40s

## Summary
Closes #3.

- Add `PageView` model + migration for successful public marketing GET hits
- Wire `PublicPageViewMiddleware` (skips portal/admin/accounts/api/static/health/etc.; fails soft on DB errors)
- Portal analytics report: last-30-day views + top pages table
- Admin registration and tests

## Test plan
- [ ] Apply migration `analytics.0002_pageview`
- [ ] Hit `/` and `/about/` → rows in `PageView` / admin
- [ ] Hit `/healthz/`, `/portal/`, `/admin/` → no new pageviews
- [ ] Open portal Analytics → views count + Top pages look right
- [ ] `uv run python site/manage.py test analytics.tests`

Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
2026-08-20 03:34:56 -07:00
parent 30ce58e610
commit 46abaa6917
9 changed files with 234 additions and 7 deletions
+15
View File
@@ -4,6 +4,21 @@ from core.models import TimeStampedModel, UUIDPrimaryKeyModel
from leads.models import Lead
class PageView(UUIDPrimaryKeyModel, TimeStampedModel):
"""One successful GET of a public marketing page."""
path = models.CharField(max_length=512, db_index=True)
class Meta:
ordering = ["-created_at"]
indexes = [
models.Index(fields=["created_at", "path"]),
]
def __str__(self) -> str:
return self.path or "/"
class UTMVisit(UUIDPrimaryKeyModel, TimeStampedModel):
correlation_id = models.CharField(max_length=64, db_index=True)
path = models.CharField(max_length=512, blank=True)