# Privacy & Consent

Privacy and consent management allows you to control tracking, respect user preferences, and comply with privacy regulations like GDPR and CCPA.

## Capabilities

### Opt In to Capturing

Opts the user into tracking and data capture.

```typescript { .api }
/**
 * Opts the user into tracking
 * @param options - Options for opt-in behavior
 */
function opt_in_capturing(options?: {
    captureEventName?: EventName | null | false;
    captureProperties?: Properties;
}): void;
```

**Usage Examples:**

```typescript
// Basic opt-in
posthog.opt_in_capturing();

// Opt-in with custom event
posthog.opt_in_capturing({
    captureEventName: 'user_opted_in',
    captureProperties: {
        opt_in_method: 'cookie_banner',
        timestamp: Date.now()
    }
});

// Opt-in without capturing event
posthog.opt_in_capturing({
    captureEventName: false
});

// Opt-in with consent categories
posthog.opt_in_capturing({
    captureEventName: 'consent_granted',
    captureProperties: {
        consent_analytics: true,
        consent_marketing: true,
        consent_preferences: true
    }
});
```

### Opt Out of Capturing

Opts the user out of tracking and data capture.

```typescript { .api }
/**
 * Opts the user out of tracking
 * Stops all event capture and deletes local data
 */
function opt_out_capturing(): void;
```

**Usage Examples:**

```typescript
// Opt out
posthog.opt_out_capturing();

// Opt out on user request
function onUserOptOut() {
    posthog.opt_out_capturing();
    showConfirmation('You have been opted out of tracking');
}

// Opt out with cleanup
function optOutAndClean() {
    posthog.opt_out_capturing();
    posthog.reset(true); // Also reset device ID
}
```

### Check Opt-In Status

Checks if the user has explicitly opted in to tracking.

```typescript { .api }
/**
 * Checks if the user has opted in to tracking
 * @returns True if user has opted in, false otherwise
 */
function has_opted_in_capturing(): boolean;
```

**Usage Examples:**

```typescript
// Check opt-in status
if (posthog.has_opted_in_capturing()) {
    console.log('User has opted in');
}

// Conditional tracking
function trackUserAction(action) {
    if (posthog.has_opted_in_capturing()) {
        posthog.capture(action);
    }
}

// UI state
function ConsentBanner() {
    const hasOptedIn = posthog.has_opted_in_capturing();
    return hasOptedIn ? null : <ConsentPrompt />;
}
```

### Check Opt-Out Status

Checks if the user has explicitly opted out of tracking.

```typescript { .api }
/**
 * Checks if the user has opted out of tracking
 * @returns True if user has opted out, false otherwise
 */
function has_opted_out_capturing(): boolean;
```

**Usage Examples:**

```typescript
// Check opt-out status
if (posthog.has_opted_out_capturing()) {
    console.log('User has opted out');
}

// Prevent tracking
function captureIfAllowed(event, properties) {
    if (!posthog.has_opted_out_capturing()) {
        posthog.capture(event, properties);
    }
}

// Show privacy status
function PrivacyStatus() {
    const hasOptedOut = posthog.has_opted_out_capturing();
    return (
        <div>
            Tracking: {hasOptedOut ? 'Disabled' : 'Enabled'}
        </div>
    );
}
```

### Get Explicit Consent Status

Gets the explicit consent status (granted, denied, or pending).

```typescript { .api }
/**
 * Gets the explicit consent status
 * @returns 'granted' if opted in, 'denied' if opted out, 'pending' if neither
 */
function get_explicit_consent_status(): 'granted' | 'denied' | 'pending';
```

**Usage Examples:**

```typescript
// Get consent status
const status = posthog.get_explicit_consent_status();
console.log('Consent status:', status);

// Handle all states
switch (posthog.get_explicit_consent_status()) {
    case 'granted':
        initializeAllFeatures();
        break;
    case 'denied':
        showMinimalFeatures();
        break;
    case 'pending':
        showConsentBanner();
        break;
}

// Conditional feature initialization
function initializeFeatures() {
    const consent = posthog.get_explicit_consent_status();

    if (consent === 'granted') {
        posthog.startSessionRecording();
        posthog.startExceptionAutocapture();
    } else if (consent === 'pending') {
        // Wait for user decision
        waitForConsent();
    }
}
```

