Microsoft Clarity Event Tracking Setup | Blue Frog Docs

Microsoft Clarity Event Tracking Setup

Configure custom events, user identification, and session tagging in Microsoft Clarity

Microsoft Clarity Event Tracking Setup

Overview

While Microsoft Clarity automatically tracks user interactions (clicks, scrolls, page navigation), custom event tracking lets you mark specific moments that matter to your business. Whether it's a purchase, a feature activation, or a form submission, custom events make these moments filterable and analyzable in Clarity's dashboard.

This guide walks you through implementing custom events, user identification, and session tagging to enhance your Clarity data.

Clarity JavaScript API

Clarity provides three core API methods for custom tracking:

// Fire a custom event
clarity("event", "event_name");

// Set custom session tags
clarity("set", "key", "value");

// Identify a user
clarity("identify", "user_id");

These methods are available as soon as the Clarity script loads.

Custom Events

Custom events mark significant user actions that Clarity doesn't automatically detect.

When to Use Custom Events

✅ Use custom events for:

  • Purchases or conversions
  • Form submissions
  • Feature usage (toggles, settings changes)
  • Video play/completion
  • Content downloads
  • Multi-step process completions (onboarding, checkout)

❌ Don't use for:

  • Every click (Clarity already tracks this)
  • Every page view (tracked automatically)
  • High-frequency events (scroll, mousemove) unless throttled

Basic Custom Event Implementation

// Simple event
clarity("event", "signup_complete");

// Fire on button click
document.querySelector('#cta-button').addEventListener('click', function() {
  clarity("event", "cta_clicked");
});

// Fire on form submission
document.querySelector('#contact-form').addEventListener('submit', function(e) {
  clarity("event", "contact_form_submitted");
});

Event Naming Best Practices

✅ Good Event Names:

  • checkout_complete – Descriptive, action-oriented
  • video_played – Clear purpose
  • feature_toggled – Specific action
  • trial_started – Business milestone

❌ Bad Event Names:

  • click – Too generic
  • Event1 – Not descriptive
  • Checkout Complete – Contains spaces, inconsistent casing
  • checkoutComplete – camelCase instead of snake_case

Naming Convention:

  • Use snake_case (lowercase with underscores)
  • Be descriptive but concise (2-3 words)
  • Use action verbs: _clicked, _submitted, _completed, _viewed
  • Keep under 40 characters

Real-World Examples

E-Commerce: Track Add to Cart

document.querySelectorAll('.add-to-cart-btn').forEach(button => {
  button.addEventListener('click', function(e) {
    const productId = this.dataset.productId;
    const productName = this.dataset.productName;

    // Set product context
    clarity("set", "product_id", productId);
    clarity("set", "product_name", productName);

    // Fire event
    clarity("event", "add_to_cart");
  });
});

SaaS: Track Feature Activation

function enableDarkMode() {
  // Your app logic to enable dark mode
  document.body.classList.add('dark-mode');
  localStorage.setItem('theme', 'dark');

  // Track in Clarity
  clarity("set", "theme", "dark");
  clarity("event", "dark_mode_enabled");
}

Media: Track Video Engagement

const video = document.querySelector('video');

video.addEventListener('play', function() {
  clarity("set", "video_title", this.dataset.title);
  clarity("event", "video_played");
});

video.addEventListener('ended', function() {
  clarity("event", "video_completed");
});

// Track 50% milestone
video.addEventListener('timeupdate', function() {
  const percent = (this.currentTime / this.duration) * 100;

  if (percent >= 50 && !this.dataset.clarity50Tracked) {
    this.dataset.clarity50Tracked = 'true';
    clarity("event", "video_50_percent");
  }
});

Lead Gen: Track Form Funnel

const form = document.querySelector('#lead-form');

// Track form start
form.addEventListener('focusin', function() {
  if (!form.dataset.clarityStarted) {
    form.dataset.clarityStarted = 'true';
    clarity("event", "lead_form_started");
  }
}, { once: true });

// Track form submission
form.addEventListener('submit', function(e) {
  e.preventDefault();

  // Tag with form details
  clarity("set", "lead_source", document.referrer);
  clarity("event", "lead_form_submitted");

  // Then submit form
  this.submit();
});

Custom Session Tags

Session tags add metadata to sessions, enabling powerful filtering in Clarity's dashboard.

When to Use Session Tags

Use clarity("set") to tag sessions with:

  • User type or tier (free, premium, enterprise)
  • A/B test variants (variant_a, variant_b)
  • Traffic source or campaign (when not using GA integration)
  • Page category (homepage, product_page, checkout)
  • Custom user properties

