Hotjar Troubleshooting & Debugging | Blue Frog Docs

Hotjar Troubleshooting & Debugging

Troubleshooting playbook and diagnostics checklist for resolving common Hotjar issues.

Hotjar Troubleshooting & Debugging

Common Issues & Solutions

Hotjar Not Tracking or Recording

Symptoms

  • No recordings appearing in dashboard
  • Heatmaps show zero data
  • Real-time view shows no active users

Diagnosis Steps

1. Verify Installation

Open browser DevTools (F12) and check console for errors:

// Check if Hotjar loaded
console.log(typeof hj); // Should return "function"
console.log(window._hjSettings); // Should show your site ID

2. Check Network Requests

In DevTools Network tab, filter by "hotjar" and look for:

  • script.hotjar.com - Script loaded successfully
  • insights.hotjar.com - Data being sent

3. Review Site Settings

In Hotjar dashboard:

  • Go to Sites & Organizations
  • Verify site status is "Installed"
  • Check that site URL matches your domain

Common Causes & Fixes

Issue Cause Solution
Script blocked by ad blocker User has ad/tracking blocker enabled Inform users, test in incognito mode
Wrong Site ID Incorrect hjid in tracking code Verify Site ID in Hotjar settings
Content Security Policy (CSP) CSP headers block external scripts Add script.hotjar.com and *.hotjar.com to CSP
Script loaded after user leaves Async loading too slow Move script higher in <head>
Privacy settings Cookie consent not granted Implement consent management properly

Fix Example: CSP Headers

Content-Security-Policy:
  script-src 'self' https://script.hotjar.com;
  connect-src 'self' https://*.hotjar.com https://*.hotjar.io;
  img-src 'self' https://*.hotjar.com;
  font-src 'self' https://script.hotjar.com;
  style-src 'self' 'unsafe-inline';

Recordings Not Capturing

Symptoms

  • Hotjar is installed but specific sessions aren't recorded
  • Recording quota not being consumed
  • Filters return no results

Diagnosis

Check Recording Settings:

  1. Go to Recordings > Settings
  2. Verify sampling rate (e.g., 100% = record all sessions)
  3. Check URL targeting rules
  4. Review device/browser filters

Common Scenarios:

Sampling Too Low

Setting: Record 10% of sessions
Result: Only 1 in 10 visitors recorded
Fix: Increase sampling to 50% or 100%

URL Filters Too Restrictive

Setting: Only record URLs containing "/checkout"
Result: Homepage sessions ignored
Fix: Broaden filters or create multiple recordings

Triggering Conditions Not Met

Setting: Only record if event "purchase_completed" fires
Result: Sessions without that event aren't captured
Fix: Remove event trigger or verify event fires correctly

Solutions

Broaden Your Filters:

// Remove restrictive targeting
// Before: Only /checkout/*
// After: All pages, segment later

Verify Events Fire:

// Test event in console
hj('event', 'test_event');
// Check if recording starts

Check Quota:

  • Recordings stop when monthly quota is reached
  • Upgrade plan or wait for quota reset

Heatmaps Show No Data

Symptoms

Diagnosis Steps

1. Check Data Collection Period

  • Heatmaps require time to accumulate data (usually 30+ pageviews)
  • Verify date range includes recent traffic

2. Verify URL Matching

Common Issue: URL mismatch
Example:
  Heatmap URL: https://example.com/page
  Actual URL: https://example.com/page?utm_source=email
Fix: Use wildcard matching or remove query parameters

3. Review Filters

  • Device filters (mobile vs desktop)
  • Geographic filters
  • Custom event filters

Solutions

URL Wildcard Matching:

Instead of: https://example.com/product
Use: https://example.com/product*
Matches: /product, /product?id=123, /product/details

Combine Similar Pages:

If you have:
  /product/123
  /product/456
  /product/789