### Check If Capturing Is Active

Checks if capturing is currently enabled (not opted out).

```typescript { .api }
/**
 * Checks if capturing is currently enabled
 * @returns True if capturing is active, false otherwise
 */
function is_capturing(): boolean;
```

**Usage Examples:**

```typescript
// Check if capturing
if (posthog.is_capturing()) {
    console.log('Capturing is active');
}

// Conditional operations
function performTrackedOperation() {
    const result = doOperation();

    if (posthog.is_capturing()) {
        posthog.capture('operation_completed');
    }

    return result;
}

// Debug logging
if (!posthog.is_capturing()) {
    console.warn('PostHog capturing is disabled');
}
```

### Clear Opt-In/Out Status

Clears the opt-in/out status, resetting to default behavior.

```typescript { .api }
/**
 * Clears the opt-in/out status
 * Resets to default capturing behavior based on config
 */
function clear_opt_in_out_capturing(): void;
```

**Usage Examples:**

```typescript
// Clear status
posthog.clear_opt_in_out_capturing();

// Reset consent state
function resetConsent() {
    posthog.clear_opt_in_out_capturing();
    showConsentBanner();
}

// Allow user to change decision
function changeConsentPreference() {
    posthog.clear_opt_in_out_capturing();
    // User can now choose again
    promptForConsent();
}
```

## Configuration

### Opt-Out by Default

Configure PostHog to start with capturing disabled:

```typescript { .api }
// Require opt-in before capturing
posthog.init('token', {
    opt_out_capturing_by_default: true
});

// User must explicitly opt in
// posthog.opt_in_capturing();

// Also disable persistence by default
posthog.init('token', {
    opt_out_capturing_by_default: true,
    opt_out_persistence_by_default: true
});
```

### Respect Do Not Track

Respect the browser's Do Not Track setting:

```typescript { .api }
posthog.init('token', {
    respect_dnt: true
});
```

### Cookieless Mode

Configure cookieless tracking:

```typescript { .api }
// Never use cookies/storage
posthog.init('token', {
    cookieless_mode: 'always'
});

// Use cookies unless user rejects
posthog.init('token', {
    cookieless_mode: 'on_reject'
});

// Always use cookies (default)
posthog.init('token', {
    cookieless_mode: 'never'
});
```

### Property Deny List

Prevent specific properties from being captured:

```typescript { .api }
posthog.init('token', {
    property_denylist: [
        'password',
        'credit_card',
        'ssn',
        'api_key',
        'secret'
    ]
});
```

### Mask Personal Data

Automatically mask personal data properties:

```typescript { .api }
posthog.init('token', {
    mask_personal_data_properties: true,
    custom_personal_data_properties: [
        'email',
        'phone',
        'address',
        'name'
    ]
});
```

## Best Practices

### GDPR Compliance

Implement GDPR-compliant consent:

```typescript
// Initialize with opt-out by default
posthog.init('token', {
    opt_out_capturing_by_default: true,
    opt_out_persistence_by_default: true
});

// Show consent banner
function showConsentBanner() {
    const banner = document.createElement('div');
    banner.innerHTML = `
        <div class="consent-banner">
            <p>We use cookies for analytics. Accept?</p>
            <button id="accept">Accept</button>
            <button id="reject">Reject</button>
        </div>
    `;

    document.getElementById('accept').addEventListener('click', () => {
        posthog.opt_in_capturing({
            captureEventName: 'gdpr_consent_granted'
        });
        banner.remove();
    });

    document.getElementById('reject').addEventListener('click', () => {
        posthog.opt_out_capturing();
        banner.remove();
    });

    document.body.appendChild(banner);
}

// Check consent on page load
if (posthog.get_explicit_consent_status() === 'pending') {
    showConsentBanner();
}
```

### CCPA Compliance

Implement CCPA "Do Not Sell" option:

```typescript
// Show "Do Not Sell My Personal Information" link
function showCCPALink() {
    const link = document.createElement('a');
    link.textContent = 'Do Not Sell My Personal Information';
    link.href = '#';

    link.addEventListener('click', (e) => {
        e.preventDefault();
        posthog.opt_out_capturing();
        alert('You have opted out of personal information sale');
    });

    document.body.appendChild(link);
}

// Allow users to check and change status
function showPrivacyDashboard() {
    const hasOptedOut = posthog.has_opted_out_capturing();

    if (hasOptedOut) {
        showOptInButton();
    } else {
        showOptOutButton();
    }
}
```

### Granular Consent

Implement consent for specific tracking features:

```typescript
class ConsentManager {
    constructor() {
        this.consent = {
            analytics: false,
            advertising: false,
            personalization: false,
            sessionRecording: false,
            errorTracking: false
        };
    }

    updateConsent(category, granted) {
        this.consent[category] = granted;
        this.applyConsent();
    }

    applyConsent() {
        // Basic analytics
        if (this.consent.analytics) {
            posthog.opt_in_capturing();
        } else {
            posthog.opt_out_capturing();
        }

        // Session recording
        if (this.consent.sessionRecording) {
            posthog.startSessionRecording();
        } else {
            posthog.stopSessionRecording();
        }

        // Error tracking
        if (this.consent.errorTracking) {
            posthog.startExceptionAutocapture();
        } else {
            posthog.stopExceptionAutocapture();
        }
    }

    getConsentState() {
        return { ...this.consent };
    }
}

// Usage
const consentManager = new ConsentManager();

consentManager.updateConsent('analytics', true);
consentManager.updateConsent('sessionRecording', true);
consentManager.updateConsent('errorTracking', false);
```

### Consent UI Components

Build reusable consent components:

```typescript
// React consent banner
function ConsentBanner() {
    const [visible, setVisible] = useState(true);

    useEffect(() => {
        const status = posthog.get_explicit_consent_status();
        if (status !== 'pending') {
            setVisible(false);
        }
    }, []);

    const handleAccept = () => {
        posthog.opt_in_capturing({
            captureEventName: 'consent_accepted'
        });
        setVisible(false);
    };

    const handleReject = () => {
        posthog.opt_out_capturing();
        setVisible(false);
    };

    if (!visible) return null;

    return (
        <div className="consent-banner">
            <p>We use cookies to improve your experience.</p>
            <button onClick={handleAccept}>Accept</button>
            <button onClick={handleReject}>Reject</button>
        </div>
    );
}

// Privacy settings page
function PrivacySettings() {
    const [capturing, setCapturing] = useState(posthog.is_capturing());

    const handleToggle = () => {
        if (capturing) {
            posthog.opt_out_capturing();
            setCapturing(false);
        } else {
            posthog.opt_in_capturing();
            setCapturing(true);
        }
    };

    return (
        <div>
            <h2>Privacy Settings</h2>
            <label>
                <input
                    type="checkbox"
                    checked={capturing}
                    onChange={handleToggle}
                />
                Enable Analytics
            </label>
        </div>
    );
}
```

## Common Patterns

### Cookie Consent Integration

Integrate with cookie consent libraries:

```typescript
// OneTrust integration
window.OptanonWrapper = function() {
    const activeGroups = window.OnetrustActiveGroups;

    // Check if analytics cookies are accepted
    if (activeGroups.includes('C0002')) {
        posthog.opt_in_capturing({
            captureEventName: 'onetrust_consent_granted'
        });
    } else {
        posthog.opt_out_capturing();
    }
};

// CookieBot integration
window.addEventListener('CookiebotOnAccept', function() {
    if (Cookiebot.consent.statistics) {
        posthog.opt_in_capturing({
            captureEventName: 'cookiebot_consent_granted'
        });
    }
});

window.addEventListener('CookiebotOnDecline', function() {
    posthog.opt_out_capturing();
});

// Google Consent Mode integration
function updatePostHogConsent(consentSettings) {
    if (consentSettings.analytics_storage === 'granted') {
        posthog.opt_in_capturing();
    } else {
        posthog.opt_out_capturing();
    }
}

gtag('consent', 'default', {
    analytics_storage: 'denied'
});

gtag('consent', 'update', {
    analytics_storage: 'granted'
});

updatePostHogConsent({ analytics_storage: 'granted' });
```

### Conditional Feature Loading

Load features based on consent:

```typescript
async function initializeWithConsent() {
    const consent = posthog.get_explicit_consent_status();

    if (consent === 'pending') {
        // Wait for user decision
        await promptForConsent();
    }

    if (posthog.has_opted_in_capturing()) {
        // Load full features
        posthog.startSessionRecording();
        posthog.startExceptionAutocapture();

        // Load analytics-dependent features
        await loadUserRecommendations();
        await loadPersonalizedContent();
    } else {
        // Load minimal features
        showGenericContent();
    }
}
```

### Consent Expiration

Implement consent expiration:

```typescript
const CONSENT_EXPIRY_DAYS = 365;

function setConsentWithExpiry(granted) {
    const expiry = Date.now() + (CONSENT_EXPIRY_DAYS * 24 * 60 * 60 * 1000);

    localStorage.setItem('consent_expiry', expiry.toString());

    if (granted) {
        posthog.opt_in_capturing();
    } else {
        posthog.opt_out_capturing();
    }
}

function checkConsentExpiry() {
    const expiry = localStorage.getItem('consent_expiry');

    if (expiry && Date.now() > parseInt(expiry)) {
        // Consent expired, reset
        posthog.clear_opt_in_out_capturing();
        localStorage.removeItem('consent_expiry');
        showConsentBanner();
    }
}

// Check on page load
checkConsentExpiry();
```

### Geolocation-Based Consent

Show consent based on user location:

```typescript
async function initializeWithGeolocation() {
    const country = await getUserCountry();

    const gdprCountries = ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB'];

    if (gdprCountries.includes(country)) {
        // Require explicit consent for GDPR countries
        posthog.init('token', {
            opt_out_capturing_by_default: true
        });

        if (posthog.get_explicit_consent_status() === 'pending') {
            showGDPRConsentBanner();
        }
    } else {
        // Auto opt-in for non-GDPR countries (with opt-out option)
        posthog.init('token', {
            opt_out_capturing_by_default: false
        });

        showOptOutLink();
    }
}
```

### Consent Change Tracking

Track consent changes for audit:

```typescript
function trackConsentChange(oldStatus, newStatus) {
    // Log to backend for compliance
    fetch('/api/consent-log', {
        method: 'POST',
        body: JSON.stringify({
            user_id: posthog.get_distinct_id(),
            old_status: oldStatus,
            new_status: newStatus,
            timestamp: Date.now(),
            user_agent: navigator.userAgent
        })
    });
}

function optInWithTracking() {
    const oldStatus = posthog.get_explicit_consent_status();

    posthog.opt_in_capturing({
        captureEventName: 'consent_granted'
    });

    const newStatus = posthog.get_explicit_consent_status();
    trackConsentChange(oldStatus, newStatus);
}

function optOutWithTracking() {
    const oldStatus = posthog.get_explicit_consent_status();

    posthog.opt_out_capturing();

    const newStatus = posthog.get_explicit_consent_status();
    trackConsentChange(oldStatus, newStatus);
}
```

### Privacy-First Initialization

Initialize with maximum privacy by default:

```typescript
posthog.init('token', {
    // Require opt-in
    opt_out_capturing_by_default: true,
    opt_out_persistence_by_default: true,

    // Respect browser settings
    respect_dnt: true,

    // Cookieless mode
    cookieless_mode: 'always',

    // Disable features by default
    disable_session_recording: true,
    capture_exceptions: false,
    autocapture: false,

    // Mask all data
    mask_all_text: true,
    mask_all_element_attributes: true,
    property_denylist: [
        'email', 'name', 'phone', 'address',
        'credit_card', 'ssn', 'password'
    ]
});

// Enable features after consent
function onUserConsent() {
    posthog.opt_in_capturing();
    posthog.set_config({
        autocapture: true,
        capture_exceptions: true
    });
    posthog.startSessionRecording();
}
```

### Consent Persistence

Persist consent across sessions:

