tessl install tessl/npm-posthog-js@1.335.0PostHog Browser JS Library is a comprehensive browser analytics and feature management SDK that enables developers to capture user events, track product analytics, manage feature flags, record session replays, and implement feedback mechanisms like surveys and conversations in web applications.
Initialization and configuration of the PostHog SDK.
Creates and initializes a PostHog instance with your project API key and optional configuration.
/**
* 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:
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');Updates the configuration of an already initialized PostHog instance.
/**
* Updates PostHog configuration after initialization
* @param config - Partial configuration to update
*/
function set_config(config: Partial<PostHogConfig>): void;Usage Example:
posthog.set_config({
disable_session_recording: true,
capture_pageview: false
});Enables or disables debug logging for troubleshooting.
/**
* Enable or disable debug mode
* @param debug - True to enable, false to disable
*/
function debug(debug?: boolean): void;Usage Example:
// Enable debug mode
posthog.debug(true);
// Disable debug mode
posthog.debug(false);Main configuration interface with extensive options for controlling SDK behavior.
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';
}Configuration for automatic event capture.
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;
}Configuration for session recording.
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[];
};
};
}Configuration for automatic exception capture.
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;
}Configuration for bootstrapping the SDK with preloaded data.
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;
}Function to modify or block events before sending.
/**
* Callback to modify events before sending
* Return null to block the event from being sent
*/
type BeforeSendFn = (data: CaptureResult) => CaptureResult | null;// ✅ Minimum required configuration
posthog.init('<your-project-api-key>');
// ❌ Missing API key will fail
posthog.init(); // Error: API key required// ❌ 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'
});// 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);// 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
});
}
});// 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'
});
}// 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
});
}
}// 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// 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');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'));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);
}// 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();
}
}// 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 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
});// 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);