Basic Tag Implementation

// Set a single tag
clarity("set", "user_type", "premium");

// Set multiple tags
clarity("set", "experiment", "homepage_redesign");
clarity("set", "variant", "B");
clarity("set", "signup_date", "2024-01-15");

Tag Naming Best Practices

✅ Good Tag Names:

  • user_type – Clear purpose
  • experiment_variant – Descriptive
  • product_category – Business context
  • subscription_tier – Specific attribute

❌ Bad Tag Names:

  • tag1 – Not descriptive
  • User Type – Contains space
  • userType – camelCase instead of snake_case

Tag Value Guidelines:

  • Convert all values to strings: clarity("set", "price", String(29.99))
  • Keep values under 100 characters
  • Use consistent values: "premium" not "Premium" or "PREMIUM"

Real-World Examples

E-Commerce: Tag by User Segment

// After user login
function onUserLogin(user) {
  clarity("set", "user_tier", user.tier); // "basic", "pro", "enterprise"
  clarity("set", "customer_since", user.joinDate);
  clarity("set", "total_orders", String(user.orderCount));
}

SaaS: Tag by Feature Access

// Tag users by feature flags
clarity("set", "feature_advanced_analytics", user.features.advancedAnalytics ? "enabled" : "disabled");
clarity("set", "feature_api_access", user.features.apiAccess ? "enabled" : "disabled");

Content Site: Tag by Content Category

// On article page load
clarity("set", "article_category", "technology");
clarity("set", "article_author", "Jane Doe");
clarity("set", "article_publish_date", "2024-03-15");

A/B Testing: Tag by Experiment

// After assigning user to experiment
function assignExperiment(experimentName, variant) {
  clarity("set", "experiment", experimentName);
  clarity("set", "variant", variant); // "A" or "B"

  // Now you can filter Clarity sessions by variant
}

User Identification

User identification links sessions to specific users, enabling you to:

  • Track user journeys across multiple sessions
  • Filter by specific user ID
  • Analyze behavior of known users

Basic User Identification

// Identify user after login
clarity("identify", "user_12345");

// With additional user properties
clarity("identify", "user_12345");
clarity("set", "user_email_hash", hashEmail(user.email));
clarity("set", "user_type", "premium");

User ID Best Practices

✅ Do:

  • Use hashed or anonymized IDs: hash(user.email), "user_" + userId
  • Use consistent IDs across sessions
  • Identify users as early as possible (after login)
  • Document your user ID scheme

❌ Don't:

  • Send PII (emails, names, phone numbers) in plain text
  • Use frequently changing IDs (defeats the purpose)
  • Identify users before they actually log in

Privacy-Compliant User Identification

// Hash email before sending
function hashEmail(email) {
  // Use a proper hashing library like crypto.subtle or sha256
  return sha256(email); // Returns hashed string
}

function identifyUserSafely(user) {
  const hashedId = hashEmail(user.email);
  clarity("identify", hashedId);

  // Add non-PII traits
  clarity("set", "user_subscription", user.subscription);
  clarity("set", "user_signup_date", user.signupDate);
}

Real-World Examples

E-Commerce: Identify After Checkout

function onOrderComplete(order) {
  // Identify user
  clarity("identify", `customer_${order.customerId}`);

  // Tag session with order details
  clarity("set", "order_id", order.id);
  clarity("set", "order_total", String(order.total));
  clarity("set", "order_items", String(order.items.length));

  // Fire conversion event
  clarity("event", "purchase_complete");
}

SaaS: Identify During Signup