```typescript
class ConsentStorage {
    static save(status) {
        localStorage.setItem('posthog_consent', status);
        localStorage.setItem('posthog_consent_date', Date.now().toString());
    }

    static load() {
        return localStorage.getItem('posthog_consent');
    }

    static getDate() {
        return localStorage.getItem('posthog_consent_date');
    }

    static clear() {
        localStorage.removeItem('posthog_consent');
        localStorage.removeItem('posthog_consent_date');
    }
}

// Initialize with saved consent
function initializeWithSavedConsent() {
    const savedConsent = ConsentStorage.load();

    if (savedConsent === 'granted') {
        posthog.opt_in_capturing();
    } else if (savedConsent === 'denied') {
        posthog.opt_out_capturing();
    } else {
        // No saved consent, show banner
        showConsentBanner();
    }
}

// Save when consent changes
function handleConsentChange(granted) {
    if (granted) {
        posthog.opt_in_capturing();
        ConsentStorage.save('granted');
    } else {
        posthog.opt_out_capturing();
        ConsentStorage.save('denied');
    }
}
```

## Advanced Compliance Patterns

### Multi-Region Compliance

```typescript { .api }
// Handle different privacy laws by region
interface RegionConfig {
    requiresExplicitConsent: boolean;
    dataResidency: 'us' | 'eu';
    retentionDays: number;
}

const regionConfigs: Record<string, RegionConfig> = {
    'US': { requiresExplicitConsent: false, dataResidency: 'us', retentionDays: 730 },
    'GB': { requiresExplicitConsent: true, dataResidency: 'eu', retentionDays: 365 },
    'DE': { requiresExplicitConsent: true, dataResidency: 'eu', retentionDays: 365 },
    'FR': { requiresExplicitConsent: true, dataResidency: 'eu', retentionDays: 365 }
};

async function initializeWithRegionalCompliance() {
    const userRegion = await detectUserRegion();
    const config = regionConfigs[userRegion] || regionConfigs['US'];
    
    const apiHost = config.dataResidency === 'eu'
        ? 'https://eu.i.posthog.com'
        : 'https://us.i.posthog.com';
    
    posthog.init('token', {
        api_host: apiHost,
        opt_out_capturing_by_default: config.requiresExplicitConsent
    });
    
    if (config.requiresExplicitConsent) {
        const consent = getStoredConsent();
        if (!consent) {
            showConsentBanner();
        } else if (consent === 'granted') {
            posthog.opt_in_capturing();
        }
    }
}
```

### Consent Management Platform Integration

```typescript { .api }
// OneTrust CMP integration
declare global {
    interface Window {
        OneTrust?: {
            OnConsentChanged: (callback: () => void) => void;
        };
        OnetrustActiveGroups?: string;
    }
}

function initializeOneTrustIntegration() {
    // Check initial consent
    const checkConsent = () => {
        const activeGroups = window.OnetrustActiveGroups || '';
        const analyticsConsent = activeGroups.includes('C0002');
        
        if (analyticsConsent) {
            posthog.opt_in_capturing({
                captureEventName: 'onetrust_consent_granted',
                captureProperties: {
                    consent_groups: activeGroups
                }
            });
        } else {
            posthog.opt_out_capturing();
        }
    };
    
    // Check on load
    checkConsent();
    
    // Listen for changes
    window.OneTrust?.OnConsentChanged(() => {
        checkConsent();
    });
}
```

### California Consumer Privacy Act (CCPA) Compliance

```typescript { .api }
// Implement CCPA "Do Not Sell" functionality
class CCPACompliance {
    private readonly DO_NOT_SELL_KEY = 'ccpa_do_not_sell';
    
    initialize() {
        // Check if user has opted out of sale
        const doNotSell = localStorage.getItem(this.DO_NOT_SELL_KEY) === 'true';
        
        if (doNotSell) {
            this.optOutOfSale();
        }
        
        // Add "Do Not Sell" link to footer
        this.addDoNotSellLink();
    }
    
    optOutOfSale() {
        // Opt out of tracking
        posthog.opt_out_capturing();
        
        // Store preference
        localStorage.setItem(this.DO_NOT_SELL_KEY, 'true');
        
        // Capture opt-out event before disabling
        posthog.capture('ccpa_do_not_sell', {
            opted_out_at: new Date().toISOString()
        });
    }
    
    optInToSale() {
        // Opt back in
        posthog.opt_in_capturing({
            captureEventName: 'ccpa_sale_opted_in'
        });
        
        // Clear preference
        localStorage.removeItem(this.DO_NOT_SELL_KEY);
    }
    
    addDoNotSellLink() {
        const link = document.createElement('a');
        link.href = '#';
        link.textContent = 'Do Not Sell My Personal Information';
        link.className = 'ccpa-opt-out-link';
        
        link.addEventListener('click', (e) => {
            e.preventDefault();
            this.showOptOutModal();
        });
        
        document.querySelector('.footer')?.appendChild(link);
    }
    
    showOptOutModal() {
        const confirmed = confirm(
            'You are about to opt out of the sale of your personal information. Continue?'
        );
        
        if (confirmed) {
            this.optOutOfSale();
            alert('You have successfully opted out.');
        }
    }
}
```

