# Initialization

Initialization and configuration of the PostHog SDK.

## Capabilities

### Initialize PostHog Instance

Creates and initializes a PostHog instance with your project API key and optional configuration.

```typescript { .api }
/**
 * Initializes a new instance of the PostHog capturing object
 * @param token - Your PostHog API token
 * @param config - Configuration options
 * @param name - Optional name for the instance (for multiple instances)
 * @returns The initialized PostHog instance
 */
function init(
    token: string,
    config?: Partial<PostHogConfig>,
    name?: string
): PostHog;
```

**Usage Example:**

```typescript
import posthog from 'posthog-js';

// Basic initialization
posthog.init('<your-project-api-key>', {
    api_host: 'https://us.i.posthog.com'
});

// With configuration
posthog.init('<your-project-api-key>', {
    api_host: 'https://us.i.posthog.com',
    autocapture: true,
    capture_pageview: true,
    loaded: (posthog) => {
        console.log('PostHog is ready!');
        // You can safely use posthog here
    }
});

// Create a named instance
posthog.init('<secondary-token>', {
    api_host: 'https://us.i.posthog.com'
}, 'secondary');

// Use the named instance
posthog.secondary.capture('event');
```

### Update Configuration

Updates the configuration of an already initialized PostHog instance.

```typescript { .api }
/**
 * Updates PostHog configuration after initialization
 * @param config - Partial configuration to update
 */
function set_config(config: Partial<PostHogConfig>): void;
```

**Usage Example:**

```typescript
posthog.set_config({
    disable_session_recording: true,
    capture_pageview: false
});
```

### Debug Mode

Enables or disables debug logging for troubleshooting.

```typescript { .api }
/**
 * Enable or disable debug mode
 * @param debug - True to enable, false to disable
 */
function debug(debug?: boolean): void;
```

**Usage Example:**

```typescript
// Enable debug mode
posthog.debug(true);

// Disable debug mode
posthog.debug(false);
```

## Configuration Types

### PostHogConfig

Main configuration interface with extensive options for controlling SDK behavior.

