diff --git a/requirements.txt b/requirements.txt index d72ab2a..af2f01e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,7 @@ fastapi[standard]~=0.111.0 requests~=2.32.0 starlette~=0.37.2 -uvicorn~=0.31.0 \ No newline at end of file +uvicorn~=0.31.0 +httpx~=0.27.0 +PyYAML~=6.0.1 +user-agents~=2.2.0 \ No newline at end of file diff --git a/src/middleware/plausible_analytics.py b/src/middleware/plausible_analytics.py new file mode 100644 index 0000000..32a8cd6 --- /dev/null +++ b/src/middleware/plausible_analytics.py @@ -0,0 +1,42 @@ +import httpx +import yaml + +from user_agents import parse as ua_parse + +config = yaml.safe_load(open('../config.yaml')) + +class PlausibleAnalytics: + async def __call__(self, request, call_next): + response = await call_next(request) + + user_agent = request.headers.get('user-agent', 'unknown') + user_agent_parsed = ua_parse(user_agent) + + event = { + "domain": config['analytics']['domain'], + "name": request.url.path or '404 - Not Found', + "url": str(request.url), + "props": { + "method": request.method, + "statusCode": response.status_code, + "browser": f"{user_agent_parsed.browser.family} {user_agent_parsed.browser.version_string}", + "os": f"{user_agent_parsed.os.family} {user_agent_parsed.os.version_string}", + "source": request.headers.get('referer', 'direct'), + }, + } + + async with httpx.AsyncClient() as client: + try: + await client.post( + config['analytics']['endpoint'], + json=event, + headers={ + "Authorization": f"Bearer {config['analytics']['token']}", + "Content-Type": "application/json", + "User-Agent": request.headers.get('user-agent', 'unknown'), + }, + ) + except Exception as e: + print(f"Error sending event to Plausible: {e}") + + return response \ No newline at end of file