Files
MyClub/DOCS/UMAMI_WEBSITE_CREATION_FIX.md
Tomas Dvorak 77213f4e83 dev day #65
2025-10-19 17:16:57 +02:00

312 lines
10 KiB
Markdown

# 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<string>('');
const [umamiDomain, setUmamiDomain] = useState<string>('');
const [umamiName, setUmamiName] = useState<string>('');
const [umamiInitializing, setUmamiInitializing] = useState<boolean>(false);
const [umamiConfig, setUmamiConfig] = useState<any>(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 <token>` 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).