```typescript { .api }
interface PostHogConfig {
    // ============================================================
    // Core Configuration
    // ============================================================

    /**
     * PostHog API host
     * @default 'https://us.i.posthog.com'
     */
    api_host?: string;

    /**
     * Project API key (token)
     */
    token?: string;

    /**
     * Callback invoked when the SDK is fully loaded
     */
    loaded?: (posthog: PostHog) => void;

    /**
     * Name for this PostHog instance (for multiple instances)
     * @default 'posthog'
     */
    name?: string;

    // ============================================================
    // Event Capture Configuration
    // ============================================================

    /**
     * Automatically capture page views
     * - true: Capture on initial load only
     * - 'history_change': Capture on URL changes (for SPAs)
     * - false: Disable automatic page view capture
     * @default true
     */
    capture_pageview?: boolean | 'history_change';

    /**
     * Automatically capture page leave events
     * - true: Always capture
     * - 'if_capture_pageview': Only if capture_pageview is enabled
     * - false: Never capture
     * @default 'if_capture_pageview'
     */
    capture_pageleave?: boolean | 'if_capture_pageview';

    /**
     * Automatically capture click events
     * @default true
     */
    autocapture?: boolean | AutocaptureConfig;

    /**
     * Automatically capture exceptions
     * @default false
     */
    capture_exceptions?: boolean | ExceptionAutoCaptureConfig;

    // ============================================================
    // Storage & Persistence Configuration
    // ============================================================

    /**
     * Storage mechanism for user data
     * - 'cookie': Use cookies only
     * - 'localStorage': Use localStorage only
     * - 'sessionStorage': Use sessionStorage only
     * - 'memory': In-memory only (no persistence)
     * - 'localStorage+cookie': Try localStorage, fall back to cookie
     * @default 'localStorage+cookie'
     */
    persistence?: 'cookie' | 'localStorage' | 'sessionStorage' | 'memory' | 'localStorage+cookie';

    /**
     * Completely disable persistence
     * @default false
     */
    disable_persistence?: boolean;

    /**
     * Custom name for the persistence storage
     * @default 'ph_{token}'
     */
    persistence_name?: string;

    /**
     * Cookie expiration in days
     * @default 365
     */
    cookie_expiration?: number;

    /**
     * Use secure cookies (HTTPS only)
     * @default true if on HTTPS
     */
    secure_cookie?: boolean;

    /**
     * Allow cross-subdomain cookies
     * @default Automatically detected
     */
    cross_subdomain_cookie?: boolean;

    /**
     * Properties to persist in cookies (when using localStorage+cookie)
     * @default []
     */
    cookie_persisted_properties?: string[];

    // ============================================================
    // Privacy & Consent Configuration
    // ============================================================

    /**
     * Start with capturing disabled (user must opt in)
     * @default false
     */
    opt_out_capturing_by_default?: boolean;

    /**
     * Start with persistence disabled
     * @default false
     */
    opt_out_persistence_by_default?: boolean;

    /**
     * Respect Do Not Track browser setting
     * @default false
     */
    respect_dnt?: boolean;

    /**
     * Cookieless tracking mode
     * - 'never': Always use cookies/storage
     * - 'always': Never use cookies/storage
     * - 'on_reject': Use cookies unless user rejects
     * @default 'never'
     */
    cookieless_mode?: 'never' | 'always' | 'on_reject';

    /**
     * Custom storage key for consent persistence
     * @default '__ph_consent'
     */
    consent_persistence_name?: string;

    /**
     * Persistence type for opt-out/opt-in status
     * @default 'localStorage'
     */
    opt_out_capturing_persistence_type?: 'localStorage' | 'cookie';

    /**
     * Custom prefix for opt-out cookie (deprecated, use consent_persistence_name)
     * @deprecated
     */
    opt_out_capturing_cookie_prefix?: string;

    /**
     * Properties to never capture
     * @default []
     */
    property_denylist?: string[];

    /**
     * Mask all personal data properties
     * @default false
     */
    mask_personal_data_properties?: boolean;

    /**
     * Custom list of personal data properties to mask
     * @default []
     */
    custom_personal_data_properties?: string[];

    // ============================================================
    // Feature Flags Configuration
    // ============================================================

    /**
     * Disable all feature flag functionality
     * @default false
     */
    advanced_disable_feature_flags?: boolean;

    /**
     * Disable feature flag loading on first page load
     * @default false
     */
    advanced_disable_feature_flags_on_first_load?: boolean;

    /**
     * Disable all /decide endpoint calls
     * @default false
     */
    advanced_disable_decide?: boolean;

    /**
     * Only evaluate feature flags for surveys (not general flags)
     * @default false
     */
    advanced_only_evaluate_survey_feature_flags?: boolean;

    /**
     * Timeout for feature flag requests in milliseconds
     * @default 3000
     */
    feature_flag_request_timeout_ms?: number;

    /**
     * Override API host for feature flag requests
     * @default null (uses api_host)
     */
    flags_api_host?: string | null;

    // ============================================================
    // Session Recording Configuration
    // ============================================================

    /**
     * Disable session recording
     * @default false
     */
    disable_session_recording?: boolean;

    /**
     * Detailed session recording configuration
     */
    session_recording?: SessionRecordingOptions;

    // ============================================================
    // Request Configuration
    // ============================================================

    /**
     * Enable request batching
     * @default true
     */
    request_batching?: boolean;

    /**
     * Maximum number of events per batch
     * @default 50
     */
    batch_size?: number;

    /**
     * Maximum time to wait before sending a batch (milliseconds)
     * @default 30000
     */
    batch_max_wait_ms?: number;

    /**
     * Custom HTTP headers for requests
     * @default {}
     */
    request_headers?: Record<string, string>;

    /**
     * Disable compression
     * @default false
     */
    disable_compression?: boolean;

    /**
     * Request queue configuration
     */
    request_queue_config?: {
        /**
         * Flush interval in milliseconds
         * @default 3000
         */
        flush_interval_ms?: number;
    };

    /**
     * Error callback for failed requests
     */
    on_request_error?: (response: RequestResponse) => void;

    // ============================================================
    // Session Configuration
    // ============================================================

    /**
     * Session idle timeout in seconds
     * @default 1800 (30 minutes)
     */
    session_idle_timeout_seconds?: number;

    // ============================================================
    // Person Profiles Configuration
    // ============================================================

    /**
     * When to create person profiles
     * - 'always': Create for all users
     * - 'identified_only': Only after identify() is called
     * - 'never': Never create person profiles
     * @default 'identified_only'
     */
    person_profiles?: 'always' | 'identified_only' | 'never';

    // ============================================================
    // Other Configuration
    // ============================================================

    /**
     * Enable debug logging
     * @default false
     */
    debug?: boolean;

    /**
     * Automatically save UTM parameters as user properties
     * @default true
     */
    save_campaign_params?: boolean;

    /**
     * Custom campaign parameter names to capture
     * @default ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']
     */
    custom_campaign_params?: string[];

    /**
     * Save referrer as user property
     * @default true
     */
    save_referrer?: boolean;

    /**
     * Maximum string length for properties
     * @default 65535
     */
    properties_string_max_length?: number;

    /**
     * Callback to modify events before sending
     */
    before_send?: BeforeSendFn;

    /**
     * Custom device ID generator
     */
    get_device_id?: (uuid: string) => string;

    /**
     * Mask all element attributes in session recordings
     * @default false
     */
    mask_all_element_attributes?: boolean;

    /**
     * Mask all text content in session recordings
     * @default false
     */
    mask_all_text?: boolean;

    /**
     * Bootstrap configuration with preloaded data
     */
    bootstrap?: BootstrapConfig;

    /**
     * UI host for viewing data (toolbar, etc.)
     * @default null (uses api_host)
     */
    ui_host?: string | null;

    /**
     * Disable surveys
     * @default false
     */
    disable_surveys?: boolean;

    /**
     * Disable automatic survey display
     * @default false
     */
    disable_surveys_automatic_display?: boolean;

    /**
     * Timeout for survey requests in milliseconds
     * @default 5000
     */
    surveys_request_timeout_ms?: number;

    /**
     * Disable conversations
     * @default false
     */
    disable_conversations?: boolean;

    /**
     * Disable product tours
     * @default true
     */
    disable_product_tours?: boolean;

    /**
     * Disable web experiments (A/B tests with DOM transforms)
     * @default false
     */
    disable_web_experiments?: boolean;

    /**
     * Configure heatmaps data collection
     * - true: Enable heatmaps
     * - false: Disable heatmaps
     * - object: Enable with custom configuration
     * - undefined: Use server-side configuration (default)
     * @default undefined
     */
    capture_heatmaps?: boolean | {
        /**
         * How often to send heatmap data to server (milliseconds)
         * @default 5000
         */
        flush_interval_milliseconds?: number;
    };

    /**
     * Disable loading external dependencies
     * @default false
     */
    disable_external_dependency_loading?: boolean;

    /**
     * Config defaults version (controls default values)
     * @default 'unset'
     */
    defaults?: ConfigDefaults | 'unset';
}
```