### Children's Online Privacy Protection Act (COPPA) Compliance

```typescript { .api }
// Disable tracking for users under 13
function initializeCOPPACompliance(userAge?: number) {
    if (userAge && userAge < 13) {
        posthog.init('token', {
            // Completely disable tracking for children
            opt_out_capturing_by_default: true,
            opt_out_persistence_by_default: true,
            disable_persistence: true,
            disable_session_recording: true,
            disable_surveys: true,
            autocapture: false,
            capture_pageview: false
        });
        
        // Ensure opt-out is persistent
        posthog.opt_out_capturing();
        
        console.log('COPPA compliance mode: Tracking disabled for user under 13');
    } else {
        // Normal initialization for adults
        posthog.init('token', {
            opt_out_capturing_by_default: true
        });
        
        // Show age-appropriate consent
        showAdultConsentBanner();
    }
}
```

## Data Subject Rights Implementation

### Right to Access

```typescript { .api }
// Provide user access to their data
async function getUserData() {
    const distinctId = posthog.get_distinct_id();
    const groups = posthog.getGroups();
    
    return {
        distinct_id: distinctId,
        groups: groups,
        // Note: Full data export must be done via PostHog API
        posthog_profile_url: `https://app.posthog.com/person/${distinctId}`
    };
}
```

### Right to Deletion

```typescript { .api }
// Handle deletion request
async function handleDeletionRequest(userId: string) {
    // Reset local state
    posthog.reset(true);  // Reset including device ID
    
    // Opt out to prevent future tracking
    posthog.opt_out_capturing();
    
    // Clear all local storage
    Object.keys(localStorage).forEach(key => {
        if (key.startsWith('ph_')) {
            localStorage.removeItem(key);
        }
    });
    
    // Log deletion request for backend processing
    await logDeletionRequest(userId);
    
    console.log('User data deletion initiated');
}
```

### Right to Rectification

```typescript { .api }
// Update incorrect user properties
async function rectifyUserData(corrections: Properties) {
    // Update properties in PostHog
    posthog.setPersonProperties(corrections);
    
    // Log rectification for audit trail
    posthog.capture('data_rectified', {
        rectified_fields: Object.keys(corrections),
        rectified_at: new Date().toISOString()
    });
}
```

### Right to Portability

```typescript { .api }
// Export user data in portable format
async function exportUserData() {
    const userData = {
        distinct_id: posthog.get_distinct_id(),
        groups: posthog.getGroups(),
        session_id: posthog.get_session_id(),
        feature_flags: posthog.featureFlags.getFlagVariants(),
        // Note: Full event history requires PostHog API access
        export_date: new Date().toISOString()
    };
    
    // Convert to JSON for portability
    const dataBlob = new Blob(
        [JSON.stringify(userData, null, 2)],
        { type: 'application/json' }
    );
    
    // Download file
    const url = URL.createObjectURL(dataBlob);
    const link = document.createElement('a');
    link.href = url;
    link.download = `posthog-data-${userData.distinct_id}.json`;
    link.click();
    
    URL.revokeObjectURL(url);
}
```

## Consent Lifecycle Management

### Complete Consent Flow

```typescript { .api }
class ConsentLifecycleManager {
    private readonly CONSENT_VERSION = '2.0';
    
    initialize() {
        const stored = this.getStoredConsent();
        
        if (!stored || stored.version !== this.CONSENT_VERSION) {
            // No consent or version changed, show banner
            this.showConsentBanner();
        } else {
            // Apply stored consent
            this.applyConsent(stored.granted);
        }
    }
    
