# Heatmaps

Heatmaps capture click and mouse movement data to visualize where users interact with your website. This data powers click heatmaps, scroll depth analysis, and rage click detection in PostHog.

## Capabilities

### Check If Enabled

Checks whether heatmaps are currently enabled based on configuration or server-side settings.

```typescript { .api }
/**
 * Whether heatmaps are enabled
 * Checks local config and server-side remote config
 */
readonly isEnabled: boolean;
```

**Usage Example:**

```typescript
if (posthog.heatmaps.isEnabled) {
    console.log('Heatmaps are active');
}
```

### Start Heatmaps

Starts heatmap data collection if enabled.

```typescript { .api }
/**
 * Starts heatmap collection if enabled
 * Safe to call multiple times - will not restart if already running
 */
function startIfEnabled(): void;
```

**Usage Example:**

```typescript
// Typically called automatically on initialization
// Can be called manually if needed
posthog.heatmaps.startIfEnabled();
```

### Stop Heatmaps

Stops heatmap data collection.

```typescript { .api }
/**
 * Stops heatmap collection and clears listeners
 */
function stop(): void;
```

**Usage Example:**

```typescript
// Stop collecting heatmap data
posthog.heatmaps.stop();
```

### Flush Interval

The interval at which heatmap data is sent to the server.

```typescript { .api }
/**
 * Flush interval in milliseconds
 * Controls how often collected heatmap data is sent to PostHog
 * @default 5000 (5 seconds)
 */
readonly flushIntervalMilliseconds: number;
```

**Usage Example:**

```typescript
const interval = posthog.heatmaps.flushIntervalMilliseconds;
console.log(`Heatmaps flush every ${interval}ms`);
```

## Configuration

Heatmaps can be controlled through initialization config.

```typescript
posthog.init('token', {
    // Enable/disable heatmaps
    capture_heatmaps: true, // default: undefined (server-controlled)

    // Or use detailed configuration
    capture_heatmaps: {
        // Custom flush interval in milliseconds
        flush_interval_milliseconds: 5000 // default
    }
});
```

### Configuration Options

```typescript { .api }
interface HeatmapsConfig {
    /**
     * Enable or disable heatmaps
     * - true: Enable heatmaps
     * - false: Disable heatmaps
     * - undefined: Use server-side configuration (default)
     */
    capture_heatmaps?: boolean | {
        /**
         * How often to send heatmap data to server (milliseconds)
         * @default 5000
         */
        flush_interval_milliseconds?: number;
    };
}
```

## How Heatmaps Work

### Data Collection

Heatmaps automatically track:

1. **Click Events** - Where users click on the page
2. **Mouse Movements** - Where users move their cursor
3. **Rage Clicks** - Rapid repeated clicks indicating frustration
4. **Dead Clicks** - Clicks that don't trigger any action

### Server-Side Control

By default, heatmaps are controlled by server-side configuration from PostHog:

```typescript
// Let PostHog control heatmaps
posthog.init('token'); // Uses server config

// Override to always enable
posthog.init('token', {
    capture_heatmaps: true
});

// Override to always disable
posthog.init('token', {
    capture_heatmaps: false
});
```

### Data Transmission

Heatmap data is:
- Buffered locally as users interact
- Sent to PostHog at regular intervals (default: 5 seconds)
- Flushed immediately on page unload

## Usage Patterns

### Basic Usage

```typescript
// Initialize with heatmaps enabled
posthog.init('token', {
    capture_heatmaps: true
});

// Check if heatmaps are active
if (posthog.heatmaps.isEnabled) {
    console.log('Collecting heatmap data');
}
```

### Custom Flush Interval

```typescript
// Send heatmap data more frequently
posthog.init('token', {
    capture_heatmaps: {
        flush_interval_milliseconds: 2000 // Send every 2 seconds
    }
});
```

### Conditional Heatmaps

```typescript
// Only enable heatmaps for specific pages
posthog.init('token', {
    capture_heatmaps: false // Disabled by default
});

// Enable on specific pages
if (window.location.pathname.startsWith('/product/')) {
    posthog.heatmaps.startIfEnabled();
}

// Disable on other pages
posthog.heatmaps.stop();
```

### Dynamic Control

```typescript
// Start collecting heatmaps based on user action
function enableDetailedTracking() {
    posthog.set_config({
        capture_heatmaps: true
    });
    posthog.heatmaps.startIfEnabled();
}

// Stop collecting heatmaps
function disableDetailedTracking() {
    posthog.heatmaps.stop();
    posthog.set_config({
        capture_heatmaps: false
    });
}
```

## Integration with Other Features

### Rage Clicks

Heatmaps automatically detect and track rage clicks (rapid repeated clicks):

```typescript
posthog.init('token', {
    capture_heatmaps: true,
    autocapture: {
        rageclicks: true // Enable rage click detection
    }
});

// Rage clicks are automatically included in heatmap data
```

### Dead Clicks

Heatmaps can also track dead clicks (clicks with no effect):

```typescript
posthog.init('token', {
    capture_heatmaps: true,
    autocapture: {
        dead_clicks: true // Enable dead click detection
    }
});
```

### Session Recording

Heatmaps complement session recording for complete user interaction analysis:

