diff --git a/backend/app/services/analytics.py b/backend/app/services/analytics.py index be0b494..3d34804 100644 --- a/backend/app/services/analytics.py +++ b/backend/app/services/analytics.py @@ -37,13 +37,12 @@ async def track(event: str, properties: dict[str, Any] | None = None, profile_id """Record a named event; swallows every error.""" if not _configured(): return - body = { - "type": "track", - "event": event, - "properties": properties or {}, - } + # OpenPanel's Track API takes {type, payload:{…}} (same envelope the browser SDK + # sends) — a flat body is rejected with 400, which this module swallows by design. + inner: dict[str, Any] = {"event": event, "properties": properties or {}} if profile_id: - body["profileId"] = profile_id + inner["profileId"] = profile_id + body = {"type": "track", "payload": inner} try: async with httpx.AsyncClient(timeout=_TIMEOUT) as client: await client.post( @@ -66,7 +65,7 @@ async def identify(profile_id: str, properties: dict[str, Any] | None = None) -> async with httpx.AsyncClient(timeout=_TIMEOUT) as client: await client.post( f"{settings.OPENPANEL_API_URL.rstrip('/')}/track", - json={"type": "identify", "profileId": profile_id, "properties": properties or {}}, + json={"type": "identify", "payload": {"profileId": profile_id, "properties": properties or {}}}, headers={ "openpanel-client-id": settings.OPENPANEL_CLIENT_ID, "openpanel-client-secret": settings.OPENPANEL_CLIENT_SECRET, diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 9530fbb..8b08a3e 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -23,9 +23,13 @@ ENV VITE_ENABLE_DEV_LOGIN=${DEV_LOGIN_ENABLED} # Empty values disable the feature (analytics.ts is a no-op then). ARG VITE_OPENPANEL_URL="" ARG VITE_OPENPANEL_CLIENT_ID="" +# The browser script (op1.js) lives on the dashboard origin, not under the API path, +# so it needs its own arg — defined here or the value never reaches the bundle. +ARG VITE_OPENPANEL_SCRIPT_URL="" ARG VITE_SENTRY_DSN="" ENV VITE_OPENPANEL_URL=${VITE_OPENPANEL_URL} \ VITE_OPENPANEL_CLIENT_ID=${VITE_OPENPANEL_CLIENT_ID} \ + VITE_OPENPANEL_SCRIPT_URL=${VITE_OPENPANEL_SCRIPT_URL} \ VITE_SENTRY_DSN=${VITE_SENTRY_DSN} # Source code + build