Simple Analytics Event Tracking Setup | OpsBlu Docs

Simple Analytics Event Tracking Setup

Implement event tracking in Simple Analytics — custom events, ecommerce tracking, data layer configuration, and validation.

Event Tracking in Simple Analytics

Simple Analytics provides straightforward event tracking with its privacy-first approach. Events let you track user interactions beyond page views, such as button clicks, form submissions, purchases, and custom actions - all without compromising visitor privacy or requiring cookies.

Event Tracking Philosophy

Simple Analytics' event tracking is designed to be:

  • Simple: Single function call to track events
  • Privacy-Friendly: No user identification or cookies
  • Lightweight: Minimal JavaScript overhead
  • Flexible: Track any custom action
  • Aggregate-Only: Events are counted, not tied to individual users

Basic Event Tracking

JavaScript API:

sa_event('event_name');

Example Events:

// Newsletter signup
sa_event('newsletter_signup');

// Button click
sa_event('cta_click');

// Download
sa_event('file_download');

Event with Metadata

Simple Analytics supports event metadata for additional context:

sa_event('event_name', { key: 'value' });

E-Commerce Example:

// Purchase event
sa_event('purchase', {
  amount: 99.99,
  currency: 'USD',
  product: 'Pro Plan'
});

Feature Usage:

sa_event('feature_used', {
  feature: 'export_data',
  format: 'CSV'
});

Common Event Tracking Patterns

User Interactions

Button Clicks:

// Track specific button
document.getElementById('signup-button').addEventListener('click', () => {
  sa_event('button_click', {
    button: 'signup',
    location: 'hero'
  });
});

// Track all CTA buttons
document.querySelectorAll('.cta-button').forEach(button => {
  button.addEventListener('click', (e) => {
    sa_event('cta_click', {
      text: e.target.textContent.trim(),
      url: e.target.href
    });
  });
});

Link Clicks:

// Track outbound links
document.querySelectorAll('a[href^="http"]').forEach(link => {
  link.addEventListener('click', (e) => {
    const url = e.target.href;

    if (!url.includes(window.location.hostname)) {
      sa_event('outbound_link', {
        destination: url
      });
    }
  });
});

Navigation Menu Clicks:

document.querySelectorAll('.main-nav a').forEach(link => {
  link.addEventListener('click', (e) => {
    sa_event('nav_click', {
      section: e.target.dataset.section,
      label: e.target.textContent.trim()
    });
  });
});

Form Tracking

Form Submission:

document.getElementById('contact-form').addEventListener('submit', (e) => {
  sa_event('form_submit', {
    form: 'contact',
    method: e.target.method
  });
});

Newsletter Signup:

document.getElementById('newsletter-form').addEventListener('submit', async (e) => {
  e.preventDefault();

  // Track event
  sa_event('newsletter_signup', {
    source: 'footer'
  });

  // Submit form
  await submitForm(e.target);
});

Form Errors:

function validateForm(form) {
  const errors = [];

  if (!form.email.value.includes('@')) {
    errors.push('email');

    sa_event('form_error', {
      form: 'signup',
      field: 'email',
      error: 'invalid_format'
    });
  }

  return errors;
}

E-Commerce Events

Product Views:

// Track when user views product page
sa_event('product_view', {
  product_id: product.id,
  product_name: product.name,
  category: product.category,
  price: product.price
});

Add to Cart:

function addToCart(product, quantity) {
  sa_event('add_to_cart', {
    product: product.name,
    quantity: quantity,
    value: product.price * quantity
  });

  // Add to cart logic...
}

Checkout Funnel:

// Step 1: Checkout initiated
sa_event('checkout_started', {
  cart_value: getCartTotal(),
  items: getCartItems().length
});

// Step 2: Shipping info entered
sa_event('shipping_info_entered');

// Step 3: Payment method selected
sa_event('payment_method_selected', {
  method: 'credit_card'
});

// Step 4: Order completed
sa_event('purchase_completed', {
  order_id: orderId,
  value: orderTotal,
  currency: 'USD'
});

Cart Abandonment:

// Track when user leaves checkout without completing
window.addEventListener('beforeunload', () => {
  if (isOnCheckoutPage() && !orderCompleted) {
    sa_event('cart_abandoned', {
      cart_value: getCartTotal(),
      items_count: getCartItems().length
    });
  }
});

Content Engagement

Video Tracking:

const video = document.getElementById('promo-video');

// Video play
video.addEventListener('play', () => {
  sa_event('video_play', {
    video_id: 'product_demo',
    duration: video.duration
  });
});