    showConsentBanner() {
        // Show UI with granular options
        const banner = this.createGranularConsentUI({
            onSave: (choices) => {
                this.saveConsent(choices);
                this.applyConsent(choices.analytics);
            }
        });
    }
    
    saveConsent(choices: {
        analytics: boolean;
        marketing: boolean;
        functional: boolean;
    }) {
        const consent = {
            version: this.CONSENT_VERSION,
            granted: choices.analytics,
            choices: choices,
            timestamp: new Date().toISOString()
        };
        
        localStorage.setItem('posthog_consent', JSON.stringify(consent));
    }
    
    getStoredConsent(): {
        version: string;
        granted: boolean;
        choices: any;
        timestamp: string;
    } | null {
        const stored = localStorage.getItem('posthog_consent');
        return stored ? JSON.parse(stored) : null;
    }
    
    applyConsent(granted: boolean) {
        if (granted) {
            posthog.opt_in_capturing({
                captureEventName: 'consent_applied',
                captureProperties: {
                    consent_version: this.CONSENT_VERSION
                }
            });
        } else {
            posthog.opt_out_capturing();
        }
    }
    
    revokeConsent() {
        // Revoke consent and delete data
        posthog.opt_out_capturing();
        posthog.reset(true);
        localStorage.removeItem('posthog_consent');
        
        console.log('Consent revoked and data cleared');
    }
    
    createGranularConsentUI(options: any) {
        // Implementation of granular consent UI
        // Returns banner element
    }
}
```

## Testing Privacy Compliance

### Automated Compliance Tests

```typescript { .api }
describe('Privacy Compliance', () => {
    it('requires opt-in before tracking', () => {
        posthog.init('token', {
            opt_out_capturing_by_default: true
        });
        
        expect(posthog.is_capturing()).toBe(false);
        
        posthog.opt_in_capturing();
        
        expect(posthog.is_capturing()).toBe(true);
    });
    
    it('respects Do Not Track', () => {
        // Mock DNT
        Object.defineProperty(navigator, 'doNotTrack', {
            value: '1',
            configurable: true
        });
        
        posthog.init('token', {
            respect_dnt: true
        });
        
        expect(posthog.is_capturing()).toBe(false);
    });
    
    it('deletes data on opt-out', () => {
        posthog.init('token');
        posthog.identify('user-123');
        
        const distinctIdBefore = posthog.get_distinct_id();
        
        posthog.opt_out_capturing();
        
        // Should clear local data
        expect(posthog.is_capturing()).toBe(false);
    });
});
```

## Troubleshooting Privacy Issues

### Consent Not Persisting

```typescript { .api }
// Debug consent persistence
function debugConsent() {
    console.log('Consent status:', posthog.get_explicit_consent_status());
    console.log('Has opted in:', posthog.has_opted_in_capturing());
    console.log('Has opted out:', posthog.has_opted_out_capturing());
    console.log('Is capturing:', posthog.is_capturing());
    
    // Check storage
    console.log('Consent storage:', {
        localStorage: localStorage.getItem('__ph_consent'),
        cookie: document.cookie.includes('ph_consent')
    });
    
    // Check config
    console.log('Config:', {
        opt_out_by_default: posthog.config.opt_out_capturing_by_default,
        consent_name: posthog.config.consent_persistence_name
    });
}
```

### Opt-Out Not Working

```typescript { .api }
// Verify opt-out
function verifyOptOut() {
    posthog.opt_out_capturing();
    
    // Wait for state to update
    setTimeout(() => {
        console.log('Opt-out verification:', {
            is_capturing: posthog.is_capturing(),
            has_opted_out: posthog.has_opted_out_capturing(),
            status: posthog.get_explicit_consent_status()
        });
        
        // Try capturing event (should fail)
        const result = posthog.capture('test_event');
        console.log('Capture after opt-out:', result);  // Should be undefined or void
    }, 100);
}
```

### DNT Not Respected

```typescript { .api }
// Force DNT respect
function enforceDNT() {
    if (navigator.doNotTrack === '1' || 
        (navigator as any).doNotTrack === 'yes' ||
        (window as any).doNotTrack === '1') {
        
        console.log('DNT detected, disabling tracking');
        
        posthog.opt_out_capturing();
        
        // Ensure it can't be overridden
        const originalOptIn = posthog.opt_in_capturing;
        posthog.opt_in_capturing = () => {
            console.warn('Opt-in blocked due to DNT');
        };
    }
}
```

## Cookie Consent Library Integrations

### Cookiebot Integration

```typescript { .api }
// Full Cookiebot integration
declare global {
    interface Window {
        Cookiebot?: {
            consent: {
                necessary: boolean;
                preferences: boolean;
                statistics: boolean;
                marketing: boolean;
            };
            consented: boolean;
        };
    }
}