Create dynamic heatmap:
  /product/*
Aggregates data across all product pages

Wait for Sufficient Data:

  • Minimum: 30 pageviews
  • Recommended: 100+ for statistical significance
  • High-traffic pages: 1,000+ for detailed insights

Events Not Firing

Symptoms

  • Custom events don't appear in filters
  • Event-triggered recordings not starting
  • Surveys not displaying on event

Diagnosis

Test Event Manually:

// Open console on your site
hj('event', 'test_event');

// Check network tab for request to:
// insights.hotjar.com/api/v2/events

Check Event Name:

// ✅ Correct
hj('event', 'signup_completed');

// ❌ Common mistakes
hj('events', 'signup_completed'); // Wrong function name
hj('event'); // Missing event name
hj('event', signupCompleted); // Variable instead of string
hj('event', 'signup completed'); // Spaces not recommended

Verify Timing:

// ❌ Event fires before Hotjar loads
hj('event', 'page_loaded'); // Might fail if hj not ready

// ✅ Check if Hotjar loaded first
if (typeof hj !== 'undefined') {
  hj('event', 'page_loaded');
}

// ✅ Or wrap in timeout
window.addEventListener('load', function() {
  setTimeout(() => hj('event', 'page_loaded'), 1000);
});

Solutions

Event Naming Best Practices:

// Use snake_case
hj('event', 'form_submitted');

// Not camelCase or spaces
hj('event', 'formSubmitted'); // Works, but inconsistent
hj('event', 'form submitted'); // Avoid

Debugging Event Flow:

// Add console logs
function trackEvent(eventName) {
  console.log('Tracking event:', eventName);
  if (typeof hj !== 'undefined') {
    hj('event', eventName);
    console.log('Event sent successfully');
  } else {
    console.error('Hotjar not loaded');
  }
}

// Usage
trackEvent('button_clicked');

GTM Event Troubleshooting:

If using GTM:

  1. Enable Preview Mode
  2. Trigger the event on your site
  3. Check Tags tab to see if Hotjar tag fired
  4. Review Variables to ensure event name is correct
  5. Check Console for errors

Identify API Not Working

Symptoms

  • User attributes not showing in recordings
  • Can't filter by identified users
  • User ID doesn't appear in session details

Diagnosis

Check Identify Call Format:

// ✅ Correct
hj('identify', 'USER_ID_123', {
  'email': 'user@example.com',
  'plan': 'premium'
});

// ❌ Common mistakes
hj('identify', null, { email: 'user@example.com' }); // Missing user ID
hj('identify', userObject); // Missing attributes object
hj('identify', '123'); // Missing attributes
hj('identify', 123, {}); // User ID should be string

Verify Timing:

// ❌ Called before Hotjar loads
hj('identify', userId, userAttributes);

// ✅ Wrapped in ready check
function identifyUser(userId, attributes) {
  if (typeof hj !== 'undefined') {
    hj('identify', userId, attributes);
  } else {
    console.warn('Hotjar not ready, retrying...');
    setTimeout(() => identifyUser(userId, attributes), 500);
  }
}

Check Attribute Limits:

  • Maximum 100 attributes per user
  • Attribute values must be strings, numbers, or booleans
  • No nested objects

Solutions

Proper Identify Implementation:

// On user login
function onUserLogin(user) {
  hj('identify', String(user.id), {
    'email': user.email,
    'plan': user.subscription.plan,
    'signup_date': user.createdAt,
    'role': user.role,
    'company_size': user.company.employeeCount
  });
}

// For SPAs, call on route change
router.afterEach(() => {
  if (currentUser) {
    hj('identify', String(currentUser.id), userAttributes);
  }
});

Attribute Value Formatting:

// ✅ Correct types
hj('identify', 'user123', {
  'age': 28, // Number
  'premium': true, // Boolean
  'country': 'USA', // String
  'signup_date': '2024-01-15' // String (dates as ISO)
});

// ❌ Avoid
hj('identify', 'user123', {
  'user_object': {id: 123}, // No nested objects
  'tags': ['premium', 'annual'], // No arrays
  'undefined_value': undefined // No undefined
});

Surveys Not Appearing

Symptoms

  • Survey created but doesn't display to users
  • Targeting conditions seem correct
  • No responses being collected

Diagnosis

Check Survey Status:

  1. Go to Surveys in Hotjar
  2. Verify survey is Active (not paused or draft)
  3. Check start/end dates

Review Targeting:

Common Issues:
- URL targeting too specific (exact match vs wildcard)
- Device filter excludes all traffic (e.g., tablet-only on desktop site)
- Event trigger never fires
- Display frequency: "Once per user" + user already saw it

Test in Incognito:

  • Cookies/localStorage might mark you as already seen
  • Ad blockers might prevent display
  • Consent settings might block survey

Solutions

URL Targeting Fixes:

❌ Too specific: https://example.com/page
✅ Use wildcard: https://example.com/page*

❌ Wrong protocol: http:// (site uses https://)
✅ Match protocol: https://

❌ Subdomain mismatch: www.example.com (tracking example.com)
✅ Use: *example.com/*

Display Frequency:

Setting: Show once per user
Problem: Tested survey already, won't show again
Fix: Clear cookies/localStorage or test in incognito

Event-Based Triggering:

// Verify event fires when expected
hj('event', 'checkout_completed');

// Check survey settings match event name exactly
Survey Setting: Show when event "checkout_completed" happens
Code: hj('event', 'checkout_completed'); // ✅ Match
Code: hj('event', 'checkoutCompleted'); // ❌ Mismatch

Device/Browser Testing:

Survey Settings:
- Device: All devices ✅
- Browser: All browsers ✅

If issues persist:
- Test on different browsers
- Check responsive design (survey might be off-screen)
- Review CSS conflicts

Cross-Domain Tracking Issues

Symptoms

  • Sessions split across domains
  • User journey fragmented
  • Can't track user across subdomains

Diagnosis

Check Tracking Code:

// Both domains must have same Hotjar Site ID
// Domain 1 & Domain 2: hjid: 123456

// Verify in console
console.log(window._hjSettings.hjid); // Should match

Cookie Domain Settings: Hotjar cookies are domain-specific by default.

Solutions

Enable Cross-Domain Tracking:

This isn't automatic in Hotjar like it is in GA. You need to:

  1. Use the same Site ID on all domains
  2. Share user ID via URL parameter:
// On domain1.com (sending domain)
const userId = getUserId(); // Your user ID
const targetUrl = `https://domain2.com?user_id=${userId}`;
window.location.href = targetUrl;

// On domain2.com (receiving domain)
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('user_id');

if (userId) {
  hj('identify', userId, userAttributes);
}

Subdomain Tracking:

Hotjar automatically tracks across subdomains if you set cookies correctly:

// No code changes needed
// Hotjar cookies work across:
// www.example.com
// app.example.com
// blog.example.com

Just ensure all subdomains use the same Site ID.

Performance & Loading Issues

Symptoms

  • Hotjar slows down page load
  • Recording playback laggy
  • High CPU usage during recording

Diagnosis

Check Script Loading:

<!-- ✅ Async loading (recommended) -->
<script async src="https://script.hotjar.com/..."></script>

<!-- ❌ Synchronous (blocks rendering) -->
<script src="https://script.hotjar.com/..."></script>

Monitor Impact:

// Measure load time
const start = performance.now();
// Hotjar loads
const end = performance.now();
console.log(`Hotjar load time: ${end - start}ms`);

Solutions

Optimize Loading:

// Lazy load Hotjar after page interactive
window.addEventListener('load', function() {
  setTimeout(loadHotjar, 2000); // Delay 2 seconds
});

function loadHotjar() {
  (function(h,o,t,j,a,r){
    // Hotjar code here
  })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
}

Reduce Recording Volume:

  • Lower sampling rate (record 50% instead of 100%)
  • Use URL filters to record only critical pages
  • Avoid recording during peak traffic hours (if possible)

Minimize Event Tracking:

// ❌ Excessive tracking
document.addEventListener('mousemove', () => {
  hj('event', 'mouse_moved'); // Fires hundreds of times
});

// ✅ Throttle or debounce
let lastEventTime = 0;
document.addEventListener('scroll', () => {
  const now = Date.now();
  if (now - lastEventTime > 1000) { // Max once per second
    hj('event', 'user_scrolled');
    lastEventTime = now;
  }
});

Data Discrepancies

Symptoms

  • Hotjar session count doesn't match Google Analytics
  • Heatmap clicks don't align with elements
  • Recording shows different content than live site

Common Causes

Session Definition Differences:

  • GA4: Session timeout after 30 min of inactivity
  • Hotjar: Session ends when user closes tab/browser
  • Result: Counts won't match exactly

Ad Blockers:

  • Hotjar blocked more often than GA
  • ~20-30% of users may block Hotjar
  • Result: Hotjar will always show fewer sessions

Sampling:

  • If recording only 50% of sessions, counts will be lower
  • Heatmaps accumulate over time, not real-time like GA

Dynamic Content:

// Content changes after Hotjar snapshot
// Heatmap shows old version, site has new version

// Solution: Create new heatmap after major updates

Solutions

Expect Discrepancies: Hotjar and GA measure differently. Use each for its strength:

  • GA: Traffic volume, sources, conversions
  • Hotjar: Behavior, UX issues, qualitative insights

Validate Heatmap Accuracy:

  1. Regenerate heatmap after site updates
  2. Check that snapshot matches current page
  3. Use browser extension to verify element positions

Reconcile Counts:

GA Sessions: 10,000
Hotjar Sessions: 6,000

Possible reasons:
- 30% blocked by ad blockers (3,000)
- 10% sampling rate adjustment (varies)
- Session definition differences

Debugging Tools & Techniques

Browser Developer Tools

Console Commands:

// Check Hotjar loaded
console.log(window.hj);

// View Hotjar settings
console.log(window._hjSettings);

// Manually trigger event
hj('event', 'debug_test');

// Trigger identify
hj('identify', 'test_user_123', { test: true });

// Force state change (SPAs)
hj('stateChange', '/new-page');

Network Tab: Filter by "hotjar" to see:

  • Script loading (script.hotjar.com)
  • Data being sent (insights.hotjar.com, vc.hotjar.io)
  • API calls

Hotjar Debug Mode

Enable detailed logging:

// In browser console
localStorage.setItem('hjDebug', 'true');

// Refresh page, check console for:
// "Hotjar: event tracked: event_name"
// "Hotjar: identify called with userId"
// "Hotjar: recording started"

// Disable debug mode
localStorage.removeItem('hjDebug');

Testing Checklist

Before deploying Hotjar changes:

  • Script loads without errors
  • Recordings capture on target pages
  • Heatmaps generate data
  • Events fire when triggered
  • Identify API updates user attributes
  • Surveys display under correct conditions
  • No console errors related to Hotjar
  • Performance impact is acceptable
  • Privacy/consent requirements met
  • Cross-browser testing completed

Support Resources

Hotjar Help Center:

Community Forum:

Contact Support:

  1. Go to Hotjar dashboard
  2. Click "?" icon (bottom right)
  3. Select "Contact Support"
  4. Provide: Site ID, issue description, screenshots

Provide When Contacting Support:

  • Hotjar Site ID
  • URL where issue occurs
  • Browser/device details
  • Screenshots of console errors
  • Network request details
  • Steps to reproduce

Preventive Maintenance

Regular Health Checks

Monthly:

  • Review recording quota usage
  • Check for new console errors
  • Verify integrations still work
  • Update filters for new pages/features

Quarterly:

  • Audit event taxonomy
  • Remove unused surveys/recordings
  • Review user feedback trends
  • Update documentation

After Site Updates:

  • Test Hotjar on staging before production
  • Regenerate heatmaps for updated pages
  • Verify events still fire correctly
  • Check for new CSP or privacy issues

Documentation

Maintain a tracking plan that includes:

  • List of custom events and their purpose
  • Identify attributes and their definitions
  • Recording/survey targeting rules
  • Integration dependencies
  • Known issues and workarounds

Monitoring & Alerts

Set up alerts for:

  • Sudden drop in session volume
  • Recording quota nearing limit
  • High rate of negative feedback
  • Survey response rate changes

Monitor via:

  • Hotjar dashboard (weekly reviews)
  • Slack/Teams notifications
  • Google Analytics annotations
  • Internal analytics dashboards

Additional Resources:

// SYS.FOOTER