// Video milestone tracking (25%, 50%, 75%, 100%)
const milestones = [25, 50, 75, 100];
const trackedMilestones = new Set();

video.addEventListener('timeupdate', () => {
  const percent = (video.currentTime / video.duration) * 100;

  milestones.forEach(milestone => {
    if (percent >= milestone && !trackedMilestones.has(milestone)) {
      trackedMilestones.add(milestone);
      sa_event('video_progress', {
        video_id: 'product_demo',
        milestone: milestone
      });
    }
  });
});

// Video completed
video.addEventListener('ended', () => {
  sa_event('video_complete', {
    video_id: 'product_demo'
  });
});

Scroll Depth:

const scrollDepths = [25, 50, 75, 100];
const trackedDepths = new Set();

window.addEventListener('scroll', () => {
  const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;

  scrollDepths.forEach(depth => {
    if (scrollPercent >= depth && !trackedDepths.has(depth)) {
      trackedDepths.add(depth);
      sa_event('scroll_depth', {
        depth: depth,
        page: window.location.pathname
      });
    }
  });
});

File Downloads:

document.querySelectorAll('a[download]').forEach(link => {
  link.addEventListener('click', (e) => {
    const fileName = e.target.getAttribute('download') || e.target.href.split('/').pop();
    const fileExt = fileName.split('.').pop();

    sa_event('file_download', {
      file: fileName,
      type: fileExt
    });
  });
});

Search Queries:

document.getElementById('search-form').addEventListener('submit', (e) => {
  e.preventDefault();
  const query = e.target.querySelector('input[name="q"]').value;

  sa_event('search', {
    query: query.toLowerCase(),
    results: getSearchResultsCount()
  });

  performSearch(query);
});

SaaS Application Events

Feature Usage:

// Track when user uses a specific feature
sa_event('export_data', {
  format: 'CSV',
  records: recordCount
});

sa_event('report_generated', {
  report_type: 'monthly_summary',
  date_range: '30_days'
});

Account Events:

// Trial started
sa_event('trial_started', {
  plan: 'pro',
  trial_days: 14
});

// Upgrade
sa_event('plan_upgraded', {
  from: 'basic',
  to: 'pro',
  billing: 'monthly'
});

// Cancellation
sa_event('subscription_cancelled', {
  plan: 'pro',
  reason: 'cost'
});

Onboarding Steps:

// Track onboarding progress
sa_event('onboarding_step_completed', {
  step: 'profile_setup',
  step_number: 1,
  total_steps: 5
});

Framework-Specific Implementation

React

import { useCallback } from 'react';

export function useAnalytics() {
  const trackEvent = useCallback((eventName, eventData) => {
    if (typeof window !== 'undefined' && window.sa_event) {
      window.sa_event(eventName, eventData);
    }
  }, []);

  return { trackEvent };
}

// Usage in component
function SignupButton() {
  const { trackEvent } = useAnalytics();

  const handleClick = () => {
    trackEvent('signup_button_click', {
      location: 'header'
    });
  };

  return <button Up</button>;
}

Vue.js

// Global mixin
export default {
  methods: {
    $trackEvent(eventName, eventData) {
      if (window.sa_event) {
        window.sa_event(eventName, eventData);
      }
    }
  }
};

// In component
<template>
  <button @click="handleClick">Buy Now</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$trackEvent('purchase_initiated', {
        product: 'Pro Plan',
        price: 99
      });
    }
  }
};
</script>

Next.js

// utils/analytics.js
export const trackEvent = (eventName, eventData) => {
  if (typeof window !== 'undefined' && window.sa_event) {
    window.sa_event(eventName, eventData);
  }
};

// In component
import { trackEvent } from '@/utils/analytics';

export default function ProductCard({ product }) {
  const handleAddToCart = () => {
    trackEvent('add_to_cart', {
      product_id: product.id,
      price: product.price
    });

    // Add to cart logic...
  };

  return (
    <button to Cart</button>
  );
}

Helper Functions

Safe Event Tracking:

function trackEvent(eventName, eventData = {}) {
  try {
    if (typeof window !== 'undefined' && window.sa_event) {
      window.sa_event(eventName, eventData);
    } else if (process.env.NODE_ENV === 'development') {
      console.log('[SA Event]', eventName, eventData);
    }
  } catch (error) {
    console.error('Error tracking event:', error);
  }
}

Debounced Event Tracking:

function debounce(func, wait) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

const trackScrollDebounced = debounce(() => {
  sa_event('page_scrolled', {
    scroll_position: window.scrollY
  });
}, 500);

