5.9 KiB
Umami Setup with Actual Club Name and Domain
Changes Made
Problem Solved
Previously, Umami created websites with:
- Name: "Fotbal Club (Dev)" (hardcoded)
- Domain: "localhost" (hardcoded)
Now it uses:
- Name: Actual club name from setup form
- Domain: Auto-detected from Host header (works with Cloudflare Tunnel!)
How It Works with Cloudflare Tunnel
When you route through Cloudflare Tunnel to a club's domain:
User → fotbalklub.cz → Cloudflare Tunnel → Your Local Backend
The HTTP request will have:
Host: fotbalklub.cz
The backend reads this header and creates the Umami website with the correct domain!
Implementation Details
Frontend (SetupPage.tsx):
- Calls
POST /api/v1/umami/initialize-setupduring step 3 - Sends:
{ "name": "SK Slavia Litomyšl" }(from club name field) - Domain is auto-detected by backend
Backend (umami_controller.go):
- New endpoint:
POST /api/v1/umami/initialize-setup - No authentication required (public, called during setup)
- Extracts domain from
c.Request.Hostheader - Removes port if present (
:8080→ ``) - Calls Umami API to create website
- Stores website ID in memory
Backend Flow:
// 1. Get club name from request
name := payload.Name // "SK Slavia Litomyšl"
// 2. Auto-detect domain from Host header
domain := c.Request.Host // "fotbalklub.cz" or "localhost:8080"
if i := strings.Index(domain, ":"); i >= 0 {
domain = domain[:i] // Remove port
}
// 3. Create Umami website
websiteID := umamiService.EnsureWebsite(name, domain)
Testing
1. Local Development Test
# Restart backend
go run main.go
# Open setup page
# Fill in club name: "Test Club"
# Complete setup
# Backend will create:
# Name: "Test Club"
# Domain: "localhost"
2. Cloudflare Tunnel Test
# Start Cloudflare tunnel
cloudflared tunnel --url http://localhost:8080
# Or with named tunnel:
cloudflared tunnel run <tunnel-name>
# Access via club domain (e.g., fotbalklub.cz)
# Fill in club name: "SK Slavia Litomyšl"
# Complete setup
# Backend will create:
# Name: "SK Slavia Litomyšl"
# Domain: "fotbalklub.cz"
3. Verify in Umami Dashboard
- Login to https://umami.tdvorak.dev
- Check websites list
- You should see the club's actual name and domain
4. Test via API
# After setup, check the website was created
$body = @{
username = "admin"
password = "eevRQ6h3G@!c#y4A1T"
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/auth/login" `
-Method Post `
-ContentType "application/json" `
-Body $body
$token = $response.token
$headers = @{ Authorization = "Bearer $token" }
$websites = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/websites" `
-Headers $headers
# Should show the new website with club name and domain
$websites.data | Format-Table name, domain, id
Environment Configuration
Your .env file should have:
# Umami Analytics
UMAMI_URL=https://umami.tdvorak.dev
UMAMI_USERNAME=admin
UMAMI_PASSWORD=eevRQ6h3G@!c#y4A1T
# Leave empty - will be auto-created during setup
UMAMI_WEBSITE_ID=
Important: No inline comments on UMAMI_WEBSITE_ID line!
Cloudflare Tunnel Setup
Quick Start
# Install cloudflared
# Windows: Download from https://github.com/cloudflare/cloudflared/releases
# Login to Cloudflare
cloudflared tunnel login
# Create tunnel
cloudflared tunnel create my-fotbal-club
# Configure tunnel (create config.yml):
tunnel: <tunnel-id>
credentials-file: C:\Users\<you>\.cloudflared\<tunnel-id>.json
ingress:
- hostname: fotbalklub.cz
service: http://localhost:8080
- service: http_status:404
# Create DNS record in Cloudflare dashboard:
# Type: CNAME
# Name: @ (or subdomain)
# Target: <tunnel-id>.cfargotunnel.com
# Run tunnel
cloudflared tunnel run my-fotbal-club
Testing the Tunnel
# Check if tunnel is working
curl https://fotbalklub.cz/api/v1/health
# Should return 200 OK
Files Modified
-
Frontend:
frontend/src/pages/SetupPage.tsx- Changed from
GET /umami/configtoPOST /umami/initialize-setup - Passes club name:
{ name: clubName } - Domain auto-detected by backend
- Changed from
-
Backend:
-
internal/controllers/umami_controller.go- Added
InitializeUmamiSetup()function - Auto-detects domain from
c.Request.Host - Removes port number
- Creates website with actual name and domain
- Added
-
internal/routes/routes.go- Added route:
POST /api/v1/umami/initialize-setup(public, no auth)
- Added route:
-
Benefits
- ✅ Correct club names in Umami dashboard
- ✅ Correct domains (not "localhost" in production)
- ✅ Works with Cloudflare Tunnel automatically
- ✅ No manual configuration needed
- ✅ Clean Umami dashboard with proper website names
Troubleshooting
Issue: Still showing "localhost"
Cause: Accessing via http://localhost:8080 directly
Fix: Access via Cloudflare Tunnel URL or set proper Host header
Issue: Website name still "Fotbal Club (Dev)"
Cause: Old website exists from previous setup Solution:
- Login to Umami dashboard
- Delete the old "Fotbal Club (Dev)" website
- Clear
.env:UMAMI_WEBSITE_ID= - Restart backend
- Run setup again
Issue: Domain includes port (e.g., "fotbalklub.cz:8080")
Cause: This shouldn't happen - the code strips ports Fix: Check the backend logs for the actual domain being used
Production Deployment Checklist
- Set up Cloudflare Tunnel
- Point club's domain to tunnel
- Verify
.envhasUMAMI_WEBSITE_ID=(empty) - Clear any old Umami websites in dashboard
- Run initial setup via club's domain
- Verify in Umami dashboard: correct name and domain
- Test tracking: visit pages and check Umami stats
Expected Result
After setup via https://fotbalklub.cz, Umami dashboard shows:
Name: SK Slavia Litomyšl
Domain: fotbalklub.cz
ID: <auto-generated-uuid>
Perfect! 🎉