```typescript
posthog.init('token', {
    capture_heatmaps: true,      // Visual click/movement analysis
    session_recording: {
        enabled: true              // Video replay of sessions
    }
});
```

## Best Practices

### Enable for High-Value Pages

Focus heatmap collection on important pages to optimize performance and data costs:

```typescript
const highValuePages = ['/pricing', '/checkout', '/product'];

posthog.init('token', {
    capture_heatmaps: highValuePages.some(page =>
        window.location.pathname.startsWith(page)
    )
});
```

### Adjust Flush Interval Based on Traffic

For high-traffic pages, consider a longer flush interval:

```typescript
const isHighTrafficPage = window.location.pathname === '/';

posthog.init('token', {
    capture_heatmaps: {
        // Less frequent flushing on high-traffic pages
        flush_interval_milliseconds: isHighTrafficPage ? 10000 : 5000
    }
});
```

### Combine with Feature Flags

Use feature flags to control heatmap collection:

```typescript
posthog.init('token');

// Check feature flag to enable heatmaps
posthog.onFeatureFlags(() => {
    if (posthog.isFeatureEnabled('enable-heatmaps')) {
        posthog.set_config({
            capture_heatmaps: true
        });
        posthog.heatmaps.startIfEnabled();
    }
});
```

### Privacy Considerations

Heatmaps respect your privacy settings:

```typescript
posthog.init('token', {
    capture_heatmaps: true,
    // Heatmaps will respect these settings
    mask_all_text: true,
    mask_all_element_attributes: true
});
```

## Common Patterns

### Gradual Rollout

```typescript
// Gradually enable heatmaps for users
posthog.init('token');

posthog.onFeatureFlags(() => {
    const heatmapVariant = posthog.getFeatureFlag('heatmap-rollout');

    if (heatmapVariant === 'enabled') {
        posthog.set_config({
            capture_heatmaps: true
        });
        posthog.heatmaps.startIfEnabled();
    }
});
```

### Page-Specific Heatmaps

```typescript
// Different settings for different page types
function configureHeatmapsForPage() {
    const path = window.location.pathname;

    if (path.startsWith('/checkout')) {
        // Detailed tracking for checkout
        posthog.set_config({
            capture_heatmaps: {
                flush_interval_milliseconds: 2000 // Fast flushing
            }
        });
    } else if (path.startsWith('/blog')) {
        // Basic tracking for content pages
        posthog.set_config({
            capture_heatmaps: {
                flush_interval_milliseconds: 10000 // Slower flushing
            }
        });
    }

    posthog.heatmaps.startIfEnabled();
}

// Call on route changes in SPAs
configureHeatmapsForPage();
```

### A/B Test Analysis

```typescript
// Use heatmaps to analyze different variants
posthog.init('token', {
    capture_heatmaps: true
});

// Tag heatmap data with experiment variant
posthog.register({
    ab_test_variant: posthog.getFeatureFlag('pricing-page-test')
});

// Analyze heatmaps for each variant in PostHog
```

### Performance Monitoring

```typescript
// Monitor heatmap collection performance
let heatmapStats = {
    flushes: 0,
    lastFlushTime: Date.now()
};

// Check flush interval
setInterval(() => {
    if (posthog.heatmaps.isEnabled) {
        heatmapStats.flushes++;
        const interval = Date.now() - heatmapStats.lastFlushTime;
        console.log(`Heatmap flush #${heatmapStats.flushes}, interval: ${interval}ms`);
        heatmapStats.lastFlushTime = Date.now();
    }
}, posthog.heatmaps.flushIntervalMilliseconds);
```

## Viewing Heatmap Data

Once enabled, heatmap data appears in PostHog's Toolbar:

1. Load the PostHog toolbar on your site
2. Navigate to the Heatmaps tab
3. View click heatmaps, rage clicks, and scroll depth
4. Filter by date range, URL, or user properties

## Performance Impact

Heatmaps have minimal performance impact:

- **Memory**: Buffers data locally before sending
- **Network**: Batches data and sends at intervals
- **CPU**: Lightweight event listeners for clicks and movements
- **Bandwidth**: Typically <10KB per flush

For optimal performance:
- Use appropriate flush intervals
- Enable only on important pages
- Combine with sampling if needed

## Troubleshooting

### Heatmaps Not Collecting

```typescript
// Check if enabled
console.log('Heatmaps enabled:', posthog.heatmaps.isEnabled);

// Force enable
posthog.set_config({
    capture_heatmaps: true
});
posthog.heatmaps.startIfEnabled();

// Check configuration
console.log('Flush interval:', posthog.heatmaps.flushIntervalMilliseconds);
```

### Server-Side Configuration

If heatmaps aren't enabled and `capture_heatmaps` is not set:

1. Check your PostHog project settings
2. Verify server-side remote config enables heatmaps
3. Override locally if needed:

```typescript
posthog.init('token', {
    capture_heatmaps: true // Force enable
});
```

### High Memory Usage

If experiencing high memory usage:

```typescript
// Reduce flush interval to send data more frequently
posthog.init('token', {
    capture_heatmaps: {
        flush_interval_milliseconds: 2000 // Flush more often
    }
});
```
