CI / test (pull_request) Successful in 13s
Closes #3 — record successful public GET hits, show last-30-day views and top pages on the analytics report, and keep portal/admin/API paths out of the counts.
80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
from datetime import timedelta
|
|
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.db.models import Count
|
|
from django.shortcuts import render
|
|
from django.utils import timezone
|
|
|
|
from analytics.models import Attribution, PageView, UTMVisit
|
|
|
|
|
|
def _bar_pct(rows, key="count"):
|
|
max_count = max((row[key] for row in rows), default=1) or 1
|
|
for row in rows:
|
|
row["bar_pct"] = max(12, int(100 * row[key] / max_count))
|
|
return rows
|
|
|
|
|
|
@login_required
|
|
def report(request):
|
|
since_30d = timezone.now() - timedelta(days=30)
|
|
pageviews_qs = PageView.objects.filter(created_at__gte=since_30d)
|
|
pageviews_last_30_days = pageviews_qs.count()
|
|
top_pages = list(
|
|
pageviews_qs.values("path").annotate(count=Count("id")).order_by("-count")[:20]
|
|
)
|
|
|
|
visits_by_source = _bar_pct(
|
|
list(
|
|
UTMVisit.objects.values("utm_source")
|
|
.annotate(count=Count("id"))
|
|
.order_by("-count")[:20]
|
|
)
|
|
)
|
|
visits_by_combo = list(
|
|
UTMVisit.objects.values("utm_source", "utm_medium", "utm_campaign")
|
|
.annotate(count=Count("id"))
|
|
.order_by("-count")[:50]
|
|
)
|
|
top_visit = visits_by_source[0] if visits_by_source else None
|
|
top_visit_campaign = (
|
|
UTMVisit.objects.exclude(utm_campaign="")
|
|
.values("utm_campaign")
|
|
.annotate(count=Count("id"))
|
|
.order_by("-count")
|
|
.first()
|
|
)
|
|
|
|
leads_by_source = _bar_pct(
|
|
list(
|
|
Attribution.objects.values("utm_source")
|
|
.annotate(count=Count("id"))
|
|
.order_by("-count")[:20]
|
|
)
|
|
)
|
|
leads_by_combo = list(
|
|
Attribution.objects.values("utm_source", "utm_medium", "utm_campaign")
|
|
.annotate(count=Count("id"))
|
|
.order_by("-count")[:50]
|
|
)
|
|
|
|
recent_visits = UTMVisit.objects.all()[:25]
|
|
|
|
return render(
|
|
request,
|
|
"analytics/report.html",
|
|
{
|
|
"pageviews_last_30_days": pageviews_last_30_days,
|
|
"top_pages": top_pages,
|
|
"total_visits": UTMVisit.objects.count(),
|
|
"total_attributed": Attribution.objects.count(),
|
|
"top_source": (top_visit or {}).get("utm_source") or "(direct)",
|
|
"top_campaign": (top_visit_campaign or {}).get("utm_campaign") or "—",
|
|
"visits_by_source": visits_by_source,
|
|
"visits_by_combo": visits_by_combo,
|
|
"leads_by_source": leads_by_source,
|
|
"leads_by_combo": leads_by_combo,
|
|
"recent_visits": recent_visits,
|
|
},
|
|
)
|