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-orientedvideo_played– Clear purposefeature_toggled– Specific actiontrial_started– Business milestone
❌ Bad Event Names:
click– Too genericEvent1– Not descriptiveCheckout Complete– Contains spaces, inconsistent casingcheckoutComplete– 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 purposeexperiment_variant– Descriptiveproduct_category– Business contextsubscription_tier– Specific attribute
❌ Bad Tag Names:
tag1– Not descriptiveUser Type– Contains spaceuserType– 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
- Go to Recordings in Clarity dashboard
- Click Add filter
- Select Custom events
- Choose your event name
- See all sessions where that event fired
Example Use Cases:
- Filter by
purchase_completeto watch successful checkout sessions - Filter by
javascript_errorto debug broken user experiences - Filter by
feature_toggledto see how users interact with new features
Filter by Custom Tags
- Go to Recordings
- Click Add filter
- Select Custom tags
- Choose tag name and value
- See sessions matching that tag
Example Use Cases:
- Filter by
user_type: premiumto see premium user behavior - Filter by
experiment_variant: Bto analyze A/B test variant performance - Filter by
product_category: electronicsto 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
- Trigger events on your site
- Wait 15-30 minutes for data to process
- Go to Recordings > Add filter > Custom events
- Check if your event appears in the dropdown
- Filter by the event and watch a recording to verify it fired at the right moment
3. Check Network Requests
- Open DevTools > Network tab
- Filter by "clarity"
- Trigger an event
- Look for a request to
https://www.clarity.ms/collect - 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:
clarity("event", "name")– Mark significant user actionsclarity("set", "key", "value")– Add session metadata for filteringclarity("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:
- Clarity JavaScript API Reference
- Data Layer Setup Guide – Structure your tracking systematically
- Event Tracking Guide – Learn what Clarity tracks automatically