### AutocaptureConfig

Configuration for automatic event capture.

```typescript { .api }
interface AutocaptureConfig {
    /**
     * Capture click events
     * @default true
     */
    capture_clicks?: boolean;

    /**
     * Capture text content of clicked elements
     * @default true
     */
    capture_text_content?: boolean;

    /**
     * CSS selectors to allow for autocapture (only these will be captured)
     */
    element_allowlist?: string[] | undefined;

    /**
     * CSS selectors to exclude from autocapture
     * @default []
     */
    element_denylist?: string[];

    /**
     * Capture rage clicks (rapid repeated clicks)
     * @default true
     */
    rageclicks?: boolean | RageclickConfig;

    /**
     * Capture dead clicks (clicks that don't cause changes)
     * @default false
     */
    dead_clicks?: boolean | DeadClicksAutoCaptureConfig;
}
```

### SessionRecordingOptions

Configuration for session recording.

```typescript { .api }
interface SessionRecordingOptions {
    /**
     * Enable session recording
     * @default undefined (uses server-side config)
     */
    enabled?: boolean;

    /**
     * Mask all input fields
     * @default false
     */
    maskAllInputs?: boolean;

    /**
     * CSS selector for text elements to mask
     */
    maskTextSelector?: string;

    /**
     * CSS selector for elements to completely block from recording
     */
    blockSelector?: string;

    /**
     * Record cross-origin iframes
     * @default false
     */
    recordCrossOriginIframes?: boolean;

    /**
     * Sample rate (0-1) for session recording
     */
    sampleRate?: number;

    /**
     * Minimum session duration to record (milliseconds)
     */
    minimumDurationMilliseconds?: number;

    /**
     * Linked feature flag for session recording
     */
    linkedFlag?: string | FlagVariant;

    /**
     * Enable canvas recording
     */
    recordCanvas?: boolean;

    /**
     * Capture console logs in recordings
     */
    consoleLogRecordingEnabled?: boolean;

    /**
     * Capture network activity
     */
    networkPayloadCapture?: {
        recordHeaders?: boolean | { request: boolean; response: boolean };
        recordBody?: boolean | string[] | {
            request: boolean | string[];
            response: boolean | string[];
        };
    };
}
```