function initializeCookiebotIntegration() {
    posthog.init('token', {
        opt_out_capturing_by_default: true
    });
    
    // Handle consent acceptance
    window.addEventListener('CookiebotOnAccept', () => {
        if (window.Cookiebot?.consent.statistics) {
            posthog.opt_in_capturing({
                captureEventName: 'cookiebot_consent_granted',
                captureProperties: {
                    consent_preferences: window.Cookiebot.consent.preferences,
                    consent_marketing: window.Cookiebot.consent.marketing
                }
            });
            
            // Enable features based on consent
            if (window.Cookiebot.consent.statistics) {
                posthog.startSessionRecording();
            }
        }
    });
    
    // Handle consent decline
    window.addEventListener('CookiebotOnDecline', () => {
        posthog.opt_out_capturing();
        posthog.stopSessionRecording();
    });
    
    // Check if already consented
    if (window.Cookiebot?.consented && window.Cookiebot?.consent.statistics) {
        posthog.opt_in_capturing();
    }
}
```

### Usercentrics Integration

```typescript { .api }
// Usercentrics CMP integration
declare global {
    interface Window {
        UC_UI?: {
            isInitialized: () => boolean;
            getServicesBaseInfo: () => Array<{
                id: string;
                name: string;
                consent: { status: boolean };
            }>;
        };
    }
}

function initializeUsercentricsIntegration() {
    const POSTHOG_SERVICE_ID = 'PostHog';
    
    posthog.init('token', {
        opt_out_capturing_by_default: true
    });
    
    // Wait for Usercentrics
    const checkConsent = () => {
        if (window.UC_UI?.isInitialized()) {
            const services = window.UC_UI.getServicesBaseInfo();
            const posthogService = services.find(s => s.name === POSTHOG_SERVICE_ID);
            
            if (posthogService?.consent.status) {
                posthog.opt_in_capturing({
                    captureEventName: 'usercentrics_consent_granted'
                });
            } else {
                posthog.opt_out_capturing();
            }
        } else {
            // Retry
            setTimeout(checkConsent, 100);
        }
    };
    
    checkConsent();
    
    // Listen for consent changes
    window.addEventListener('ucEvent', (event: any) => {
        if (event.detail?.event === 'consent_status') {
            checkConsent();
        }
    });
}
```

## Privacy Policy Requirements

### Essential Disclosures

Your privacy policy should disclose:

1. **Data Collection**: What data PostHog collects (events, properties, device info)
2. **Purpose**: Why you're collecting it (analytics, product improvement)
3. **Storage**: Where data is stored (US/EU regions)
4. **Retention**: How long data is kept
5. **Third Parties**: That PostHog (third-party service) processes the data
6. **Rights**: User rights (access, deletion, opt-out)
7. **Cookies**: That cookies/localStorage are used for tracking

### Privacy Policy Template Section

```
Analytics and Tracking

We use PostHog to understand how users interact with our application. PostHog collects:
- Page views and navigation patterns
- Button clicks and user interactions
- Device information (browser, OS, screen size)
- Session recordings (with sensitive data masked)

This data is processed by PostHog Inc. and stored in [US/EU] data centers. You can opt out of tracking at any time through our privacy settings.

For more information, see PostHog's privacy policy: https://posthog.com/privacy
```

## See Also

- [Initialization](./initialization.md) - Privacy-focused configuration
- [Session Recording](./session-recording.md) - Recording privacy settings
- [Events](./events.md) - Event filtering and property denylists
- [Advanced Features](./advanced.md) - Group analytics and consent management
