Add Django site, Docker packaging, and beta/prod Gitea deploys.
Deploy Beta / unit-tests (push) Successful in 9s
Deploy Beta / docker (push) Successful in 17s
Deploy Beta / deploy-beta (push) Successful in 2m31s

Unignore site/ (was blocked by mkdocs /site rule), add compose/Docker/uv tooling, and split deploys so push to main goes to beta while prod stays manual.
This commit is contained in:
2026-08-08 07:32:55 -05:00
parent 7dca98bbf6
commit 1f7d78de64
204 changed files with 21662 additions and 70 deletions
+62
View File
@@ -0,0 +1,62 @@
from django.utils.crypto import get_random_string
from analytics.models import Attribution, UTMVisit
CORRELATION_COOKIE = "ms_cid"
class UTMTrackingMiddleware:
"""Capture UTM params into UTMVisit and stash a correlation id cookie."""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
cid = request.COOKIES.get(CORRELATION_COOKIE) or get_random_string(32)
request.utm_correlation_id = cid
params = request.GET
has_utm = any(params.get(k) for k in (
"utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"
))
if has_utm or params.get("utm_source"):
UTMVisit.objects.create(
correlation_id=cid,
path=request.path[:512],
referrer=(request.META.get("HTTP_REFERER") or "")[:1024],
utm_source=params.get("utm_source", "")[:128],
utm_medium=params.get("utm_medium", "")[:128],
utm_campaign=params.get("utm_campaign", "")[:128],
utm_term=params.get("utm_term", "")[:128],
utm_content=params.get("utm_content", "")[:128],
user_agent=(request.META.get("HTTP_USER_AGENT") or "")[:512],
)
response = self.get_response(request)
if CORRELATION_COOKIE not in request.COOKIES:
response.set_cookie(
CORRELATION_COOKIE,
cid,
max_age=60 * 60 * 24 * 30,
samesite="Lax",
)
return response
def attribute_lead_from_request(request, lead) -> Attribution | None:
cid = getattr(request, "utm_correlation_id", None) or request.COOKIES.get(
CORRELATION_COOKIE
)
visit = None
if cid:
visit = (
UTMVisit.objects.filter(correlation_id=cid).order_by("-created_at").first()
)
return Attribution.objects.create(
lead=lead,
visit=visit,
utm_source=visit.utm_source if visit else "",
utm_medium=visit.utm_medium if visit else "",
utm_campaign=visit.utm_campaign if visit else "",
)