### ExceptionAutoCaptureConfig

Configuration for automatic exception capture.

```typescript { .api }
interface ExceptionAutoCaptureConfig {
    /**
     * Capture uncaught errors
     * @default true
     */
    capture_unhandled_errors?: boolean;

    /**
     * Capture unhandled promise rejections
     * @default true
     */
    capture_unhandled_rejections?: boolean;

    /**
     * Capture console.error calls
     * @default false
     */
    capture_console_errors?: boolean;
}
```

### BootstrapConfig

Configuration for bootstrapping the SDK with preloaded data.

```typescript { .api }
interface BootstrapConfig {
    /**
     * Preloaded distinct ID
     */
    distinctID?: string;

    /**
     * Preloaded feature flags
     */
    featureFlags?: Record<string, boolean | string>;

    /**
     * Preloaded feature flag payloads
     */
    featureFlagPayloads?: Record<string, JsonType>;

    /**
     * Whether flags have been fully evaluated
     */
    isIdentifiedID?: boolean;
}
```

### BeforeSendFn

Function to modify or block events before sending.

```typescript { .api }
/**
 * Callback to modify events before sending
 * Return null to block the event from being sent
 */
type BeforeSendFn = (data: CaptureResult) => CaptureResult | null;
```

## Configuration Validation

### Required Configuration

```typescript { .api }
// ✅ Minimum required configuration
posthog.init('<your-project-api-key>');

// ❌ Missing API key will fail
posthog.init(); // Error: API key required
```

### Configuration Conflicts

```typescript { .api }
// ❌ Conflicting settings
posthog.init('token', {
    disable_persistence: true,
    persistence: 'localStorage'  // Ignored when disable_persistence is true
});

// ✅ Consistent settings
posthog.init('token', {
    disable_persistence: false,
    persistence: 'localStorage'
});
```

### Environment-Specific Configuration