function onSignupComplete(user) {
  // Create a hashed user ID
  const userId = `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

  clarity("identify", userId);
  clarity("set", "signup_method", user.signupMethod); // "google", "email"
  clarity("set", "plan", user.plan); // "trial", "free", "paid"

  clarity("event", "signup_complete");
}

Advanced Patterns

Conditional Event Tracking

Only track events for specific user segments:

function trackForPremiumUsers(eventName) {
  if (user.isPremium) {
    clarity("event", eventName);
  }
}

Event Batching (Throttling)

Prevent excessive events for high-frequency interactions:

let scrollTimeout;
window.addEventListener('scroll', function() {
  clearTimeout(scrollTimeout);

  scrollTimeout = setTimeout(() => {
    const scrollPercent = Math.round(
      (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100
    );

    if (scrollPercent === 25 || scrollPercent === 50 || scrollPercent === 75 || scrollPercent === 100) {
      clarity("event", `scroll_${scrollPercent}_percent`);
    }
  }, 500); // Fire only after user stops scrolling for 500ms
});

Error Tracking

Capture JavaScript errors:

window.addEventListener('error', function(event) {
  clarity("set", "error_message", event.message);
  clarity("set", "error_source", event.filename);
  clarity("set", "error_line", String(event.lineno));

  clarity("event", "javascript_error");
});

// Promise rejection tracking
window.addEventListener('unhandledrejection', function(event) {
  clarity("set", "error_message", String(event.reason));
  clarity("event", "promise_rejection");
});

Multi-Step Funnel Tracking

Track progress through a multi-step process:

const checkoutSteps = ['cart', 'shipping', 'payment', 'confirmation'];

function trackCheckoutStep(stepIndex) {
  const stepName = checkoutSteps[stepIndex];

  clarity("set", "checkout_step", stepName);
  clarity("set", "checkout_step_index", String(stepIndex));
  clarity("event", `checkout_step_${stepName}`);
}

// Usage:
// On cart page: trackCheckoutStep(0)
// On shipping page: trackCheckoutStep(1)
// etc.

Using Events for Session Filtering

Once events are implemented, use them to filter sessions in Clarity dashboard.

Filter by Custom Event

  1. Go to Recordings in Clarity dashboard
  2. Click Add filter
  3. Select Custom events
  4. Choose your event name
  5. See all sessions where that event fired

Example Use Cases:

  • Filter by purchase_complete to watch successful checkout sessions
  • Filter by javascript_error to debug broken user experiences
  • Filter by feature_toggled to see how users interact with new features

Filter by Custom Tags

  1. Go to Recordings
  2. Click Add filter
  3. Select Custom tags
  4. Choose tag name and value
  5. See sessions matching that tag

Example Use Cases:

  • Filter by user_type: premium to see premium user behavior
  • Filter by experiment_variant: B to analyze A/B test variant performance
  • Filter by product_category: electronics to understand category-specific behavior

Combining Filters

Stack multiple filters for precise segmentation:

Example: "Show me mobile users from the US who clicked the CTA but didn't complete checkout"

Filters:

  • Device = Mobile
  • Country = United States
  • Custom event = cta_clicked
  • Custom event ≠ checkout_complete

This level of filtering transforms Clarity from a recording tool into a behavior analytics powerhouse.

Testing Your Implementation

1. Console Testing

// Open browser console and manually trigger events
clarity("event", "test_event");
clarity("set", "test_tag", "test_value");
clarity("identify", "test_user_123");

// Check for errors in console

2. Verify in Clarity Dashboard

  1. Trigger events on your site
  2. Wait 15-30 minutes for data to process
  3. Go to Recordings > Add filter > Custom events
  4. Check if your event appears in the dropdown
  5. Filter by the event and watch a recording to verify it fired at the right moment

3. Check Network Requests

  1. Open DevTools > Network tab
  2. Filter by "clarity"
  3. Trigger an event
  4. Look for a request to https://www.clarity.ms/collect
  5. Inspect the request payload (should include your event/tag data)

Common Issues & Solutions

Events Don't Appear in Filters

Cause: Events haven't been fired yet, or Clarity hasn't processed them

Fix:

  • Trigger the event on your site
  • Wait 30 minutes and check again
  • Verify event name spelling (case-sensitive)

Tag Values Show as "undefined"

Cause: Variable is undefined when clarity("set") is called

Fix:

  • Ensure variables have values before tagging
  • Convert values to strings: clarity("set", "key", String(value))

User ID Not Persisting Across Sessions

Cause: clarity("identify") called too late, or not called on every page load

Fix:

  • Call clarity("identify") as early as possible after Clarity loads
  • Store user ID in localStorage and identify on every page load:
// On every page load
if (isUserLoggedIn()) {
  const userId = localStorage.getItem('user_id');
  if (userId) {
    clarity("identify", userId);
  }
}

Summary

Custom event tracking in Microsoft Clarity uses three core API methods:

  1. clarity("event", "name") – Mark significant user actions
  2. clarity("set", "key", "value") – Add session metadata for filtering
  3. clarity("identify", "user_id")Link sessions to users

Implementation checklist:

  • ✅ Define event taxonomy (10-20 key events)
  • ✅ Implement events in code with descriptive names
  • ✅ Tag sessions with relevant metadata
  • ✅ Identify users (with hashed/anonymized IDs)
  • ✅ Test events fire correctly
  • ✅ Verify events appear in Clarity dashboard filters
  • ✅ Use filters to analyze specific user segments

With custom event tracking, Clarity transforms from a passive recording tool into an active behavior analysis platform.


Additional Resources:

// SYS.FOOTER