feat: add optional matomo tracking for pageviews and download

This commit is contained in:
2026-03-03 09:57:29 +00:00
parent 0d7ae8bbb7
commit 2f79c9e650
6 changed files with 95 additions and 7 deletions

View File

@@ -8,3 +8,9 @@ PDF_TO_ICS_IMAGE=git.file-archive.de/webfarben/pdf_to_ics:v1.2.2
# Optional: App-interne Basic Auth (leer = deaktiviert)
WEB_AUTH_USER=
WEB_AUTH_PASSWORD=
# Optional: Matomo Tracking
# Beispiel: MATOMO_URL=https://matomo.example.de
# Beispiel: MATOMO_SITE_ID=5
MATOMO_URL=
MATOMO_SITE_ID=

View File

@@ -75,6 +75,23 @@ WEB_AUTH_PASSWORD=BitteSicheresPasswortSetzen
Für öffentliches Deployment zusätzlich Reverse Proxy + HTTPS verwenden.
## Matomo (optional)
Für Zugriffsstatistiken kannst du Matomo direkt aktivieren:
```dotenv
MATOMO_URL=https://matomo.example.de
MATOMO_SITE_ID=5
```
Dann neu deployen:
```bash
./update.sh
```
Wenn beide Variablen gesetzt sind, trackt die App Seitenaufrufe auf Landing/App sowie ein Event für den ICS-Download.
## Schlanker Server-Checkout (Sparse)
```bash

View File

@@ -17,6 +17,9 @@ services:
# Optional aktivieren für App-Login:
- WEB_AUTH_USER=${WEB_AUTH_USER:-}
- WEB_AUTH_PASSWORD=${WEB_AUTH_PASSWORD:-}
# Optional Matomo-Tracking:
- MATOMO_URL=${MATOMO_URL:-}
- MATOMO_SITE_ID=${MATOMO_SITE_ID:-}
healthcheck:
test: ["CMD", "python3", "-c", "import http.client,sys;c=http.client.HTTPConnection('127.0.0.1',8000,timeout=5);c.request('GET','/');r=c.getresponse();sys.exit(0 if r.status in (200,401) else 1)"]
interval: 30s

View File

@@ -29,6 +29,22 @@ app.mount("/static", StaticFiles(directory=str(Path(__file__).parent / "static")
security = HTTPBasic()
def get_matomo_context():
matomo_url = (os.getenv("MATOMO_URL") or "").strip().rstrip("/")
matomo_site_id = (os.getenv("MATOMO_SITE_ID") or "").strip()
if not matomo_url or not matomo_site_id:
return {
"matomo_url": None,
"matomo_site_id": None,
}
return {
"matomo_url": matomo_url,
"matomo_site_id": matomo_site_id,
}
def require_auth(credentials: HTTPBasicCredentials = Depends(security)):
expected_user = os.getenv("WEB_AUTH_USER")
expected_password = os.getenv("WEB_AUTH_PASSWORD")
@@ -48,22 +64,28 @@ def require_auth(credentials: HTTPBasicCredentials = Depends(security)):
@app.get("/", response_class=HTMLResponse)
def landing(request: Request):
context = {
"request": request,
}
context.update(get_matomo_context())
return templates.TemplateResponse(
"landing.html",
{
"request": request,
},
context,
)
@app.get("/app", response_class=HTMLResponse)
def index(request: Request, _: None = Depends(require_auth)):
return templates.TemplateResponse(
"index.html",
{
context = {
"request": request,
"error": None,
},
}
context.update(get_matomo_context())
return templates.TemplateResponse(
"index.html",
context,
)

View File

@@ -159,6 +159,22 @@
to { transform: rotate(360deg); }
}
</style>
{% if matomo_url and matomo_site_id %}
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u = '{{ matomo_url }}/';
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '{{ matomo_site_id }}']);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true;
g.src = u + 'matomo.js';
s.parentNode.insertBefore(g, s);
})();
</script>
{% endif %}
</head>
<body>
<main class="wrap">
@@ -230,6 +246,12 @@
</main>
<script>
function trackMatomoEvent(category, action, name) {
if (window._paq && Array.isArray(window._paq)) {
window._paq.push(['trackEvent', category, action, name]);
}
}
let currentFile = null;
let currentFilename = null;
@@ -334,6 +356,8 @@
window.URL.revokeObjectURL(url);
a.remove();
trackMatomoEvent("pdf_to_ics", "download", "ics_export");
resetForm();
} catch (error) {
showError(`Fehler: ${error.message}`);

View File

@@ -87,6 +87,22 @@
color: #4b5563;
}
</style>
{% if matomo_url and matomo_site_id %}
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u = '{{ matomo_url }}/';
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '{{ matomo_site_id }}']);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true;
g.src = u + 'matomo.js';
s.parentNode.insertBefore(g, s);
})();
</script>
{% endif %}
</head>
<body>
<main class="wrap">