```typescript { .api }
// Development configuration
const devConfig: Partial<PostHogConfig> = {
    debug: true,
    disable_compression: true,
    advanced_disable_toolbar_metrics: false,
    session_recording: {
        enabled: true,
        consoleLogRecordingEnabled: true
    }
};

// Production configuration
const prodConfig: Partial<PostHogConfig> = {
    debug: false,
    disable_compression: false,
    advanced_disable_toolbar_metrics: true,
    session_recording: {
        enabled: true,
        maskAllInputs: true,
        consoleLogRecordingEnabled: false
    }
};

const config = process.env.NODE_ENV === 'production' ? prodConfig : devConfig;
posthog.init('token', config);
```

## Edge Cases & Error Handling

### Network Errors

```typescript { .api }
// Handle initialization in offline scenarios
posthog.init('token', {
    on_request_error: (response) => {
        console.error('PostHog request failed:', response);
        // Log to error tracking service
        logToErrorService({
            error: 'PostHog request failed',
            status: response.statusCode,
            statusText: response.statusText
        });
    }
});
```

### Browser Storage Unavailable

```typescript { .api }
// Fallback when localStorage is blocked
try {
    posthog.init('token', {
        persistence: 'localStorage+cookie'
    });
} catch (error) {
    // Fall back to memory-only persistence
    console.warn('Storage blocked, using memory persistence');
    posthog.init('token', {
        persistence: 'memory'
    });
}
```

### API Host Connectivity

```typescript { .api }
// Test connectivity before full initialization
async function initWithConnectivityCheck() {
    const apiHost = 'https://us.i.posthog.com';
    
    try {
        const response = await fetch(`${apiHost}/decide/`, {
            method: 'HEAD',
            mode: 'no-cors'
        });
        
        // Initialize with standard config
        posthog.init('token', {
            api_host: apiHost
        });
    } catch (error) {
        console.error('PostHog API unreachable:', error);
        
        // Initialize in degraded mode
        posthog.init('token', {
            api_host: apiHost,
            request_batching: true,
            batch_max_wait_ms: 60000  // Longer wait for batch
        });
    }
}
```

### Multiple Initialization Attempts

```typescript { .api }
// Prevent multiple initialization
let posthogInitialized = false;

function safeInit() {
    if (posthogInitialized) {
        console.warn('PostHog already initialized');
        return;
    }
    
    posthog.init('token', {
        loaded: () => {
            posthogInitialized = true;
            console.log('PostHog initialized successfully');
        }
    });
}

// Safe to call multiple times
safeInit();
safeInit(); // Will warn and skip
```

### Async Module Loading

```typescript { .api }
// Handle async script loading
async function initPostHogAsync() {
    // Dynamically import PostHog
    const { default: posthog } = await import('posthog-js');
    
    return new Promise((resolve) => {
        posthog.init('token', {
            loaded: (ph) => {
                console.log('PostHog loaded asynchronously');
                resolve(ph);
            }
        });
    });
}

// Usage
const posthog = await initPostHogAsync();
posthog.capture('app_loaded');
```

## Configuration Best Practices

### Type-Safe Configuration

```typescript { .api }
import { PostHogConfig } from 'posthog-js';

// Create typed configuration
const createConfig = (env: 'dev' | 'prod'): Partial<PostHogConfig> => {
    const baseConfig: Partial<PostHogConfig> = {
        api_host: 'https://us.i.posthog.com',
        autocapture: true,
        capture_pageview: true
    };
    
    if (env === 'dev') {
        return {
            ...baseConfig,
            debug: true,
            disable_session_recording: false
        };
    }
    
    return {
        ...baseConfig,
        debug: false,
        session_recording: {
            enabled: true,
            maskAllInputs: true
        }
    };
};

posthog.init('token', createConfig('prod'));
```

### Configuration Validation Function

