# Umami Website Creation Fix ## Problem The Umami tracking website creation was not working properly because: 1. The auto-creation wasn't being triggered during initial setup 2. No frontend UI existed to manually trigger website creation if needed ## Solution ### Automatic Creation During Setup The initial setup process now automatically creates the Umami website: - When you complete the setup wizard, it fetches `/umami/config` - Backend detects that UMAMI credentials are in `.env` but no UMAMI_WEBSITE_ID exists - Backend automatically creates the website using the domain from your site - Analytics tracking starts working immediately ### Manual Creation (Backup Option) Added a new "Umami Analytics" tab to the Settings Admin Page that allows: - Viewing current Umami configuration status - Manually creating a new Umami website with custom name and domain - Refreshing the Umami configuration ## Changes Made ### Frontend Changes **File: `frontend/src/pages/SetupPage.tsx`** Added automatic Umami initialization during setup: ```typescript // Step 3: Initialize Umami Analytics (auto-create website) setSetupProgress('Konfiguruji analytiku...'); try { // Trigger Umami config fetch - backend will auto-create website if credentials are present const axios = (await import('axios')).default; const apiUrl = (API_URL || '').replace(/\/$/, ''); await axios.get(`${apiUrl}/umami/config`); console.log('Umami analytics initialized'); } catch (err) { console.warn('Umami initialization failed (non-critical):', err); } ``` **File: `frontend/src/pages/admin/SettingsAdminPage.tsx`** 1. Added new imports: - `import api from '../../services/api';` 2. Added new state variables: ```typescript const [umamiWebsiteId, setUmamiWebsiteId] = useState(''); const [umamiDomain, setUmamiDomain] = useState(''); const [umamiName, setUmamiName] = useState(''); const [umamiInitializing, setUmamiInitializing] = useState(false); const [umamiConfig, setUmamiConfig] = useState(null); ``` 3. Added `fetchUmamiConfig()` function to load current Umami status 4. Added "Umami Analytics" tab to the settings page with: - Status indicator (green for active, yellow for not configured) - Form fields for website name and domain - "Create Website" button that calls `/admin/umami/initialize` - "Refresh Status" button to reload configuration ## Backend API ### Authentication with Token Verification **File: `internal/services/umami_service.go`** The backend implements smart token management: 1. **Initial Authentication** (`POST /api/auth/login`) - Sends username and password in JSON format (from `.env`) - Receives JWT token with 24-hour expiration - Stores token with expiration timestamp 2. **Token Verification** (twice daily - every 12 hours) - Uses `POST /api/auth/verify` endpoint - Checks if existing token is still valid - Only re-authenticates if verification fails - Reduces unnecessary login requests 3. **Automatic Re-authentication** - If token expires or verification fails - Automatically gets a new token - Seamless for the application **Token Lifecycle:** ``` Initial: Login → Get Token (valid 24h) After 12h: Verify Token → Still valid? Continue using it After 24h: Token expired → Re-authenticate → Get new token ``` All API calls use: `Authorization: Bearer ` header ### Website Creation Endpoint **Endpoint:** `POST /admin/umami/initialize` **File:** `internal/controllers/umami_controller.go` Request body: ```json { "name": "Your Club Name", "domain": "yourclub.example.com" } ``` Response (success): ```json { "message": "Umami initialized successfully", "website_id": "abc123-def456-...", "script_url": "https://umami.tdvorak.dev/script.js" } ``` ## Testing Instructions ### 1. Verify Environment Variables Your `.env` file already has the correct credentials (they don't change): ```env UMAMI_URL=https://umami.tdvorak.dev UMAMI_USERNAME=admin UMAMI_PASSWORD=eevRQ6h3G@!c#y4A1T UMAMI_WEBSITE_ID= # Leave empty - will be auto-created during setup ``` **Important:** These credentials are permanent and don't need to be modified. ### 2. Run Initial Setup 1. Navigate to `/setup` route 2. Complete the setup wizard (club info, admin account, etc.) 3. During setup, you'll see: **"Konfiguruji analytiku..."** (Configuring analytics) 4. Backend automatically creates Umami website using your domain 5. Setup completes and analytics are ready! ### 3. Verify Umami is Working After setup, check the analytics: 1. Login to admin panel 2. Navigate to **Settings** → **Umami Analytics** tab 3. You should see green status: **"✓ Umami je aktivní"** 4. Website ID should be displayed ### 4. Manual Creation (If Needed) If auto-creation didn't work during setup, you can manually create: 1. Navigate to **Settings** → **Umami Analytics** tab 2. Fill in the form: - **Name**: Your club name - **Domain**: Your website domain 3. Click "Vytvořit webovou stránku" (Create Website) 4. Success message will show the Website ID ### 4. Verify via API (PowerShell) You can also verify directly with PowerShell: ```powershell # Login to get token $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 Write-Output "Token: $token" # List websites to verify creation $headers = @{ Authorization = "Bearer $token" } $websites = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/websites" ` -Headers $headers ` -Method Get $websites.data ``` ### 5. Website ID Persistence The Website ID is stored in-memory by the backend after auto-creation. To make it permanent across server restarts: **Option 1: Let it auto-create on each restart** (Recommended) - Leave `UMAMI_WEBSITE_ID=` empty in `.env` - Backend checks if website exists and reuses it (or creates new one if missing) - Works seamlessly **Option 2: Store Website ID in .env** - Copy the Website ID from Settings → Umami Analytics tab - Add to `.env`: `UMAMI_WEBSITE_ID=abc123-def456-...` - Restart backend server - Backend will use this ID directly without checking/creating ## How It Works ### Frontend Flow 1. User opens Settings → Umami Analytics tab 2. `fetchUmamiConfig()` is called on page load 3. Backend checks if `UMAMI_WEBSITE_ID` is set 4. If not set and credentials are available, backend may auto-create on first request 5. User can manually create via the UI by clicking "Create Website" 6. Frontend calls `POST /admin/umami/initialize` with name and domain 7. Backend authenticates with Umami and creates the website 8. Backend returns the Website ID 9. Frontend displays success and refreshes the configuration ### Backend Flow 1. Receives request at `/admin/umami/initialize` 2. Validates request payload (name and domain required) 3. Calls `umamiService.authenticate()`: - POST to Umami `https://umami.tdvorak.dev/api/auth/login` - Payload: `{"username": "admin", "password": "..."}` - Receives JWT token 4. Calls `umamiService.EnsureWebsite()`: - First checks if website exists: GET `/api/websites?query={domain}` - If exists, returns existing ID - If not, creates new website: POST `/api/websites` - Payload: `{"name": "...", "domain": "..."}` - Authorization header: `Bearer {token}` 5. Updates in-memory config with Website ID 6. Returns success response to frontend ## Troubleshooting ### Error: "authentication failed" - Check UMAMI_USERNAME and UMAMI_PASSWORD in `.env` - Verify credentials work by testing with PowerShell script above ### Error: "create website failed" - Check if website already exists (list via PowerShell) - Verify token has correct permissions - Check Umami server logs ### Website ID not persisting - The Website ID is stored in memory only - Update `.env` with `UMAMI_WEBSITE_ID=...` for persistence - Restart backend server after updating `.env` ## Additional Notes - The backend automatically tries to create a website on first request to `/umami/config` if credentials are set - In production, it only auto-creates for non-localhost domains - In development, it allows localhost - The manual UI provides explicit control over website creation - You can create multiple websites for different domains if needed ## Umami v2 Compatibility Update (Latest Fix) ### Problem with Umami v2 In Umami v2, when users are part of teams, creating a website may require specifying a `teamId`. Without this parameter, the website creation request could fail. ### Solution Implemented Updated `CreateWebsite()` method in `umami_service.go` to: 1. **Fetch current user information** via `POST /api/auth/verify` 2. **Retrieve user's teams** via `GET /api/users/:userId/teams` 3. **Automatically use the first available team** when creating a website 4. **Gracefully degrade** if teams cannot be fetched (continues without teamId) ### New Methods Added ```go // GetCurrentUser - Retrieves authenticated user info from Umami func (u *UmamiService) GetCurrentUser() (map[string]interface{}, error) // GetUserTeams - Retrieves user's teams from Umami func (u *UmamiService) GetUserTeams(userID string) ([]UmamiTeam, error) ``` ### Updated CreateWebsite Flow ``` 1. Authenticate with Umami 2. Get current user info (to obtain user ID) 3. Fetch user's teams (if user has teams) 4. Prepare website creation request with: - name: Website name - domain: Website domain - teamId: First available team ID (optional) 5. Send POST /api/websites with Authorization Bearer token 6. Return website ID on success ``` ### Enhanced Error Logging All error messages now include detailed response bodies from Umami API for easier debugging: - Authentication failures show full error response - Website creation errors display Umami's error message - Team fetch failures log warnings but don't block website creation ### Testing the Fix To verify the fix works: 1. **Check backend logs** during website creation - you should see: ``` Creating Umami website: name='...', domain='...' Using team ID: xxx-xxx-xxx (team name: ...) Sending website creation request to Umami API: https://umami.tdvorak.dev/api/websites Successfully created Umami website: ... (ID: xxx, Domain: ...) ``` 2. **If teams aren't available**, you'll see: ``` Failed to fetch user teams (continuing without team): ... Successfully created Umami website: ... (ID: xxx, Domain: ...) ``` 3. **Monitor for creation errors** - detailed error messages will help diagnose issues This update ensures compatibility with both Umami v1 (no teams) and Umami v2 (with teams).