mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
upload
This commit is contained in:
@@ -0,0 +1,482 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user