```typescript { .api }
function validateConfig(config: Partial<PostHogConfig>): {
    valid: boolean;
    errors: string[];
} {
    const errors: string[] = [];
    
    // Check for conflicts
    if (config.disable_persistence && config.persistence !== 'memory') {
        errors.push('disable_persistence conflicts with persistence setting');
    }
    
    // Check for invalid values
    if (config.batch_size && config.batch_size < 1) {
        errors.push('batch_size must be positive');
    }
    
    if (config.session_idle_timeout_seconds && config.session_idle_timeout_seconds < 0) {
        errors.push('session_idle_timeout_seconds must be non-negative');
    }
    
    // Check for deprecated options
    if ('opt_out_capturing_cookie_prefix' in config) {
        errors.push('opt_out_capturing_cookie_prefix is deprecated, use consent_persistence_name');
    }
    
    return {
        valid: errors.length === 0,
        errors
    };
}

// Usage
const config = {
    api_host: 'https://us.i.posthog.com',
    batch_size: 50
};

const validation = validateConfig(config);
if (validation.valid) {
    posthog.init('token', config);
} else {
    console.error('Invalid configuration:', validation.errors);
}
```

### Dynamic Configuration Updates

```typescript { .api }
// Update configuration after initialization
function updateConfigBasedOnUserPreferences(preferences: {
    trackingEnabled: boolean;
    recordSessions: boolean;
    captureConsole: boolean;
}) {
    if (!preferences.trackingEnabled) {
        posthog.opt_out_capturing();
        return;
    }
    
    posthog.opt_in_capturing();
    
    posthog.set_config({
        session_recording: {
            enabled: preferences.recordSessions,
            consoleLogRecordingEnabled: preferences.captureConsole
        }
    });
    
    if (preferences.recordSessions) {
        posthog.startSessionRecording();
    } else {
        posthog.stopSessionRecording();
    }
}
```

## Troubleshooting Configuration Issues

### Debug Configuration

```typescript { .api }
// Enable debug mode to troubleshoot
posthog.debug(true);

// Check current configuration
console.log('Current config:', posthog.config);

// Verify API host connectivity
fetch(posthog.config.api_host + '/decide/', { method: 'HEAD' })
    .then(() => console.log('API host reachable'))
    .catch((e) => console.error('API host unreachable:', e));

// Check persistence
console.log('Persistence type:', posthog.config.persistence);
console.log('Storage available:', {
    localStorage: typeof window.localStorage !== 'undefined',
    sessionStorage: typeof window.sessionStorage !== 'undefined',
    cookies: navigator.cookieEnabled
});
```

### Common Configuration Errors

```typescript { .api }
// ❌ Common mistake: Wrong API host format
posthog.init('token', {
    api_host: 'us.i.posthog.com'  // Missing protocol
});

// ✅ Correct: Include protocol
posthog.init('token', {
    api_host: 'https://us.i.posthog.com'
});

// ❌ Common mistake: Conflicting batch settings
posthog.init('token', {
    request_batching: false,
    batch_size: 100  // Ignored when batching is disabled
});

// ✅ Correct: Consistent batch settings
posthog.init('token', {
    request_batching: true,
    batch_size: 100
});
```

### Configuration Migration

```typescript { .api }
// Migrate from old configuration format
function migrateConfig(oldConfig: any): Partial<PostHogConfig> {
    const newConfig: Partial<PostHogConfig> = {};
    
    // Map old properties to new ones
    if (oldConfig.disable_cookie) {
        newConfig.persistence = 'localStorage';
    }
    
    if (oldConfig.cross_subdomain_cookie !== undefined) {
        newConfig.cross_subdomain_cookie = oldConfig.cross_subdomain_cookie;
    }
    
    // Handle deprecated options
    if (oldConfig.opt_out_capturing_cookie_prefix) {
        newConfig.consent_persistence_name = oldConfig.opt_out_capturing_cookie_prefix;
    }
    
    return newConfig;
}

const oldConfig = {
    disable_cookie: true,
    opt_out_capturing_cookie_prefix: '__ph_opt_out'
};

const newConfig = migrateConfig(oldConfig);
posthog.init('token', newConfig);
```
