Files
MyClub/DOCS/TRACKING_IMPLEMENTATION_GUIDE.md
Tomáš Dvořák 12cba639b9 upload
2025-10-16 13:32:05 +02:00

10 KiB

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

Based on Umami documentation, add special data properties to any HTML element.

Basic Button Click

<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.

<button
  data-umami-event="Newsletter Submit"
  data-umami-event-location={window.location.pathname}
  data-umami-event-source="homepage"
>
  Subscribe
</button>
<a 
  href="/articles/123"
  data-umami-event="Article Click"
  data-umami-event-id="123"
  data-umami-event-title="Match Report"
>
  Read Article
</a>
<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

import { 
  trackEvent, 
  trackFormSubmit,
  trackNewsletterSubscribe,
  trackContactSubmit,
  // ... other helpers
} from '../utils/umami';

Form Submission Tracking

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

// 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

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

// 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

// 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

// 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

// 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);
}

File: frontend/src/components/layout/Footer.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:

trackEvent('Purchase', {
  product_id: '123',
  category: 'jersey',
  price: 500
});

Bad:

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:

<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

// 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

useEffect(() => {
  if (article) {
    trackArticleView(article.id, article.title);
  }
}, [article]);

Search Results

const handleSearch = async (query: string) => {
  const results = await searchArticles(query);
  trackSearch(query, results.length);
  setResults(results);
};

Video Player

const handlePlay = (video: Video) => {
  trackVideoPlay(video.id, video.title);
  player.play();
};
<a
  href={pdfUrl}
  download
  data-umami-event="Download"
  data-umami-event-file={fileName}
  data-umami-event-type="pdf"
>
  Download PDF
</a>

Modal/Dialog Opens

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

    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