window.addEventListener('scroll', trackScrollDebounced);

Event Queue for Reliability:

const eventQueue = [];
let isProcessing = false;

async function queueEvent(eventName, eventData) {
  eventQueue.push({ eventName, eventData });
  processQueue();
}

async function processQueue() {
  if (isProcessing || eventQueue.length === 0) return;
  isProcessing = true;

  while (eventQueue.length > 0) {
    const { eventName, eventData } = eventQueue.shift();
    try {
      sa_event(eventName, eventData);
      await new Promise(resolve => setTimeout(resolve, 100)); // Rate limiting
    } catch (error) {
      console.error('Failed to track event:', error);
    }
  }

  isProcessing = false;
}

Testing Event Tracking

Development Logging:

const isDev = process.env.NODE_ENV === 'development';

function trackEvent(eventName, eventData) {
  if (isDev) {
    console.group('Simple Analytics Event');
    console.log('Event:', eventName);
    console.log('Data:', eventData);
    console.groupEnd();
  }

  if (window.sa_event) {
    sa_event(eventName, eventData);
  }
}

Browser Console Testing:

// Test in console
sa_event('test_event', {
  test: true,
  timestamp: new Date().toISOString()
});

// Check if Simple Analytics loaded
console.log(typeof window.sa_event); // Should be 'function'

Verify in Dashboard:

  1. Fire test event from your site
  2. Go to Simple Analytics dashboard
  3. Click "Events" in sidebar
  4. Look for your event name
  5. Click event to see metadata

Best Practices

  1. Use Descriptive Event Names: newsletter_signup instead of signup
  2. Keep Names Consistent: Use snake_case or camelCase consistently
  3. Group Related Events: checkout_started, checkout_completed, checkout_abandoned
  4. Include Meaningful Metadata: Add context that helps understand the event
  5. Don't Over-Track: Focus on actionable events
  6. Avoid PII: Never include personal information in events
  7. Test Thoroughly: Verify events appear in dashboard
  8. Document Events: Maintain a list of tracked events
  9. Use Constants: Define event names as constants to avoid typos
  10. Handle Errors: Wrap tracking in try-catch

Privacy Considerations

What NOT to Track:

// BAD: Don't track PII
sa_event('signup', {
  email: 'user@example.com',  // Don't
  name: 'John Doe',            // Don't
  address: '123 Main St'       // Don't
});

// GOOD: Track without PII
sa_event('signup', {
  source: 'landing_page',
  plan: 'free'
});

Respecting User Privacy:

// Check for consent if needed
function trackWithConsent(eventName, eventData) {
  const hasConsent = localStorage.getItem('analytics_consent') === 'true';

  if (hasConsent && window.sa_event) {
    sa_event(eventName, eventData);
  }
}

Event Naming Constants

// Define constants to avoid typos
const EVENTS = {
  SIGNUP: 'user_signup',
  LOGIN: 'user_login',
  PURCHASE: 'purchase_completed',
  CART_ADD: 'add_to_cart',
  DOWNLOAD: 'file_download',
  SEARCH: 'search_performed',
  VIDEO_PLAY: 'video_play',
  FORM_SUBMIT: 'form_submit'
};

// Usage
sa_event(EVENTS.SIGNUP, {
  source: 'homepage'
});

sa_event(EVENTS.PURCHASE, {
  value: 99.99,
  currency: 'USD'
});

Viewing Events in Dashboard

Events Page:

  1. Log into Simple Analytics dashboard
  2. Click "Events" in sidebar
  3. View event list with counts
  4. Click event name to see metadata breakdown
  5. Filter by date range
  6. Export events data

Event Metadata Analysis:

  • Click specific event to see all metadata values
  • See frequency of each metadata value
  • Filter events by metadata
  • Track trends over time

Common Pitfalls

  1. Tracking Before Script Loads: Always check window.sa_event exists
  2. Typos in Event Names: Use constants or TypeScript for type safety
  3. Too Much Metadata: Keep metadata focused and relevant
  4. Forgetting to Test: Always verify events appear in dashboard
  5. Inconsistent Naming: Stick to one naming convention

Summary

Simple Analytics event tracking is:

  • Simple: Single function call
  • Privacy-First: No cookies or user identification
  • Flexible: Track any custom action
  • Lightweight: Minimal performance impact
  • Actionable: Focus on meaningful business events

Track what matters, respect user privacy, and gain valuable insights into how users interact with your product - all without the complexity of traditional analytics platforms.