mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
483 lines
10 KiB
Markdown
483 lines
10 KiB
Markdown
# Umami Event Tracking Implementation Guide
|
|
|
|
This guide shows how to add Umami event tracking throughout your application using both **data attributes** (HTML) and **JavaScript methods**.
|
|
|
|
## Quick Reference
|
|
|
|
### When to Use Which Method
|
|
|
|
- **Data Attributes (`data-umami-event`)**: Simple button clicks, links, static elements
|
|
- **JavaScript (`trackEvent()`)**: Dynamic events, programmatic tracking, conditional tracking, form submissions
|
|
|
|
## Method 1: Data Attributes (Recommended for Simple Tracking)
|
|
|
|
Based on [Umami documentation](https://umami.is/docs/track-events), add special data properties to any HTML element.
|
|
|
|
### Basic Button Click
|
|
|
|
```tsx
|
|
<button data-umami-event="Signup button">
|
|
Sign up
|
|
</button>
|
|
```
|
|
|
|
### With Additional Event Data
|
|
|
|
Use `data-umami-event-*` to add properties. Note: All data is saved as **strings** with this method.
|
|
|
|
```tsx
|
|
<button
|
|
data-umami-event="Newsletter Submit"
|
|
data-umami-event-location={window.location.pathname}
|
|
data-umami-event-source="homepage"
|
|
>
|
|
Subscribe
|
|
</button>
|
|
```
|
|
|
|
### Link Tracking
|
|
|
|
```tsx
|
|
<a
|
|
href="/articles/123"
|
|
data-umami-event="Article Click"
|
|
data-umami-event-id="123"
|
|
data-umami-event-title="Match Report"
|
|
>
|
|
Read Article
|
|
</a>
|
|
```
|
|
|
|
### Navigation Links
|
|
|
|
```tsx
|
|
<Link
|
|
to="/matches"
|
|
data-umami-event="Navigation"
|
|
data-umami-event-destination="matches"
|
|
>
|
|
Matches
|
|
</Link>
|
|
```
|
|
|
|
## Method 2: JavaScript Tracking (For Dynamic Events)
|
|
|
|
Import tracking utilities and call them programmatically. This method supports all data types (numbers, booleans, objects).
|
|
|
|
### Import
|
|
|
|
```tsx
|
|
import {
|
|
trackEvent,
|
|
trackFormSubmit,
|
|
trackNewsletterSubscribe,
|
|
trackContactSubmit,
|
|
// ... other helpers
|
|
} from '../utils/umami';
|
|
```
|
|
|
|
### Form Submission Tracking
|
|
|
|
```tsx
|
|
const handleSubmit = async (data: FormData) => {
|
|
try {
|
|
await submitForm(data);
|
|
|
|
// Track successful submission
|
|
trackFormSubmit('Newsletter Subscribe', true);
|
|
trackNewsletterSubscribe(window.location.pathname);
|
|
|
|
showSuccessMessage();
|
|
} catch (error) {
|
|
// Track failed submission
|
|
trackFormSubmit('Newsletter Subscribe', false);
|
|
|
|
showErrorMessage();
|
|
}
|
|
};
|
|
```
|
|
|
|
### Custom Event Tracking
|
|
|
|
```tsx
|
|
// Generic event with custom data
|
|
trackEvent('Video Play', {
|
|
videoId: '123',
|
|
duration: 300,
|
|
quality: 'HD'
|
|
});
|
|
|
|
// Article view
|
|
trackArticleView(article.id, article.title);
|
|
|
|
// Search tracking
|
|
trackSearch(searchQuery, resultsCount);
|
|
|
|
// Social share
|
|
trackSocialShare('Facebook', url);
|
|
```
|
|
|
|
### Conditional Tracking
|
|
|
|
```tsx
|
|
const handlePurchase = async (item: Product) => {
|
|
const success = await processPurchase(item);
|
|
|
|
if (success) {
|
|
trackEvent('Purchase', {
|
|
product: item.name,
|
|
price: item.price,
|
|
category: item.category,
|
|
success: true
|
|
});
|
|
}
|
|
};
|
|
```
|
|
|
|
## Implemented Examples
|
|
|
|
### ✅ Newsletter Subscription
|
|
|
|
**File**: `frontend/src/components/newsletter/NewsletterSubscribe.tsx`
|
|
|
|
```tsx
|
|
// Data attribute on submit button
|
|
<Button
|
|
type="submit"
|
|
data-umami-event="Newsletter Submit"
|
|
data-umami-event-location={window.location.pathname}
|
|
>
|
|
Subscribe
|
|
</Button>
|
|
|
|
// JavaScript tracking in handler
|
|
const onSubmit = async (data: FormData) => {
|
|
try {
|
|
await subscribeToNewsletter(data.email);
|
|
trackNewsletterSubscribe(window.location.pathname);
|
|
trackFormSubmit('Newsletter Subscribe', true);
|
|
} catch (error) {
|
|
trackFormSubmit('Newsletter Subscribe', false);
|
|
}
|
|
};
|
|
```
|
|
|
|
### ✅ Newsletter Preferences
|
|
|
|
**File**: `frontend/src/pages/NewsletterPreferencesPage.tsx`
|
|
|
|
```tsx
|
|
// Save preferences button
|
|
<Button
|
|
onClick={() => saveMut.mutate()}
|
|
data-umami-event="Save Preferences"
|
|
>
|
|
Save
|
|
</Button>
|
|
|
|
// Track in mutation success
|
|
onSuccess: () => {
|
|
trackEvent('Newsletter Preferences Saved', {
|
|
blogs: prefs.blogs,
|
|
matches: prefs.matches,
|
|
events: prefs.events,
|
|
scores: prefs.scores,
|
|
});
|
|
}
|
|
```
|
|
|
|
### ✅ Newsletter Unsubscribe
|
|
|
|
**File**: `frontend/src/pages/NewsletterUnsubscribePage.tsx`
|
|
|
|
```tsx
|
|
// Track unsubscribe completion
|
|
await unsubscribeFromNewsletter(email);
|
|
trackEvent('Newsletter Unsubscribe', {
|
|
success: true,
|
|
source: 'email_link'
|
|
});
|
|
|
|
// Data attribute on button
|
|
<Button
|
|
onClick={handleBackToHome}
|
|
data-umami-event="Back to Home"
|
|
data-umami-event-from="unsubscribe"
|
|
>
|
|
Back to Home
|
|
</Button>
|
|
```
|
|
|
|
### ✅ Contact Form
|
|
|
|
**File**: `frontend/src/pages/ContactPage.tsx`
|
|
|
|
```tsx
|
|
// Submit button with data attribute
|
|
<Button
|
|
type="submit"
|
|
data-umami-event="Contact Form Submit"
|
|
>
|
|
Send Message
|
|
</Button>
|
|
|
|
// JavaScript tracking
|
|
onSuccess: () => {
|
|
trackContactSubmit(true);
|
|
trackFormSubmit('Contact Form', true);
|
|
},
|
|
onError: () => {
|
|
trackContactSubmit(false);
|
|
trackFormSubmit('Contact Form', false);
|
|
}
|
|
```
|
|
|
|
### ✅ Social Media Links
|
|
|
|
**File**: `frontend/src/components/layout/Footer.tsx`
|
|
|
|
```tsx
|
|
<IconButton
|
|
as="a"
|
|
href={facebookUrl}
|
|
onClick={() => trackSocialShare('Facebook', facebookUrl)}
|
|
aria-label="Facebook"
|
|
icon={<FiFacebook />}
|
|
/>
|
|
```
|
|
|
|
## Available Helper Functions
|
|
|
|
All functions are in `frontend/src/utils/umami.ts`:
|
|
|
|
| Function | Purpose | Example |
|
|
|----------|---------|---------|
|
|
| `trackEvent(name, data?)` | Generic event | `trackEvent('Video Play', { id: '123' })` |
|
|
| `trackButtonClick(button, location?)` | Button clicks | `trackButtonClick('Download PDF')` |
|
|
| `trackFormSubmit(form, success?)` | Form submissions | `trackFormSubmit('Contact', true)` |
|
|
| `trackNavigation(dest, source?)` | Page navigation | `trackNavigation('/matches')` |
|
|
| `trackArticleView(id, title)` | Article views | `trackArticleView(1, 'Title')` |
|
|
| `trackMatchView(id)` | Match views | `trackMatchView(123)` |
|
|
| `trackSearch(query, results?)` | Search queries | `trackSearch('striker', 10)` |
|
|
| `trackVideoPlay(id, title?)` | Video plays | `trackVideoPlay('abc123')` |
|
|
| `trackNewsletterSubscribe(source?)` | Newsletter signup | `trackNewsletterSubscribe('/home')` |
|
|
| `trackDownload(file, type?)` | File downloads | `trackDownload('brochure.pdf')` |
|
|
| `trackSocialShare(platform, url?)` | Social shares | `trackSocialShare('Twitter')` |
|
|
| `trackContactSubmit(success?)` | Contact form | `trackContactSubmit(true)` |
|
|
|
|
## Best Practices
|
|
|
|
### 1. Event Names
|
|
|
|
- **Keep them short** (max 50 characters)
|
|
- **Be descriptive but consistent**
|
|
- **Use Title Case** for readability
|
|
|
|
✅ Good:
|
|
- `Newsletter Submit`
|
|
- `Article Click`
|
|
- `Video Play`
|
|
|
|
❌ Bad:
|
|
- `newsletter_submit_button_clicked_on_homepage`
|
|
- `click`
|
|
- `event123`
|
|
|
|
### 2. Event Data
|
|
|
|
- **Use snake_case** for property names
|
|
- **Keep data relevant** - don't track sensitive information
|
|
- **Be consistent** across similar events
|
|
|
|
✅ Good:
|
|
```tsx
|
|
trackEvent('Purchase', {
|
|
product_id: '123',
|
|
category: 'jersey',
|
|
price: 500
|
|
});
|
|
```
|
|
|
|
❌ Bad:
|
|
```tsx
|
|
trackEvent('Purchase', {
|
|
PRODUCT_ID: '123',
|
|
user_email: 'sensitive@example.com', // Don't track PII
|
|
random_data: 'unnecessary'
|
|
});
|
|
```
|
|
|
|
### 3. Combining Methods
|
|
|
|
Use **both** data attributes AND JavaScript when you need tracking + custom logic:
|
|
|
|
```tsx
|
|
<Button
|
|
onClick={handleClick}
|
|
data-umami-event="Download" // Automatic tracking
|
|
data-umami-event-file="brochure.pdf"
|
|
>
|
|
Download
|
|
</Button>
|
|
|
|
const handleClick = () => {
|
|
// Additional programmatic tracking with more context
|
|
trackDownload('brochure.pdf', 'pdf');
|
|
|
|
// Your custom logic here
|
|
initiateDownload();
|
|
};
|
|
```
|
|
|
|
### 4. Don't Over-Track
|
|
|
|
Track **meaningful** user interactions, not every tiny action:
|
|
|
|
✅ Track:
|
|
- Form submissions
|
|
- Button clicks on CTAs
|
|
- Article/video views
|
|
- Downloads
|
|
- Social shares
|
|
- Navigation to key pages
|
|
|
|
❌ Don't track:
|
|
- Mouse movements
|
|
- Every scroll event
|
|
- Hovering over elements
|
|
- Typing in forms (privacy!)
|
|
|
|
## Testing Your Tracking
|
|
|
|
### 1. Browser Console
|
|
|
|
```javascript
|
|
// Check if Umami is loaded
|
|
console.log(window.umami);
|
|
|
|
// Manually trigger an event
|
|
window.umami?.track('Test Event', { test: true });
|
|
```
|
|
|
|
### 2. Network Tab
|
|
|
|
1. Open DevTools > Network
|
|
2. Filter by your Umami domain or "umami"
|
|
3. Interact with tracked elements
|
|
4. Verify requests are sent
|
|
|
|
### 3. Umami Dashboard
|
|
|
|
1. Go to `/admin/analytika`
|
|
2. Navigate to "Události" (Events) tab
|
|
3. Verify your custom events appear
|
|
|
|
## Common Patterns
|
|
|
|
### Article/Blog Post View
|
|
|
|
```tsx
|
|
useEffect(() => {
|
|
if (article) {
|
|
trackArticleView(article.id, article.title);
|
|
}
|
|
}, [article]);
|
|
```
|
|
|
|
### Search Results
|
|
|
|
```tsx
|
|
const handleSearch = async (query: string) => {
|
|
const results = await searchArticles(query);
|
|
trackSearch(query, results.length);
|
|
setResults(results);
|
|
};
|
|
```
|
|
|
|
### Video Player
|
|
|
|
```tsx
|
|
const handlePlay = (video: Video) => {
|
|
trackVideoPlay(video.id, video.title);
|
|
player.play();
|
|
};
|
|
```
|
|
|
|
### Download Links
|
|
|
|
```tsx
|
|
<a
|
|
href={pdfUrl}
|
|
download
|
|
data-umami-event="Download"
|
|
data-umami-event-file={fileName}
|
|
data-umami-event-type="pdf"
|
|
>
|
|
Download PDF
|
|
</a>
|
|
```
|
|
|
|
### Modal/Dialog Opens
|
|
|
|
```tsx
|
|
const openDialog = () => {
|
|
trackEvent('Modal Open', {
|
|
modal: 'player_details',
|
|
player_id: player.id
|
|
});
|
|
setIsOpen(true);
|
|
};
|
|
```
|
|
|
|
## Integration Checklist
|
|
|
|
- [ ] Newsletter subscription form
|
|
- [ ] Newsletter preferences page
|
|
- [ ] Newsletter unsubscribe page
|
|
- [ ] Contact form
|
|
- [ ] Social media links
|
|
- [ ] Article/blog post views
|
|
- [ ] Match views
|
|
- [ ] Video plays
|
|
- [ ] File downloads
|
|
- [ ] Search functionality
|
|
- [ ] Navigation links
|
|
- [ ] Call-to-action buttons
|
|
- [ ] E-shop links (if applicable)
|
|
|
|
## Troubleshooting
|
|
|
|
### Events Not Showing Up
|
|
|
|
1. **Check if Umami script is loaded**
|
|
```javascript
|
|
console.log(window.umami); // Should not be undefined
|
|
```
|
|
|
|
2. **Verify website ID is set**
|
|
- Check `/api/v1/umami/config` returns valid config
|
|
|
|
3. **Check Network tab**
|
|
- Look for requests to your Umami server
|
|
- Verify they return 200 OK
|
|
|
|
### Data Attributes Not Working
|
|
|
|
1. **Ensure script is loaded** before user interaction
|
|
2. **Check element syntax** - must be `data-umami-event` exactly
|
|
3. **Verify onClick handlers** aren't preventing default behavior
|
|
|
|
### JavaScript Tracking Not Working
|
|
|
|
1. **Check imports** are correct
|
|
2. **Verify function calls** happen after successful actions
|
|
3. **Check browser console** for errors
|
|
|
|
## Resources
|
|
|
|
- [Umami Event Tracking Docs](https://umami.is/docs/track-events)
|
|
- [Umami API Reference](https://umami.is/docs/api)
|
|
- Project: `UMAMI_INTEGRATION.md` - Full integration documentation
|
|
- Code: `frontend/src/utils/umami.ts` - Tracking utilities
|
|
- Code: `frontend/src/hooks/useUmami.ts` - React hook
|