UNPKG

posthog-js

Version:

Posthog-js allows you to automatically capture usage and send events to PostHog.

2,517 lines • 95.7 kB
import { PostHog } from './module';
import * as _posthog_browser_common from '@posthog/browser-common';
import { Extension as Extension$1, Client, DisplaySurveyType, SurveyPosition, Survey, PropertyMatchType, SurveyEventWithFilters, SurveyActionType, SurveyWithTypeAndAppearance, DeepReadonly, SendRequestInit, ApiResponse, Compression, RemoteConfigResult as RemoteConfigResult$1, RemoteConfig } from '@posthog/browser-common';
import { RageclickConfig, AutocaptureConfig as AutocaptureConfig$1, DeadClicksAutoCaptureConfig, SupportedWebVitalsMetrics, Properties, CaptureResult, SurveyRenderReason, ToolbarParams, JsonType, FeatureFlagsCallback, FeatureFlagDetail, FeatureFlagResult, FeatureFlagOptions, RemoteConfigFeatureFlagCallback, IsFeatureEnabledOptions, OverrideFeatureFlagsOptions, EarlyAccessFeatureCallback, EarlyAccessFeatureStage, CaptureLogOptions, Logger, CaptureMetricOptions, PostHog as PostHog$1, PostHogConfig as PostHogConfig$1, EventName, BeforeSendFn, KnownEventName } from '@posthog/types';
import { ErrorTracking, SurveyResponseValue as SurveyResponseValue$1, SurveyPosition as SurveyPosition$1, LogSdkContext } from '@posthog/core';
import { createLogger } from '@posthog/browser-common/utils/logger';

declare const SAMPLED = "sampled";
type TriggerType = 'url' | 'event';
/**
 * Session recording starts in buffering mode while waiting for "flags response".
 * Once the response is received, it might be disabled, active or sampled.
 * When "sampled" that means a sample rate is set, and the last time the session ID rotated
 * the sample rate determined this session should be sent to the server.
 */
declare const sessionRecordingStatuses: readonly ["disabled", "sampled", "active", "buffering", "paused", "lazy_loading", "awaiting_config", "missing_config", "rrweb_error"];
type SessionRecordingStatus = (typeof sessionRecordingStatuses)[number];

type ExtensionConstructor<T extends Extension> = new (instance: PostHog, ...args: any[]) => T;
interface Extension {
    initialize?(): boolean | void;
    /**
     * Receives the full remote config fetch result. Handlers must narrow on
     * `result.ok` before reading config fields, and encode their failure
     * behavior explicitly in the `!result.ok` branch.
     */
    onRemoteConfig?(result: RemoteConfigResult): void;
}

declare class RageClick {
    clicks: {
        x: number;
        y: number;
        timestamp: number;
    }[];
    thresholdPx: number;
    timeoutMs: number;
    clickCount: number;
    disabled: boolean;
    constructor(rageclickConfig: RageclickConfig | boolean);
    isRageClick(x: number, y: number, timestamp: number): boolean;
}

interface AutocaptureConfig extends AutocaptureConfig$1 {
    enabled: boolean;
    rageclick: boolean | RageclickConfig;
    maskAllElementAttributes: boolean;
    maskAllText: boolean;
    disableCaptureUrlHashes: boolean;
    getCurrentUrl?: (defaultUrl: string) => string;
    remoteRequestsDisabled: boolean;
}
interface AutocaptureConfigSource {
    refresh(config: AutocaptureConfig): void;
}

declare class Autocapture implements Extension$1 {
    private readonly _configSource;
    readonly name: _posthog_browser_common.ExtensionToken<Autocapture>;
    _initialized: boolean;
    _isDisabledServerSide: boolean | null;
    _hasReceivedConfigResponse: boolean;
    _elementSelectors: Set<string> | null;
    rageclicks: RageClick;
    _elementsChainAsString: boolean;
    private _client?;
    private readonly _config;
    private _remoteConfigSubscription?;
    private _domEventHandler?;
    private _copiedTextHandler?;
    private _disposed;
    constructor(_configSource: AutocaptureConfigSource);
    setup(client: Client): void;
    dispose(): void;
    private _refreshConfig;
    private _compileUrlPatterns;
    _addDomEventHandlers(): void;
    private _removeDomEventHandlers;
    startIfEnabled(): void;
    onRemoteConfig(result: RemoteConfigResult): void;
    setElementSelectors(selectors: Set<string>): void;
    getElementSelectors(element: Element | null): string[] | null;
    get isEnabled(): boolean;
    private _captureEvent;
    isBrowserSupported(): boolean;
}

/**
 * Author types for messages in a conversation
 */
type MessageAuthorType = 'customer' | 'AI' | 'human';
/**
 * TipTap mark types for inline formatting
 */
interface TipTapMark {
    type: 'bold' | 'italic' | 'underline' | 'strike' | 'code' | 'link';
    attrs?: {
        href?: string;
        target?: string;
        [key: string]: unknown;
    };
}
/**
 * TipTap node representing content in the document tree
 */
interface TipTapNode {
    type: string;
    attrs?: Record<string, unknown>;
    content?: TipTapNode[];
    marks?: TipTapMark[];
    text?: string;
}
/**
 * TipTap document - the root node of rich content
 */
interface TipTapDoc {
    type: 'doc';
    content?: TipTapNode[];
}
/**
 * A message in a conversation
 */
interface Message {
    /**
     * Unique identifier for the message
     */
    id: string;
    /**
     * The message content as plain text (fallback)
     */
    content: string;
    /**
     * Rich content in TipTap JSON format (preferred for rendering)
     * Falls back to `content` if missing or invalid
     */
    rich_content?: TipTapDoc;
    /**
     * Type of the message author
     */
    author_type: MessageAuthorType;
    /**
     * Display name of the message author
     */
    author_name?: string;
    /**
     * ISO timestamp when the message was created
     */
    created_at: string;
    /**
     * Whether this is an internal note (not shown to customer)
     */
    is_private: boolean;
}
/**
 * Status of a support ticket
 */
type TicketStatus = 'new' | 'open' | 'pending' | 'on_hold' | 'resolved';
/**
 * A support ticket in the conversations system
 */
interface Ticket {
    /**
     * Unique identifier for the ticket
     */
    id: string;
    /**
     * Current status of the ticket
     */
    status: TicketStatus;
    /**
     * Preview of the last message
     */
    last_message?: string;
    /**
     * ISO timestamp of the last message
     */
    last_message_at?: string;
    /**
     * Total number of messages in this ticket
     */
    message_count: number;
    /**
     * ISO timestamp when the ticket was created
     */
    created_at: string;
    /**
     * Array of messages (only present in detailed ticket view)
     */
    messages?: Message[];
    /**
     * Number of unread messages from the team
     */
    unread_count?: number;
}
/**
 * Response from sending a message
 */
interface SendMessageResponse {
    /**
     * ID of the ticket this message belongs to
     */
    ticket_id: string;
    /**
     * ID of the newly created message
     */
    message_id: string;
    /**
     * Current status of the ticket
     */
    ticket_status: TicketStatus;
    /**
     * ISO timestamp when the message was created
     */
    created_at: string;
    /**
     * Number of unread messages from the team
     * After customer sends a message, this is always 0
     */
    unread_count: number;
}
/**
 * Response from fetching messages
 */
interface GetMessagesResponse {
    /**
     * ID of the ticket
     */
    ticket_id: string;
    /**
     * Current status of the ticket
     */
    ticket_status: TicketStatus;
    /**
     * Array of messages
     */
    messages: Message[];
    /**
     * Whether there are more messages to fetch
     */
    has_more: boolean;
    /**
     * Number of unread messages from the team
     */
    unread_count: number;
}
/**
 * Response from marking messages as read
 */
interface MarkAsReadResponse {
    /**
     * Whether the operation was successful
     */
    success: boolean;
    /**
     * Number of unread messages (should be 0 after marking as read)
     */
    unread_count: number;
}
/**
 * Options for fetching tickets list
 */
interface GetTicketsOptions {
    /**
     * Filter by ticket status (e.g., 'open', 'closed')
     */
    status?: string;
    /**
     * Number of tickets to return (default: 20)
     */
    limit?: number;
    /**
     * Pagination offset (default: 0)
     */
    offset?: number;
}
/**
 * Response from fetching tickets list
 */
interface GetTicketsResponse {
    /**
     * Total count of tickets
     */
    count: number;
    /**
     * Array of tickets
     */
    results: Ticket[];
}
type RestoreFromTokenStatus = 'success' | 'expired' | 'invalid' | 'used';
/**
 * Response from restore token exchange endpoint
 */
interface RestoreFromTokenResponse {
    /**
     * Restore result
     */
    status: RestoreFromTokenStatus;
    /**
     * Canonical widget session ID to use after restore
     */
    widget_session_id?: string;
    /**
     * Migrated ticket IDs, if any
     */
    migrated_ticket_ids?: string[];
    /**
     * Optional machine-readable backend code
     */
    code?: string;
}
/**
 * Response from self-service restore link request
 */
interface RequestRestoreLinkResponse {
    ok: true;
}
/**
 * User-provided identification data (collected via the widget form)
 */
interface UserProvidedTraits {
    name?: string;
    email?: string;
}
type ConversationsUnavailableReason = 'disabled_by_config' | 'consent_opted_out' | 'disabled_for_toolbar' | 'remote_config_pending' | 'remote_config_failed' | 'disabled_in_project' | 'missing_token' | 'extensions_unavailable' | 'load_failed' | 'initializing' | 'not_loaded';

type attributes = {
    [key: string]: string | number | true | null;
};
declare const NodeType: {
    readonly Document: 0;
    readonly DocumentType: 1;
    readonly Element: 2;
    readonly Text: 3;
    readonly CDATA: 4;
    readonly Comment: 5;
};
type NodeType = (typeof NodeType)[keyof typeof NodeType];
type documentNode = {
    type: typeof NodeType.Document;
    childNodes: serializedNodeWithId[];
    compatMode?: string;
};
type documentTypeNode = {
    type: typeof NodeType.DocumentType;
    name: string;
    publicId: string;
    systemId: string;
};
type elementNode = {
    type: typeof NodeType.Element;
    tagName: string;
    attributes: attributes;
    childNodes: serializedNodeWithId[];
    isSVG?: true;
    needBlock?: boolean;
    isCustom?: true;
};
type textNode = {
    type: typeof NodeType.Text;
    textContent: string;
    isStyle?: true;
};
type cdataNode = {
    type: typeof NodeType.CDATA;
    textContent: '';
};
type commentNode = {
    type: typeof NodeType.Comment;
    textContent: string;
};
type serializedNode = (documentNode | documentTypeNode | elementNode | textNode | cdataNode | commentNode) & {
    rootId?: number;
    isShadowHost?: boolean;
    isShadow?: boolean;
};
type serializedNodeWithId = serializedNode & {
    id: number;
};
declare const EventType: {
    readonly DomContentLoaded: 0;
    readonly Load: 1;
    readonly FullSnapshot: 2;
    readonly IncrementalSnapshot: 3;
    readonly Meta: 4;
    readonly Custom: 5;
    readonly Plugin: 6;
};
type EventType = (typeof EventType)[keyof typeof EventType];
declare const IncrementalSource: {
    readonly Mutation: 0;
    readonly MouseMove: 1;
    readonly MouseInteraction: 2;
    readonly Scroll: 3;
    readonly ViewportResize: 4;
    readonly Input: 5;
    readonly TouchMove: 6;
    readonly MediaInteraction: 7;
    readonly StyleSheetRule: 8;
    readonly CanvasMutation: 9;
    readonly Font: 10;
    readonly Log: 11;
    readonly Drag: 12;
    readonly StyleDeclaration: 13;
    readonly Selection: 14;
    readonly AdoptedStyleSheet: 15;
    readonly CustomElement: 16;
};
type IncrementalSource = (typeof IncrementalSource)[keyof typeof IncrementalSource];
type domContentLoadedEvent = {
    type: typeof EventType.DomContentLoaded;
    data: unknown;
};
type loadedEvent = {
    type: typeof EventType.Load;
    data: unknown;
};
type fullSnapshotEvent = {
    type: typeof EventType.FullSnapshot;
    data: {
        node: serializedNodeWithId;
        initialOffset: {
            top: number;
            left: number;
        };
    };
};
type metaEvent = {
    type: typeof EventType.Meta;
    data: {
        href: string;
        width: number;
        height: number;
    };
};
type customEvent<T = unknown> = {
    type: typeof EventType.Custom;
    data: {
        tag: string;
        payload: T;
    };
};
type pluginEvent<T = unknown> = {
    type: typeof EventType.Plugin;
    data: {
        plugin: string;
        payload: T;
    };
};
type styleOMValue = {
    [key: string]: styleValueWithPriority | string | false;
};
type styleValueWithPriority = [string, string];
type textMutation = {
    id: number;
    value: string | null;
};
type attributeMutation = {
    id: number;
    attributes: {
        [key: string]: string | styleOMValue | null;
    };
};
type removedNodeMutation = {
    parentId: number;
    id: number;
    isShadow?: boolean;
};
type addedNodeMutation = {
    parentId: number;
    previousId?: number | null;
    nextId: number | null;
    node: serializedNodeWithId;
};
type mutationCallbackParam = {
    texts: textMutation[];
    attributes: attributeMutation[];
    removes: removedNodeMutation[];
    adds: addedNodeMutation[];
    isAttachIframe?: true;
};
type mutationData = {
    source: typeof IncrementalSource.Mutation;
} & mutationCallbackParam;
type mousePosition = {
    x: number;
    y: number;
    id: number;
    timeOffset: number;
};
declare const MouseInteractions: {
    readonly MouseUp: 0;
    readonly MouseDown: 1;
    readonly Click: 2;
    readonly ContextMenu: 3;
    readonly DblClick: 4;
    readonly Focus: 5;
    readonly Blur: 6;
    readonly TouchStart: 7;
    readonly TouchMove_Departed: 8;
    readonly TouchEnd: 9;
    readonly TouchCancel: 10;
};
type MouseInteractions = (typeof MouseInteractions)[keyof typeof MouseInteractions];
declare const PointerTypes: {
    readonly Mouse: 0;
    readonly Pen: 1;
    readonly Touch: 2;
};
type PointerTypes = (typeof PointerTypes)[keyof typeof PointerTypes];
type mouseInteractionParam = {
    type: MouseInteractions;
    id: number;
    x?: number;
    y?: number;
    pointerType?: PointerTypes;
};
type mouseInteractionData = {
    source: typeof IncrementalSource.MouseInteraction;
} & mouseInteractionParam;
type mousemoveData = {
    source: typeof IncrementalSource.MouseMove | typeof IncrementalSource.TouchMove | typeof IncrementalSource.Drag;
    positions: mousePosition[];
};
type scrollPosition = {
    id: number;
    x: number;
    y: number;
};
type scrollData = {
    source: typeof IncrementalSource.Scroll;
} & scrollPosition;
type viewportResizeDimension = {
    width: number;
    height: number;
};
type viewportResizeData = {
    source: typeof IncrementalSource.ViewportResize;
} & viewportResizeDimension;
type inputValue = {
    text: string;
    isChecked: boolean;
    userTriggered?: boolean;
};
type inputData = {
    source: typeof IncrementalSource.Input;
    id: number;
} & inputValue;
declare const MediaInteractions: {
    readonly Play: 0;
    readonly Pause: 1;
    readonly Seeked: 2;
    readonly VolumeChange: 3;
    readonly RateChange: 4;
};
type MediaInteractions = (typeof MediaInteractions)[keyof typeof MediaInteractions];
type mediaInteractionParam = {
    type: MediaInteractions;
    id: number;
    currentTime?: number;
    volume?: number;
    muted?: boolean;
    loop?: boolean;
    playbackRate?: number;
};
type mediaInteractionData = {
    source: typeof IncrementalSource.MediaInteraction;
} & mediaInteractionParam;
type styleSheetAddRule = {
    rule: string;
    index?: number | number[];
};
type styleSheetDeleteRule = {
    index: number | number[];
};
type styleSheetRuleParam = {
    id?: number;
    styleId?: number;
    removes?: styleSheetDeleteRule[];
    adds?: styleSheetAddRule[];
    replace?: string;
    replaceSync?: string;
};
type styleSheetRuleData = {
    source: typeof IncrementalSource.StyleSheetRule;
} & styleSheetRuleParam;
declare const CanvasContext: {
    readonly '2D': 0;
    readonly WebGL: 1;
    readonly WebGL2: 2;
};
type CanvasContext = (typeof CanvasContext)[keyof typeof CanvasContext];
type canvasMutationCommand = {
    property: string;
    args: Array<unknown>;
    setter?: true;
};
type canvasMutationParam = {
    id: number;
    type: CanvasContext;
    commands: canvasMutationCommand[];
} | ({
    id: number;
    type: CanvasContext;
} & canvasMutationCommand);
type canvasMutationData = {
    source: typeof IncrementalSource.CanvasMutation;
} & canvasMutationParam;
type fontParam = {
    family: string;
    fontSource: string;
    buffer: boolean;
    descriptors?: FontFaceDescriptors;
};
type fontData = {
    source: typeof IncrementalSource.Font;
} & fontParam;
type SelectionRange = {
    start: number;
    startOffset: number;
    end: number;
    endOffset: number;
};
type selectionParam = {
    ranges: Array<SelectionRange>;
};
type selectionData = {
    source: typeof IncrementalSource.Selection;
} & selectionParam;
type styleDeclarationParam = {
    id?: number;
    styleId?: number;
    index: number[];
    set?: {
        property: string;
        value: string | null;
        priority: string | undefined;
    };
    remove?: {
        property: string;
    };
};
type styleDeclarationData = {
    source: typeof IncrementalSource.StyleDeclaration;
} & styleDeclarationParam;
type adoptedStyleSheetParam = {
    id: number;
    styles?: {
        styleId: number;
        rules: styleSheetAddRule[];
    }[];
    styleIds: number[];
};
type adoptedStyleSheetData = {
    source: typeof IncrementalSource.AdoptedStyleSheet;
} & adoptedStyleSheetParam;
type customElementParam = {
    define?: {
        name: string;
    };
};
type customElementData = {
    source: typeof IncrementalSource.CustomElement;
} & customElementParam;
type incrementalData = mutationData | mousemoveData | mouseInteractionData | scrollData | viewportResizeData | inputData | mediaInteractionData | styleSheetRuleData | canvasMutationData | fontData | selectionData | styleDeclarationData | adoptedStyleSheetData | customElementData;
type incrementalSnapshotEvent = {
    type: typeof EventType.IncrementalSnapshot;
    data: incrementalData;
};
type eventWithoutTime = domContentLoadedEvent | loadedEvent | fullSnapshotEvent | incrementalSnapshotEvent | metaEvent | customEvent | pluginEvent;
type eventWithTime = eventWithoutTime & {
    timestamp: number;
    delay?: number;
};

interface LazyLoadedDeadClicksAutocaptureInterface {
    start: (observerTarget: Node) => void;
    stop: () => void;
}

declare class DeadClicksAutocapture implements Extension {
    readonly instance: PostHog;
    readonly isEnabled: (dca: DeadClicksAutocapture) => boolean;
    readonly onCapture?: DeadClicksAutoCaptureConfig['__onCapture'];
    get lazyLoadedDeadClicksAutocapture(): LazyLoadedDeadClicksAutocaptureInterface | undefined;
    private _lazyLoadedDeadClicksAutocapture;
    constructor(instance: PostHog, isEnabled: (dca: DeadClicksAutocapture) => boolean, onCapture?: DeadClicksAutoCaptureConfig['__onCapture']);
    onRemoteConfig(result: RemoteConfigResult): void;
    startIfEnabledOrStop(): void;
    private _loadScript;
    private _start;
    stop(): void;
}

declare class ExceptionObserver {
    private _instance;
    private _rateLimiter;
    private _remoteEnabled;
    private _config;
    private _unwrapOnError;
    private _unwrapUnhandledRejection;
    private _unwrapConsoleError;
    constructor(instance: PostHog);
    private _requiredConfig;
    get isEnabled(): boolean;
    startIfEnabledOrStop(): void;
    private _loadScript;
    private _startCapturing;
    private _stopCapturing;
    onRemoteConfig(result: RemoteConfigResult): void;
    onConfigChange(): void;
    captureException(errorProperties: ErrorTracking.ErrorProperties): void;
}

/**
 * Captures pageviews when selected URL components change through the history API, browser back/forward navigation,
 * or hash navigation.
 */
declare class HistoryAutocapture implements Extension {
    private _instance;
    private _popstateListener;
    private _hashchangeListener;
    private _lastLocation;
    constructor(instance: PostHog);
    initialize(): void;
    get isEnabled(): boolean;
    startIfEnabled(): void;
    startIfEnabledOrStop(): void;
    stop(): void;
    monitorHistoryChanges(): void;
    private _patchHistoryMethod;
    private _getCurrentLocation;
    private _getCaptureOptions;
    private _shouldCaptureHashChanges;
    private _hasLocationChanged;
    private _capturePageview;
    private _setupPopstateListener;
    private _setupHashchangeListener;
}

declare class TracingHeaders implements Extension {
    private readonly _instance;
    private _restoreXHRPatch;
    private _restoreFetchPatch;
    private _hostnamesForPatch;
    constructor(_instance: PostHog);
    initialize(): void;
    private _loadScript;
    private _getConfiguredHostnames;
    private _syncHostnamesForPatch;
    private _stopCapturing;
    startIfEnabledOrStop(): void;
    private _startCapturing;
}

declare class WebVitalsAutocapture {
    private readonly _instance;
    private _enabledServerSide;
    private _initialized;
    private _buffer;
    private _delayedFlushTimer;
    constructor(_instance: PostHog);
    private get _perfConfig();
    get allowedMetrics(): SupportedWebVitalsMetrics[];
    get flushToCaptureTimeoutMs(): number;
    get attributionMetrics(): SupportedWebVitalsMetrics[];
    get useAttribution(): boolean;
    get useSoftNavs(): boolean;
    get _maxAllowedValue(): number;
    get isEnabled(): boolean;
    startIfEnabled(): void;
    onRemoteConfig(result: RemoteConfigResult): void;
    private get _callbackFlavor();
    private _loadScript;
    private _maskedURL;
    private _flushToCapture;
    private _addToBuffer;
    private _startCapturing;
}

declare class SessionRecording implements Extension {
    private readonly _instance;
    _forceAllowLocalhostNetworkCapture: boolean;
    private _recordingStatus;
    private get _config();
    private get _persistence();
    private _persistFlagsOnSessionListener;
    private _lazyLoadedSessionRecording;
    private _sessionRecordingDisposed;
    private _documentWasEverVisible;
    private _onVisibilityChange;
    get started(): boolean;
    get status(): SessionRecordingStatus;
    constructor(_instance: PostHog);
    initialize(): void;
    dispose({ discardBufferedEvents }?: {
        discardBufferedEvents?: boolean;
    }): void;
    private get _isRecordingEnabled();
    startIfEnabledOrStop(startReason?: SessionStartReason): void;
    /**
     * session recording waits until it receives remote config before loading the script
     * this is to ensure we can control the script name remotely
     * and because we wait until we have local and remote config to determine if we should start at all
     * if start is called and there is no remote config then we wait until there is
     */
    private _lazyLoadAndStart;
    stopRecording(): void;
    private _discardRecording;
    private _resetSampling;
    private _validateSampleRate;
    private _persistRemoteConfig;
    onRemoteConfig(result: RemoteConfigResult): void;
    log(message: string, level?: 'log' | 'warn' | 'error'): void;
    private get _scriptName();
    private _isRemoteConfigFresh;
    private _onScriptLoaded;
    /**
     * this is maintained on the public API only because it has always been on the public API
     * if you are calling this directly you are certainly doing something wrong
     * @deprecated
     */
    onRRwebEmit(rawEvent: eventWithTime): void;
    /**
     * this ignores the linked flag config and (if other conditions are met) causes capture to start
     *
     * It is not usual to call this directly,
     * instead call `posthog.startSessionRecording({linked_flag: true})`
     * */
    overrideLinkedFlag(): void;
    /**
     * this ignores the sampling config and (if other conditions are met) causes capture to start
     *
     * It is not usual to call this directly,
     * instead call `posthog.startSessionRecording({sampling: true})`
     * */
    overrideSampling(): void;
    /**
     * this ignores the URL/Event trigger config and (if other conditions are met) causes capture to start
     *
     * It is not usual to call this directly,
     * instead call `posthog.startSessionRecording({trigger: 'url' | 'event'})`
     * */
    overrideTrigger(triggerType: TriggerType): void;
    get sdkDebugProperties(): Properties;
    /**
     * This adds a custom event to the session recording
     *
     * It is not intended for arbitrary public use - playback only displays known custom events
     * And is exposed on the public interface only so that other parts of the SDK are able to use it
     *
     * if you are calling this from client code, you're probably looking for `posthog.capture('$custom_event', {...})`
     */
    tryAddCustomEvent(tag: string, payload: any): boolean;
}

type HeatmapEventBuffer = {
    [key: string]: Properties[];
} | undefined;
declare class Heatmaps implements Extension {
    instance: PostHog;
    rageclicks: RageClick;
    _enabledServerSide: boolean;
    private get _config();
    _initialized: boolean;
    _mouseMoveTimeout: ReturnType<typeof setTimeout> | undefined;
    private _buffer;
    private _flushInterval;
    private _deadClicksCapture;
    private _onClickHandler;
    private _onMouseMoveHandler;
    private _flushHandler;
    private _onVisibilityChange_handler;
    constructor(instance: PostHog);
    initialize(): void;
    get flushIntervalMilliseconds(): number;
    get isEnabled(): boolean;
    startIfEnabled(): void;
    onRemoteConfig(result: RemoteConfigResult): void;
    getAndClearBuffer(): HeatmapEventBuffer;
    private _onDeadClick;
    private _onVisibilityChange;
    private _setupListeners;
    private _removeListeners;
    private _getProperties;
    private _onClick;
    private _onMouseMove;
    private _capture;
    private _flush;
}

/**
 * Having Survey types in types.ts was confusing tsc
 * and generating an invalid module.d.ts
 * See https://github.com/PostHog/posthog-js/issues/698
 */

type SurveyCallback = (surveys: Survey[], context?: {
    isLoaded: boolean;
    error?: string;
}) => void;
interface DisplaySurveyOptionsBase {
    /**
     * Whether to bypass the survey's targeting and display conditions.
     * @default false
     */
    ignoreConditions: boolean;
    /**
     * Whether to bypass the survey's configured popup delay.
     * @default false
     */
    ignoreDelay: boolean;
    /**
     * How the survey should be displayed.
     * @default DisplaySurveyType.Popover
     */
    displayType: DisplaySurveyType;
    /** Additional properties to include in all survey events (shown, sent, dismissed). */
    properties?: Properties;
    /** Pre-filled responses by question index (0-based). Only supported for popover surveys. */
    initialResponses?: Record<number, SurveyResponseValue>;
}
/** Options for displaying a survey as a popover. */
interface DisplaySurveyPopoverOptions extends DisplaySurveyOptionsBase {
    displayType: typeof DisplaySurveyType.Popover;
    /** Override the survey's configured position. */
    position?: SurveyPosition;
    /** CSS selector for the element to position the survey next to (when position is NextToTrigger). */
    selector?: string;
    /** When true, `survey shown` events will not be emitted automatically. */
    skipShownEvent?: boolean;
}
interface DisplaySurveyInlineOptions extends DisplaySurveyOptionsBase {
    displayType: typeof DisplaySurveyType.Inline;
    /** CSS selector for the element where the inline survey should render. */
    selector: string;
}
/** Options for `posthog.displaySurvey()`. */
type DisplaySurveyOptions = DisplaySurveyPopoverOptions | DisplaySurveyInlineOptions;
type SurveyResponseValue = SurveyResponseValue$1;

interface InferredSelector {
    autoData: string;
    text: string | null;
    excludeText?: boolean;
    precision?: number;
}

interface JSONContent {
    type?: string;
    attrs?: Record<string, any>;
    content?: JSONContent[];
    marks?: {
        type: string;
        attrs?: Record<string, any>;
    }[];
    text?: string;
}
type ProductTourStepType = 'element' | 'modal' | 'survey' | 'banner';
interface ProductTourBannerConfig {
    behavior: 'sticky' | 'static' | 'custom';
    selector?: string;
    action?: {
        type: 'none' | 'link' | 'trigger_tour';
        link?: string;
        tourId?: string;
    };
    animation?: {
        duration?: number;
    };
}
/** Button actions available on modal steps */
type ProductTourButtonAction = 'dismiss' | 'link' | 'next_step' | 'previous_step' | 'trigger_tour';
interface ProductTourStepButton {
    text: string;
    action: ProductTourButtonAction;
    /** URL to open when action is 'link' */
    link?: string;
    /** Tour ID to trigger when action is 'trigger_tour' */
    tourId?: string;
}
interface ProductTourStepButtons {
    primary?: ProductTourStepButton;
    secondary?: ProductTourStepButton;
}
type ProductTourSurveyQuestionType = 'open' | 'rating';
interface ProductTourSurveyQuestion {
    type: ProductTourSurveyQuestionType;
    questionText: string;
    /** Rating display type - emoji or number */
    display?: 'emoji' | 'number';
    /** Rating scale - 3 or 5 for emoji, 5 or 10 for number */
    scale?: 3 | 5 | 10;
    /** Label for low end of rating scale (e.g., "Not likely") */
    lowerBoundLabel?: string;
    /** Label for high end of rating scale (e.g., "Very likely") */
    upperBoundLabel?: string;
    submitButtonText?: string;
    backButtonText?: string;
}
interface ProductTourStep {
    id: string;
    type: ProductTourStepType;
    selector?: string;
    progressionTrigger: 'button' | 'click';
    content: JSONContent | null;
    /** Pre-rendered HTML content from the editor. If present, SDK should use this instead of rendering from JSONContent. */
    contentHtml?: string;
    /** Inline survey question config - if present, this is a survey step */
    survey?: ProductTourSurveyQuestion;
    /** ID of the auto-created survey for this step (set by backend) */
    linkedSurveyId?: string;
    /** ID of the survey question (set by backend, used for event tracking) */
    linkedSurveyQuestionId?: string;
    /** Enhanced element data for more reliable lookup at runtime */
    inferenceData?: InferredSelector;
    /** Use CSS selector instead of inference. Defaults to false (use inference). */
    useManualSelector?: boolean;
    /** Maximum tooltip width in pixels (defaults to 320px) */
    maxWidth?: number;
    /** Position for modal/survey steps (defaults to middle_center) */
    modalPosition?: SurveyPosition$1;
    /** Button configuration for modal steps */
    buttons?: ProductTourStepButtons;
    /** Banner configuration (only for banner steps) */
    bannerConfig?: ProductTourBannerConfig;
    /** translation data for this tour step */
    translations?: Record<string, ProductTourStepTranslation>;
}
/** all translatable content for a given tour step */
interface ProductTourStepTranslation {
    content?: ProductTourStep['content'];
    contentHtml?: ProductTourStep['contentHtml'];
    buttons?: {
        primary?: Pick<ProductTourStepButton, 'text'>;
        secondary?: Pick<ProductTourStepButton, 'text'>;
    };
    survey?: Pick<ProductTourSurveyQuestion, 'questionText' | 'lowerBoundLabel' | 'upperBoundLabel' | 'submitButtonText' | 'backButtonText'>;
}
/** maps to main repo EffectiveProductTourType */
type ProductTourType = 'tour' | 'announcement' | 'banner';
interface ProductTourWaitPeriod {
    days: number;
    types: ProductTourType[];
}
interface ProductTourConditions {
    url?: string;
    urlMatchType?: PropertyMatchType;
    selector?: string;
    autoShowDelaySeconds?: number;
    events?: {
        values: SurveyEventWithFilters[];
    } | null;
    cancelEvents?: {
        values: SurveyEventWithFilters[];
    } | null;
    actions?: {
        values: SurveyActionType[];
    } | null;
    linkedFlagVariant?: string;
    deviceTypes?: string[];
    seenTourWaitPeriod?: ProductTourWaitPeriod;
}
interface ProductTourAppearance {
    backgroundColor?: string;
    textColor?: string;
    buttonColor?: string;
    borderRadius?: number;
    buttonBorderRadius?: number;
    borderColor?: string;
    fontFamily?: string;
    boxShadow?: string;
    showOverlay?: boolean;
    whiteLabel?: boolean;
    /** defaults to true, auto-set to false for announcements/banners */
    dismissOnClickOutside?: boolean;
    zIndex?: number;
}
type ProductTourDisplayFrequency = 'show_once' | 'until_interacted' | 'always';
interface ProductTour {
    id: string;
    name: string;
    description?: string;
    tour_type: ProductTourType;
    auto_launch?: boolean;
    start_date: string | null;
    end_date: string | null;
    current_iteration?: number;
    conditions?: ProductTourConditions;
    appearance?: ProductTourAppearance;
    steps: ProductTourStep[];
    internal_targeting_flag_key?: string;
    linked_flag_key?: string;
    display_frequency?: ProductTourDisplayFrequency;
    disable_image_preload?: boolean;
}
type ProductTourCallback = (tours: ProductTour[], context?: {
    isLoaded: boolean;
    error?: string;
}) => void;

declare class PostHogProductTours implements Extension {
    private _instance;
    private _productTourManager;
    private _cachedTours;
    private get _persistence();
    constructor(instance: PostHog);
    initialize(): void;
    onRemoteConfig(result: RemoteConfigResult): void;
    loadIfEnabled(): void;
    private _loadScript;
    private _startProductTours;
    getProductTours(callback: ProductTourCallback, forceReload?: boolean): void;
    getActiveProductTours(callback: ProductTourCallback): void;
    showProductTour(tourId: string): void;
    previewTour(tour: ProductTour): void;
    dismissProductTour(): void;
    nextStep(): void;
    previousStep(): void;
    clearCache(): void;
    resetTour(tourId: string): void;
    resetAllTours(): void;
    cancelPendingTour(tourId: string): void;
}

declare class SiteApps implements Extension {
    private _instance;
    apps: Record<string, SiteApp>;
    private _stopBuffering?;
    private _bufferedInvocations;
    private _siteAppElementPatchCount;
    private _restoreSiteAppElementPatches?;
    constructor(_instance: PostHog);
    get isEnabled(): boolean;
    private _eventCollector;
    get siteAppLoaders(): SiteAppLoader[] | undefined;
    initialize(): void;
    globalsForEvent(event: CaptureResult): SiteAppGlobals;
    private _prepareElementForSiteApp;
    private _patchSiteAppElementInsertionMethods;
    private _releaseSiteAppElementPatches;
    private _runWithPreparedSiteAppElements;
    setupSiteApp(loader: SiteAppLoader): void;
    private _setupSiteApps;
    private _onCapturedEvent;
    onRemoteConfig(result: RemoteConfigResult): void;
}

declare class SurveyManager {
    private _posthog;
    private _surveyInFocus;
    private _surveyTimeouts;
    private _widgetSelectorListeners;
    private _renderedTargets;
    private _prefillHandledSurveys;
    private _automaticDisplayDispose?;
    private _currentLanguage;
    private _surveyIsRendered;
    private _languageChangeListener;
    private _unsubscribeFeatureFlags;
    private _surveyPopupProps;
    private _displayOptions;
    constructor(posthog: PostHog);
    private _onLanguageChange;
    private get _featureFlags();
    private _applyDisplayOverrides;
    handlePageUnload: () => void;
    private _clearSurveyTimeout;
    /**
     * cancel a "pending" survey, i.e. one that is waiting to be displayed in
     * the _surveyTimeouts queue
     */
    cancelSurvey(surveyId: string): void;
    setAutomaticDisplayDispose(dispose: () => void): void;
    dispose(): void;
    /**
     * `resumeDelayFromActivation` is internal to the display loop: a survey armed by an
     * event/action trigger resumes its popup delay from when the trigger fired, so navigating
     * mid-delay does not restart the countdown. An explicit `displaySurvey()` call carries its own
     * `ignoreDelay` option instead, so it must always honor the full configured delay.
     */
    handlePopoverSurvey: (surveyParam: Survey, options?: DisplaySurveyPopoverOptions, { resumeDelayFromActivation }?: {
        resumeDelayFromActivation?: boolean;
    }) => void;
    private _handleWidget;
    private _detachWidgetSelectorListener;
    private _removeWidgetSelectorListener;
    private _isWidgetSurveyOpen;
    private _manageWidgetSelectorListener;
    /**
     * Sorts surveys by their appearance delay in ascending order. If a survey does not have an appearance delay,
     * it is considered to have a delay of 0.
     * @param surveys
     * @returns The surveys sorted by their appearance delay
     */
    private _sortSurveysByAppearanceDelay;
    renderPopover: (survey: Survey) => void;
    renderSurvey: (survey: Survey, selector: Element, properties?: Properties) => void;
    private _translateSurveyForRendering;
    private _handleUrlPrefill;
    /**
     * On load, capture a response for prefilled questions only when:
     * 1) the survey is complete, OR
     * 2) partial responses are enabled AND the skipped questions were set to auto-submit.
     */
    private _autoSubmitPrefilledResponses;
    /**
     * process prefilled responses for non-hosted surveys
     *
     * @returns boolean, true if the survey is completed
     */
    private _handleInitialResponses;
    private _processPrefillData;
    private _isSurveyFeatureFlagEnabled;
    private _isSurveyConditionMatched;
    private _internalFlagCheckSatisfied;
    checkSurveyEligibility(survey: Survey): {
        eligible: boolean;
        reason?: string;
    };
    /**
     * Renderability = eligibility (running, type, flags, wait period, already-seen) plus the
     * survey's event/action activation trigger. Used by the programmatic `canRenderSurvey` /
     * `canRenderSurveyAsync` checks so they match the display loop.
     *
     * The trigger is intentionally kept out of `checkSurveyEligibility`: that method is also
     * used by the explicit `displaySurvey` path, and the trigger state only lives in memory
     * (a reload clears it, server-side events never set it). Gating eligibility on it would
     * make explicit `displaySurvey('id')` calls silently show nothing.
     */
    checkSurveyRenderability(survey: Survey): {
        eligible: boolean;
        reason?: string;
    };
    /**
     * Surveys can be activated by events or actions. This method checks if the survey has events and actions,
     * and if so, it checks if the survey has been activated.
     * @param survey
     */
    private _hasActionOrEventTriggeredSurvey;
    private _checkFlags;
    /**
     * The full predicate for "should this survey display right now": eligibility (running,
     * type, linked/targeting/internal flags, wait period, already-seen) plus the URL/device/
     * selector conditions, the event/action trigger, and any feature-flag dependencies.
     *
     * Shared by the display loop and re-checked when a popover's delay timer fires, so a
     * survey that became ineligible *during* the delay (e.g. an identify() reloaded flags and
     * the internal targeting flag is now false) is not shown. Note this is purely an AND gate:
     * adding it can only ever suppress a display, never cause an extra one.
     */
    private _shouldDisplaySurvey;
    getActiveMatchingSurveys: (callback: SurveyCallback, forceReload?: boolean) => void;
    callSurveysAndEvaluateDisplayLogic: (forceReload?: boolean) => void;
    private _addSurveyToFocus;
    private _removeSurveyFromDom;
    private _removeSurveyFromFocus;
    getTestAPI(): {
        addSurveyToFocus: (survey: Pick<Survey, "id">) => void;
        removeSurveyFromFocus: (survey: SurveyWithTypeAndAppearance) => void;
        surveyInFocus: string | null;
        surveyTimeouts: Map<string, number>;
        handleWidget: (survey: Survey) => void;
        handlePopoverSurvey: (surveyParam: Survey, options?: DisplaySurveyPopoverOptions, { resumeDelayFromActivation }?: {
            resumeDelayFromActivation?: boolean;
        }) => void;
        manageWidgetSelectorListener: (survey: Survey, selector: string) => void;
        sortSurveysByAppearanceDelay: (surveys: Survey[]) => Survey[];
        checkFlags: (survey: Survey) => boolean;
        isSurveyFeatureFlagEnabled: (flagKey: string | null, flagVariant?: string | undefined) => boolean;
        onLanguageChange: () => void;
        currentLanguage: string | null;
        surveyIsRendered: boolean;
    };
}

declare class ActionMatcher {
    private readonly _instance?;
    private readonly _actionRegistry;
    private readonly _actionEvents;
    private _debugEventEmitter;
    private _captureHookUnsubscribe?;
    constructor(_instance?: PostHog | undefined);
    init(): void;
    dispose(): void;
    register(actions: SurveyActionType[]): void;
    replace(actions: SurveyActionType[]): void;
    on(eventName: string, eventPayload?: CaptureResult): void;
    _addActionHook(callback: (actionName: string, eventPayload?: any) => void): void;
    private _checkAction;
    onAction(event: 'actionCaptured', cb: (...args: any[]) => void): () => void;
    private _checkStep;
    private _checkStepEvent;
    private _checkStepUrl;
    private _checkStepElement;
    private _checkStepHref;
    private _checkStepText;
    private _checkStepSelector;
    private _getElementsList;
    private _checkStepProperties;
}

/**
 * Interface for items that can be triggered by events/actions.
 * Both Survey and ProductTour implement this interface.
 */
interface EventTriggerable {
    id: string;
    conditions?: {
        events?: {
            repeatedActivation?: boolean;
            values: SurveyEventWithFilters[];
        } | null;
        cancelEvents?: {
            values: SurveyEventWithFilters[];
        } | null;
        actions?: {
            values: SurveyActionType[];
        } | null;
    } | null;
}
/**
 * What a captured lifecycle event (shown / dismissed / sent) does to an already-activated item:
 * - `consume`: it's done — drop it from both the in-memory and persisted sets.
 * - `persist`: it was shown and should survive a reload — move it from memory into persistence.
 * - `ignore`: no transition for this item on this event.
 */
type ActivationOutcome = 'consume' | 'persist' | 'ignore';
/**
 * Abstract base class for receiving events and matching them to triggerable items.
 * Subclasses implement type-specific behavior for surveys and product tours.
 */
declare abstract class EventReceiver<T extends EventTriggerable> {
    protected _eventToItems: Map<string, string[]>;
    protected _cancelEventToItems: Map<string, string[]>;
    protected readonly _actionToItems: Map<string, string[]>;
    protected _actionMatcher?: ActionMatcher | null;
    protected readonly _instance?: PostHog;
    /**
     * Items armed by an event or action but not yet shown live here, in memory only.
     * They are intentionally NOT persisted, so they do not survive a page reload: an
     * event trigger only displays an item in the session the event fired in. Once an
     * item is shown, surviving items are promoted into persistence (see `onEvent`) so
     * a reload re-reads and re-displays them until the user interacts — but that
     * persisted activation is scoped to the triggering session (see
     * `_getPersistedActivatedIds`), so it does not leak into a brand-new session where
     * the trigger never fired.
     */
    private _pendingActivatedItems;
    private _captureHookUnsubscribe?;
    private _sessionIdUnsubscribe?;
    constructor(instance: PostHog);
    protected abstract _getActivatedKey(): string;
    /** Persistence key under which the session id of the persisted activation set is stamped. */
    protected abstract _getActivatedSessionKey(): string;
    protected abstract _getShownEventName(): string;
    protected abstract _getItems(callback: (items: T[]) => void): void;
    protected abstract _cancelPendingItem(itemId: string): void;
    protected abstract _getLogger(): ReturnType<typeof createLogger>;
    protected abstract _setActivatedItems(eligibleItems: string[]): void;
    /** Persist the session id the current activation set belongs to. */
    protected abstract _setActivatedSession(sessionId: string): void;
    /** Forget the persisted session stamp. */
    protected abstract _clearActivatedSession(): void;
    /** Check if item is permanently ineligible (e.g. completed/dismissed). Skip adding to activated list. */
    protected abstract _isItemPermanentlyIneligible(itemId?: string): boolean;
    /**
     * Decide what a captured lifecycle `event` does to an already-activated `itemId`. Most items are
     * consumed when shown (so they only reappear when their trigger fires again). Surveys keep
     * non-repeatable ones activated — promoting them to session-scoped persistence on shown — until the
     * user dismisses or answers them, so an event-triggered survey survives a reload within the
     * triggering session (but not a brand-new session) until it's actually interacted with.
     */
    protected abstract _activationOutcome(event: string, itemId: string): ActivationOutcome;
    /**
     * Whether an item armed by a trigger should be persisted immediately (session-scoped)
     * instead of kept in memory until it is shown. Overridden by receivers whose items carry a
     * display delay that must survive a navigation, so the delay can resume from where it left
     * off on the next page. Default: keep in memory, so the arming is page-scoped and an
     * exit-intent-style trigger cannot leak an armed item onto a later page load.
     */
    protected _shouldPersistArmedActivation(_itemId: string): boolean;
    /**
     * Persistence key under which per-item activation timestamps are read from, or null for
     * receivers that don't track them. Used to resume a display delay across navigations. Writes
     * go through `_writeActivationTimestamps` / `_clearActivationTimestampsStore` so the register
     * sink always resolves to a literal key constant.
     */
    protected _getActivationTimestampsKey(): string | null;
    /** Persist the activation timestamp map. Overridden by receivers that track timestamps. */
    protected _writeActivationTimestamps(_timestamps: Record<string, number>): void;
    /** Forget the whole activation timestamp map. Overridden by receivers that track timestamps. */
    protected _clearActivationTimestampsStore(): void;
    private _doesEventMatchFilter;
    private _buildEventToItemMap;
    /**
     * build a map of (Event1) => [Item1, Item2, Item3]
     * used for items that should be [activated|cancelled] by Event1
     */
    private _getMatchingItems;
    register(items: T[]): void;
    replace(items: T[]): void;
    private _register;
    private _setupActionBasedItems;
    private _mergeItemMaps;
    private _setupEventBasedItems;
    onEvent(event: string, eventPayload?: CaptureResult): void;
    onAction(actionName: string): void;
    /**
     * Arm items. Most are held in memory only (not persisted) until they are shown, so their
     * arming is page-scoped. Items that opt in via `_shouldPersistArmedActivation` (those with a
     * display delay) are persisted right away and stamped with the activation time, so the delay
     * survives a navigation and resumes from the elapsed time on the next page.
     */
    private _activateItems;
    /**
     * Move an in-memory activation into persistence so it survives a page reload within the
     * triggering session. The set is (re)stamped with the current session id; reading it back
     * via `_getPersistedActivatedIds` discards it once the session rolls over. Because we build
     * on top of the session-scoped read, a stale set left over from a previous session is
     * dropped here rather than accumulated.
     */
    private _persistActivation;
    /** Drop items from both the in-memory and persisted activation sets. */
    private _deactivateItems;
    /** The raw persisted activation timestamps as stored, ignoring session scoping. */
    private _getRawActivationTimestamps;
    /**
     * Stamp when an item enters persisted activation, so a resumed display delay can be computed
     * from the elapsed time on a later page load. Repeated triggers do not call this method because
     * `_persistActivation` returns false while the current activation is still live.
     */
    private _recordActivationTimestamp;
    /** Drop the activation timestamps for the given items. */
    private _clearActivationTimestamps;
    /** Forget all activation timestamps (e.g. on reset or a session rollover). */
    private _clearAllActivationTimestamps;
    /**
     * The time (epoch ms) an item was armed by its trigger, or undefined if none is recorded.
     * Session-scoped: a timestamp is only honored while its activation is still live for the
     * current session, so a stale entry left in persistence cannot resurrect an expired delay.
     */
    getActivationTimestamp(itemId: string): number | undefined;
    /** The raw persisted set as stored, ignoring session scoping. */
    private _getRawPersistedActivatedIds;
    /**
     * The persisted activations that still belong to the current session. A persisted activation
     * is scoped to the session the item was shown in: an event/action trigger only earns a display
     * in the session it fired in, so once the session rolls over the activation is stale and must
     * not silently re-display the item in a brand-new session where the trigger never fired.
     */
    private _getPersistedActivatedIds;
    /** Stamp the persisted activation set with the current session id. */
    private _stampActivationSession;
    /** Forget the session stamp once nothing is persisted under it. */
    private _clearActivationSession;
    /**
     * Drop a persisted activation once the session it was stamped under is no longer current.
     * Fired on session rotation (idle timeout, max length, cross-tab adoption) — the cases the
     * read-only session read on the display path cannot observe. Pending timers must also be
     * cancelled so a fresh trigger in the new session starts its full delay from the new timestamp.
     */
    private _onSessionIdChanged;
    getActivatedIds(): string[];
    /**
     * Clear all activations. Called on `posthog.reset()` so a logout or account switch
     * (without a full page reload) does not leave an event-armed item live for the next
     * user — the in-memory set would otherwise survive `persistence.clear()`.
     */
    dispose(): void;
    reset(): void;
    getEventToItemsMap(): Map<string, string[]>;
    _getActionMatcher(): ActionMatcher | null | undefined;
}

declare class SurveyEventReceiver extends EventReceiver<Survey> {
    constructor(instance: PostHog);
    protected _getActivatedKey(): string;
    protected _getActivatedSessionKey(): string;
    protected _getActivationTimestampsKey(): string;
    protected _writeActivationTimestamps(timestamps: Record<string, number>): void;
    protected _clearActivationTimestampsStore(): void;
    /**
     * A survey with a popup delay must survive navigation so the delay resumes from the recorded
     * activation time on the next page instead of restarting from zero. Surveys without a delay
     * keep the in-memory arming, so an exit-intent trigger does not surface them on a later page.
     */
    protected _shouldPersistArmedActivation(itemId: string): boolean;
    protected _getShownEventName(): string;
    protected _getItems(callback: (items: Survey[]) => void): void;
    protected _cancelPendingItem(itemId: string): void;
    protected _getLogger(): ReturnType<typeof createLogger>;
    protected _setActivatedItems(eligibleItems: string[]): void;
    protected _setActivatedSession(sessionId: string): void;
    protected _clearActivatedSession(): void;
    protected _isItemPermanentlyIneligible(): boolean;
    protected _activationOutcome(event: string, itemId: string): ActivationOutcome;
    getSurveys(): string[];
    getEventToSurveys(): Map<string, string[]>;
}

interface SurveysConfig {
    disableSurveys: boolean;
    cookielessMode: boolean;
    advancedEnableSurveys: boolean;
    requestTimeoutMs: number;
}
interface SurveysExtensionHost {
    generateSurveys?: (isSurveysEnabled: boolean) => SurveyManager;
    loadExternalDependency?: (callback: (error?: unknown) => void) => void;
}
interface SurveysConfigSource {
    get(): Readonly<SurveysConfig>;
    isOptedOut(): boolean;
    getExtensions(): SurveysExtensionHost | undefined;
    createEventReceiver(): SurveyEventReceiver;
}

type SurveysClientState = Pick<Client, 'projectToken' | 'kv'>;
declare class PostHogSurveys implements Extension$1 {
    private readonly _configSource;
    private readonly _initialClientState?;
    readonly name: _posthog_browser_common.ExtensionToken<PostHogSurveys>;
    private _isSurveysEnabled?;
    _surveyEventReceiver: SurveyEventReceiver | null;
    private _surveyManager;
    private _isInitializingSurveys;
    private _surveyCallbacks;
    private _getSurveysInFlightPromise;
    private _lastSurveyRefreshFailedAt;
    private _client?;
    private _initializingClient?;
    private _remoteConfigSubscription?;
    private _disposed;
    private _renderTimeouts;
    constructor(_configSource: SurveysConfigSource, _initialClientState?: SurveysClientState | undefined);
    setup(client: Client): void | Promise<void>;
    dispose(): void;
    private get _config();
    initialize(): void;
    onRemoteConfig: (result: DeepReadonly<RemoteConfigResult>) => void;
    reset(): void;
    loadIfEnabled(): void;
    /** Helper to finalize survey initialization */
    private _completeSurveyInitialization;
    /** Helper to handle errors during survey loading */
    private _handleSurveyLoadError;
    /**
     * Register a callback that runs when surveys are initialized.
     * ### Usage:
     *
     *     posthog.onSurveysLoaded((surveys) => {
     *         // You can work with all surveys
     *         console.log('All available surveys:', surveys)
     *
     *         // Or get active matching surveys
     *         posthog.getActiveMatchingSurveys((activeMatchingSurveys) => {
     *             if (activeMatchingSurveys.length > 0) {
     *                 posthog.renderSurvey(activeMatchingSurveys[0].id, '#survey-container')
     *             }
     *         })
     *     })
     *
     * @param {Function} callback The callback function will be called when surveys are loaded or updated.
     *                           It receives the array of all surveys and a context object with error status.
     * @returns {Function} A function that can be called to unsubscribe the listener.
     */
    onSurveysLoaded(callback: SurveyCallback): () => void;
    getSurveys(callback: SurveyCallback, forceReload?: boolean): void;
    protected _sendSurveysRequest(path: string, init: SendRequestInit): Promise<ApiResponse>;
    private _handleSurveyResponse;
    /**
     * Whether to kick off a background refresh of the cached definitions: the cache is stale, no
     * fetch is already in flight, and we're not backing off after a recent failure.
     */
    private _shouldBackgroundRefreshSurveys;
    /**
     * Whether the cached `$surveys` definitions have aged past their TTL. Returns false when no
     * timestamp is recorded (e.g. surveys injected directly in tests) so the cache stays valid.
     */
    private _isSurveyCacheStale;
    private _isSurveyRefreshBackingOff;
    /**
     * Marks a survey as seen for the current device, mirroring the local state the SDK records
     * when it shows or sends a survey itself.
     *
     * Use this when you display surveys through your own backend/integration (so the SDK never
     * captures the `survey shown`/`sent`/`dismissed` events) and still want PostHog's display
     * logic to honour the "already seen" and wait-period checks on subsequent page loads.
     *
     * Note: surveys configured to repeat (`schedule: 'always'` or event `repeatedActivation`)
     * intentionally bypass the seen check, so marking them as seen will not stop them showing.
     *
     * @param surveyId The ID of the survey to mark as seen.
     * @param options Optional settings. `iteration` is the survey's current iteration number, if any.
     */
    markSurveyAsSeen(surveyId: string, options?: {
        iteration?: number | null;
    }): void;
    /** Helper method to notify all registered callbacks */
    private _notifySurveyCallbacks;
    getActiveMatchingSurveys(callback: SurveyCallback, forceReload?: boolean): void;
    private _getSurveyById;
    private _checkSurveyEligibility;
    private _checkSurveyRenderability;
    canRenderSurvey(surveyId: string | Survey): SurveyRenderReason;
    canRenderSurveyAsync(surveyId: string, forceReload: boolean): Promise<SurveyRenderReason>;
    renderSurvey(surveyId: string | Survey, selector: string, properties?: Properties): void;
    displaySurvey(surveyId: string, options: DisplaySurveyOptions): void;
    cancelPendingSurvey(surveyId: string): void;
    handlePageUnload(): void;
}

/** Browser-v1 compatibility wrapper for the shared surveys extension. */
declare class BrowserSurveys extends PostHogSurveys {
    private readonly _instance;
    constructor(_instance: PostHog);
    protected _sendSurveysRequest(path: string, init: SendRequestInit): Promise<ApiResponse>;
}

declare class Toolbar implements Extension {
    instance: PostHog;
    constructor(instance: PostHog);
    private _setToolbarState;
    private _getToolbarState;
    initialize(): boolean;
    /**
     * To load the toolbar, we need an access token and other state. That state comes from one of three places:
     * 1. In the URL hash params
     * 2. From session storage under the key `toolbarParams` if the toolbar was initialized on a previous page
     */
    maybeLoadToolbar(location?: Location | undefined, localStorage?: Storage | undefined, history?: History | undefined): boolean;
    private _callLoadToolbar;
    loadToolbar(params?: ToolbarParams): boolean;
    /** @deprecated Use "loadToolbar" instead. */
    _loadEditor(params: ToolbarParams): boolean;
    /** @deprecated Use "maybeLoadToolbar" instead. */
    maybeLoadEditor(location?: Location | undefined, localStorage?: Storage | undefined, history?: History | undefined): boolean;
}

declare class PostHogExceptions implements Extension {
    private readonly _instance;
    private _suppressionRules;
    private _errorPropertiesBuilder;
    private _exceptionStepsBuffer;
    private _exceptionStepsConfig;
    constructor(instance: PostHog);
    onConfigChange(): void;
    onRemoteConfig(result: RemoteConfigResult): void;
    private get _captureExtensionExceptions();
    buildProperties(input: unknown, metadata?: {
        handled?: boolean;
        syntheticException?: Error;
    }): ErrorTracking.ErrorProperties;
    addExceptionStep(message: string, properties?: Properties): void;
    sendExceptionEvent(properties: Properties): CaptureResult | undefined;
    private _addBufferedExceptionSteps;
    private _addDroppedExceptionStep;
    private _coerceExceptionStepProperties;
    private _getExceptionStepsConfig;
    private _matchesSuppressionRule;
    private _isExtensionException;
    private _isInjectedBrowserScriptException;
    private _isPostHogException;
    private _isExceptionList;
}

interface WebExperimentTransform {
    attributes?: {
        name: string;
        value: string;
    }[];
    selector?: string;
    text?: string;
    html?: string;
    imgUrl?: string;
    css?: string;
}
type WebExperimentUrlMatchType = 'regex' | 'not_regex' | 'exact' | 'is_not' | 'icontains' | 'not_icontains';
interface WebExperimentVariant {
    conditions?: {
        url?: string;
        urlMatchType?: WebExperimentUrlMatchType;
        utm?: {
            utm_source?: string;
            utm_medium?: string;
            utm_campaign?: string;
            utm_term?: string;
        };
    };
    variant_name: string;
    transforms: WebExperimentTransform[];
}
interface WebExperiment {
    id: number;
    name: string;
    feature_flag_key?: string;
    variants: Record<string, WebExperimentVariant>;
}
type WebExperimentsCallback = (webExperiments: WebExperiment[]) => void;

declare class WebExperiments implements Extension {
    private _instance;
    private _flagToExperiments?;
    private get _config();
    constructor(_instance: PostHog);
    initialize(): void;
    onFeatureFlags(flags: string[]): void;
    previewWebExperiment(): void;
    loadIfEnabled(): void;
    getWebExperimentsAndEvaluateDisplayLogic: (forceReload?: boolean) => void;
    getWebExperiments(callback: WebExperimentsCallback, forceReload: boolean, previewing?: boolean): void;
    private _showPreviewWebExperiment;
    private static _matchesTestVariant;
    private static _matchUrlConditions;
    static getWindowLocation(): Location | undefined;
    private static _matchUTMConditions;
    private static _logInfo;
    private _applyTransforms;
    _is_bot(): boolean | undefined;
}

declare class PostHogConversations implements Extension {
    private _instance;
    private _isConversationsEnabled?;
    private _conversationsManager;
    private _isInitializing;
    private _remoteConfig;
    private _remoteConfigSuccessful?;
    private _loadFailed;
    constructor(_instance: PostHog);
    initialize(): void;
    onRemoteConfig(result: RemoteConfigResult): void;
    reset(): void;
    loadIfEnabled(): void;
    /** Helper to finalize conversations initialization */
    private _completeInitialization;
    /** Helper to handle initialization errors */
    private _handleLoadError;
    /**
     * Show the conversations widget (button and chat panel)
     */
    show(): void;
    /**
     * Hide the conversations widget completely (button and chat panel)
     */
    hide(): void;
    /**
     * Check if conversations are available (enabled in remote config AND loaded)
     * Use this to check if conversations API can be used.
     */
    isAvailable(): boolean;
    /**
     * Explain why {@link isAvailable} is currently false, or null when conversations are available.
     * Lets a caller that falls back to another channel record the specific cause (bundle blocked,
     * disabled in the project, remote config not loaded yet, still initializing, …) rather than
     * collapsing every case into a single "unavailable" signal.
     */
    getUnavailableReason(): ConversationsUnavailableReason | null;
    /**
     * Check if the widget is currently visible (rendered and shown)
     */
    isVisible(): boolean;
    /**
     * Send a message programmatically
     * Creates a new ticket if none exists or if newTicket is true
     *
     * @param message - The message text to send
     * @param userTraits - Optional user identification data (name, email)
     * @param newTicket - If true, forces creation of a new ticket (starts new conversation)
     * @returns Promise with response or null if conversations not available yet
     * @note Conversations must be available first (check with isAvailable())
     *
     * @example
     * // Send to existing or create new conversation
     * const response = await posthog.conversations.sendMessage('Hello!', {
     *   name: 'John Doe',
     *   email: 'john@example.com'
     * })
     *
     * @example
     * // Force creation of a new conversation/ticket
     * const newConvo = await posthog.conversations.sendMessage('Start fresh', undefined, true)
     */
    sendMessage(message: string, userTraits?: UserProvidedTraits, newTicket?: boolean): Promise<SendMessageResponse | null>;
    /**
     * Get messages for the current or specified ticket
     *
     * @param ticketId - Optional ticket ID (defaults to current active ticket)
     * @param after - Optional ISO timestamp to fetch messages after
     * @returns Promise with messages response or null if conversations not available yet
     * @note Conversations must be available first (check with isAvailable())
     *
     * @example
     * // Get messages for current ticket
     * const messages = await posthog.conversations.getMessages()
     *
     * // Get messages for specific ticket
     * const messages = await posthog.conversations.getMessages('ticket-uuid')
     */
    getMessages(ticketId?: string, after?: string): Promise<GetMessagesResponse | null>;
    /**
     * Mark messages as read for the current or specified ticket
     *
     * @param ticketId - Optional ticket ID (defaults to current active ticket)
     * @returns Promise with response or null if conversations not available yet
     * @note Conversations must be available first (check with isAvailable())
     *
     * @example
     * await posthog.conversations.markAsRead()
     */
    markAsRead(ticketId?: string): Promise<MarkAsReadResponse | null>;
    /**
     * Get list of tickets for the current widget session
     *
     * @param options - Optional filtering and pagination options
     * @returns Promise with tickets response or null if conversations not available yet
     * @note Conversations must be available first (check with isAvailable())
     *
     * @example
     * const tickets = await posthog.conversations.getTickets({
     *   limit: 10,
     *   offset: 0,
     *   status: 'open'
     * })
     */
    getTickets(options?: GetTicketsOptions): Promise<GetTicketsResponse | null>;
    /**
     * Request a restore link email for previous conversations.
     *
     * @param email - Email address associated with previous conversations
     * @returns Promise with generic success response or null if conversations unavailable
     */
    requestRestoreLink(email: string): Promise<RequestRestoreLinkResponse | null>;
    /**
     * Redeem a restore token and relink eligible tickets to this browser session.
     *
     * @param restoreToken - Opaque restore token from restore email link
     * @returns Promise with restore status or null if conversations unavailable
     */
    restoreFromToken(restoreToken: string): Promise<RestoreFromTokenResponse | null>;
    /**
     * Parse and redeem `ph_conv_restore` token from the current URL.
     *
     * @returns Promise with restore status, or null when no token/conversations unavailable
     */
    restoreFromUrlToken(): Promise<RestoreFromTokenResponse | null>;
    /**
     * Get the current active ticket ID
     * Returns null if no conversation has been started yet or if not available
     *
     * @returns Ticket ID or null
     * @note Safe to call before conversations are available, will return null
     *
     * @example
     * const ticketId = posthog.conversations.getCurrentTicketId()
     * if (ticketId) {
     *   console.log('Current ticket ID:', ticketId)
     * }
     */
    getCurrentTicketId(): string | null;
    /**
     * Get the widget session ID (persistent browser identifier)
     * This ID is used for access control and stays the same across page loads
     * Returns null if conversations not available yet
     *
     * @returns Session ID or null if not available
     * @note Safe to call before conversations are available, will return null
     *
     * @example
     * const sessionId = posthog.conversations.getWidgetSessionId()
     * if (!sessionId) {
     *   // Conversations not available yet
     *   posthog.conversations.show()
     * }
     */
    getWidgetSessionId(): string | null;
    /** @internal Called by PostHog.setIdentity() -- forwards to the manager without recursing */
    _onIdentityChanged(): void;
    /** @internal Called by PostHog.clearIdentity() -- forwards to the manager without recursing */
    _onIdentityCleared(): void;
}

interface FeatureFlagsConfig {
    readonly bootstrap: {
        readonly featureFlags?: Readonly<Record<string, string | boolean>>;
        readonly featureFlagPayloads?: Readonly<Record<string, JsonType>>;
    };
    readonly remoteRequestsDisabled: boolean;
    readonly featureFlagsDisabled: boolean;
    readonly onlyEvaluateSurveyFeatureFlags: boolean;
    readonly deduplicateCallsPerSession: boolean;
    readonly cacheTtlMs?: number;
    readonly refreshIntervalMs?: number;
    readonly requestTimeoutMs: number;
    readonly compression?: Compression | 'best-available';
    readonly evaluationContexts: readonly string[];
    readonly flagKeys?: readonly string[];
}
interface FeatureFlagsConfigSource {
    get(): Readonly<FeatureFlagsConfig>;
}

declare class PostHogFeatureFlags implements Extension$1 {
    readonly name: _posthog_browser_common.ExtensionToken<PostHogFeatureFlags>;
    _override_warning: boolean;
    featureFlagEventHandlers: FeatureFlagsCallback[];
    $anon_distinct_id: string | undefined;
    private _client?;
    private _initializingClient?;
    private _logger;
    private _dynamicProperties?;
    private _crossTabPersistenceUnsubscribe?;
    private _baseEventProperties;
    private _eventPropertiesWithFlagValues;
    private _reloadingHandlers;
    private _hasLoadedFlags;
    private _requestInFlight;
    private _requestGeneration;
    private _reloadingDisabled;
    private _additionalReloadRequested;
    private _reloadDebouncer?;
    private _flagsLoadedFromRemote;
    private _staleCacheRefreshTriggered;
    private _consecutiveStatusZeroFailures;
    private _refreshInterval?;
    private _refreshIntervalMs?;
    private _lastRefreshAt?;
    private readonly _configSource;
    private readonly _mutableConfigSource?;
    private readonly _instance?;
    constructor(instance: PostHog);
    constructor(configSource: FeatureFlagsConfigSource);
    updateConfig(config: PostHogConfig, remoteRequestsDisabled: boolean): void;
    setup(client: Client): void | Promise<void>;
    private _finishSetup;
    private _onOnline;
    private _refreshIfDue;
    private _onVisibilityChange;
    private _syncAutomaticRefresh;
    private _scheduleNextRefresh;
    private _stopAutomaticRefresh;
    destroy(): void;
    dispose(): void;
    private _dispose;
    private get _config();
    private _prop;
    private _set;
    private _markCrossTabFeatureFlagSnapshot;
    private _remove;
    private _persist;
    private _rebuildEventProperties;
    /**
     * Check if the feature flag cache is stale based on the configured TTL.
     */
    private _isCacheStale;
    /**
     * Triggers a debounced reload when cache staleness is first detected.
     * Returns true if cache is stale, false otherwise.
     */
    private _checkAndTriggerStaleRefresh;
    private _getValidEvaluationEnvironments;
    private _getValidFlagKeys;
    initialize(): void;
    updateFlags(flags: Record<string, boolean | string>, payloads?: Record<string, JsonType>, options?: {
        merge?: boolean;
    }): void;
    get hasLoadedFlags(): boolean;
    getFlags(): string[];
    getFlagsWithDetails(): Record<string, FeatureFlagDetail>;
    getAllFeatureFlags(): FeatureFlagResult[];
    getFlagVariants(): Record<string, string | boolean>;
    getFlagPayloads(): Record<string, JsonType>;
    /**
     * Reloads feature flags asynchronously.
     *
     * Constraints:
     *
     * 1. Avoid parallel requests
     * 2. Delay a few milliseconds after each reloadFeatureFlags call to batch subsequent changes together
     */
    reloadFeatureFlags(): void;
    private _clearDebouncer;
    onReloading(handler: () => void): () => void;
    ensureFlagsLoaded(): void;
    setAnonymousDistinctId(anon_distinct_id: string): void;
    setReloadingPaused(isPaused: boolean): void;
    resetFlagCallReported(): void;
    _callFlagsEndpoint(options?: {
        disableFlags?: boolean;
    }): void;
    private _hasStatusZeroCircuitBreakerTripped;
    private _trackStatusZeroReachability;
    /**
     * Get feature flag's value for user.
     *
     * By default, this method may return cached values from localStorage if the `/flags` endpoint
     * hasn't responded yet. This reduces flicker but means you might briefly see stale values
     * (e.g., a flag that was disabled on the server).
     *
     * ### Usage:
     *
     *     if(posthog.getFeatureFlag('my-flag') === 'some-variant') { // do something }
     *
     *     // Only use fresh values from the server (returns undefined until /flags responds)
     *     if(posthog.getFeatureFlag('my-flag', { fresh: true }) === 'some-variant') { // do something }
     *
     * @param {String} key Key of the feature flag.
     * @param {Object} options Optional settings.
     * @param {boolean} [options.send_event=true] If false, won't send a $feature_flag_called event to PostHog.
     * @param {boolean} [options.fresh=false] If true, only returns values loaded from the server, not cached localStorage values.
     *                  Use this when you need to ensure the flag value reflects the current server state,
     *                  such as after disabling a flag. Returns undefined until the /flags endpoint responds.
     * @returns {boolean | string | undefined} The flag value, or undefined if not found or not yet loaded.
     */
    getFeatureFlag(key: string, options?: FeatureFlagOptions): boolean | string | undefined;
    getFeatureFlagDetails(key: string): FeatureFlagDetail | undefined;
    /**
     * @deprecated Use `getFeatureFlagResult()` instead which properly tracks the feature flag call.
     * `getFeatureFlagPayload()` does not emit the `$feature_flag_called` event which may result in
     * missing analytics. This method will be removed in a future version.
     */
    getFeatureFlagPayload(key: string): JsonType;
    /**
     * Get a feature flag result including both the flag value and payload, while properly tracking the call.
     * This method emits the `$feature_flag_called` event by default.
     *
     * By default, this method may return cached values from localStorage if the `/flags` endpoint
     * hasn't responded yet. This reduces flicker but means you might briefly see stale values
     * (e.g., a flag that was disabled on the server).
     *
     * ### Usage:
     *
     *     const result = posthog.getFeatureFlagResult('my-flag')
     *     if (result?.enabled) {
     *         console.log('Flag is enabled with payload:', result.payload)
     *     }
     *
     *     // Only use fresh values from the server
     *     const freshResult = posthog.getFeatureFlagResult('my-flag', { fresh: true })
     *
     * @param {String} key Key of the feature flag.
     * @param {Object} [options] Options for the feature flag lookup.
     * @param {boolean} [options.send_event=true] If false, won't send the $feature_flag_called event.
     * @param {boolean} [options.fresh=false] If true, only returns values loaded from the server, not cached localStorage values.
     *                  Use this when you need to ensure the flag value reflects the current server state.
     *                  Returns undefined until the /flags endpoint responds.
     * @returns {FeatureFlagResult | undefined} The feature flag result including key, enabled, variant, and payload.
     */
    getFeatureFlagResult(key: string, options?: FeatureFlagOptions): FeatureFlagResult | undefined;
    private _captureFeatureFlagCalled;
    getRemoteConfigPayload(key: string, callback: RemoteConfigFeatureFlagCallback): void;
    private _getRemoteConfigPayload;
    /**
     * See if feature flag is enabled for user.
     *
     * By default, this method may return cached values from localStorage if the `/flags` endpoint
     * hasn't responded yet. This reduces flicker but means you might briefly see stale values
     * (e.g., a flag that was disabled on the server).
     *
     * ### Usage:
     *
     *     if(posthog.isFeatureEnabled('beta-feature')) { // do something }
     *
     *     // Only use fresh values from the server
     *     if(posthog.isFeatureEnabled('beta-feature', { fresh: true })) { // do something }
     *
     * @param {String} key Key of the feature flag.
     * @param {Object} [options] Optional settings.
     * @param {boolean} [options.send_event=true] If false, won't send a $feature_flag_called event to PostHog.
     * @param {boolean} [options.fresh=false] If true, only returns values loaded from the server, not cached localStorage values.
     *                  Use this when you need to ensure the flag value reflects the current server state.
     *                  Returns undefined until the /flags endpoint responds.
     * @param {boolean} [options.defaultValue] Value to return when the flag has no value, e.g. flags have not loaded yet or no flag with that key exists.
     * @returns {boolean | undefined} Whether the flag is enabled; when the flag has no value, defaultValue if given, otherwise undefined.
     */
    isFeatureEnabled(key: string, options: IsFeatureEnabledOptions & {
        defaultValue: boolean;
    }): boolean;
    isFeatureEnabled(key: string, options?: IsFeatureEnabledOptions): boolean | undefined;
    addFeatureFlagsHandler(handler: FeatureFlagsCallback): void;
    removeFeatureFlagsHandler(handler: FeatureFlagsCallback): void;
    receivedFeatureFlags(response: Partial<FlagsResponse>, errorsLoading?: boolean, options?: {
        partialResponse?: boolean;
    }): void;
    private _receivedFeatureFlags;
    /**
     * @deprecated Use overrideFeatureFlags instead. This will be removed in a future version.
     */
    override(flags: boolean | string[] | Record<string, string | boolean>, suppressWarning?: boolean): void;
    /**
     * Override feature flags on the client-side. Useful for setting non-persistent feature flags,
     * or for testing/debugging feature flags in the PostHog app.
     *
     * ### Usage:
     *
     *     - posthog.featureFlags.overrideFeatureFlags(false) // clear all overrides
     *     - posthog.featureFlags.overrideFeatureFlags(['beta-feature']) // enable flags
     *     - posthog.featureFlags.overrideFeatureFlags({'beta-feature': 'variant'}) // set variants
     *     - posthog.featureFlags.overrideFeatureFlags({ flags: ['beta-feature'] }) // enable flags
     *     - posthog.featureFlags.overrideFeatureFlags({ flags: {'beta-feature': 'variant'} }) // set variants
     *     - posthog.featureFlags.overrideFeatureFlags({ // set both flags and payloads
     *         flags: {'beta-feature': 'variant'},
     *         payloads: { 'beta-feature': { someData: true } }
     *       })
     *     - posthog.featureFlags.overrideFeatureFlags({ // only override payloads
     *         payloads: { 'beta-feature': { someData: true } }
     *       })
     */
    overrideFeatureFlags(overrideOptions: OverrideFeatureFlagsOptions): void;
    private _overrideFeatureFlags;
    onFeatureFlags(callback: FeatureFlagsCallback): () => void;
    updateEarlyAccessFeatureEnrollment(key: string, isEnrolled: boolean, stage?: string): void;
    getEarlyAccessFeatures(callback: EarlyAccessFeatureCallback, force_reload?: boolean, stages?: EarlyAccessFeatureStage[]): void;
    private _getEarlyAccessFeatures;
    _prepareFeatureFlagsForCallbacks(): {
        flags: string[];
        flagVariants: Record<string, string | boolean>;
    };
    _fireFeatureFlagsCallbacks(errorsLoading?: boolean): void;
    /**
     * Set override person properties for feature flags.
     * This is used when dealing with new persons / where you don't want to wait for ingestion
     * to update user properties.
     */
    setPersonPropertiesForFlags(properties: Properties, reloadFeatureFlags?: boolean): void;
    private _setPersonPropertiesForFlags;
    /**
     * Remove override person properties used for feature flags.
     * This is the counterpart to setPersonPropertiesForFlags, used when person properties
     * are unset so flags re-evaluate without the removed values.
     */
    unsetPersonPropertiesForFlags(propertyNames: string[], reloadFeatureFlags?: boolean): void;
    resetPersonPropertiesForFlags(reloadFeatureFlags?: boolean): void;
    /**
     * Set override group properties for feature flags.
     * This is used when dealing with new groups / where you don't want to wait for ingestion
     * to update properties.
     * Takes in an object, the key of which is the group type.
     * For example:
     *     setGroupPropertiesForFlags({'organization': { name: 'CYZ', employees: '11' } })
     */
    setGroupPropertiesForFlags(properties: {
        [type: string]: Properties;
    }, reloadFeatureFlags?: boolean): void;
    resetGroupPropertiesForFlags(group_type?: string): void;
    reset(): void;
}

declare class PostHogLogs implements Extension$1 {
    private readonly _instance;
    readonly name: _posthog_browser_common.ExtensionToken<PostHogLogs>;
    private _isLogsEnabled;
    private _isLoaded;
    private _isLoading;
    private readonly _logger;
    private readonly _coreLogger;
    private _queue;
    private _core;
    private _resolvedConfig;
    private _resolvedFrom;
    private _capture_logger;
    private _consoleQueue;
    private _consoleCore;
    private _consoleLogsDispose;
    private _consoleResolvedConfig;
    private _consoleResolvedFrom;
    private _consecutiveStatusZeroFailures;
    private _client?;
    private _remoteConfigSubscription?;
    private _disposed;
    private _consoleBuffer;
    private _consoleRecorderUnpatchers;
    private _isRecordingConsole;
    private _consoleRecorderTimeout;
    private _isRecordingConsoleEntry;
    constructor(_instance: PostHog);
    private _onReconnect;
    private _buildCore;
    private _getCore;
    private _getConsoleCore;
    setup(client: Client): void;
    dispose(): void;
    onRemoteConfig(result: DeepReadonly<RemoteConfigResult>): void;
    reset(): void;
    captureLog(options: CaptureLogOptions): void;
    /** @internal */
    captureConsoleLog(options: CaptureLogOptions): void;
    /** @internal */
    captureBufferedConsoleLog(options: CaptureLogOptions, context: LogSdkContext, occurredAtMs: number): void;
    private _persistedCaptureHint;
    private _remoteConfigWillArrive;
    /**
     * Releases everything console capture is holding when capturing is turned off: the
     * pre-load buffer, the `console` patches, and console records already queued — at
     * that moment rather than whenever the page next writes to the console.
     *
     * @internal
     */
    _onOptOut(): void;
    private _stopRecorderStartedByPersistedHint;
    private _startConsoleRecorder;
    private _recordConsoleEntry;
    private _stopConsoleRecorder;
    private _takeConsoleBuffer;
    get logger(): Logger;
    flushLogs(transport?: 'XHR' | 'fetch' | 'sendBeacon'): void;
    private _logFlushError;
    loadIfEnabled(): void;
    private _createHost;
    private _sendLogsBatch;
    private _trackEndpointReachability;
    private _flushViaTransport;
    private _drainQueueViaTransport;
    private _logsUrl;
    private _getSdkContext;
}

/**
 * The `posthog.metrics` extension: a statsd-style pre-aggregating client.
 *
 * ```ts
 * posthog.metrics.count('orders_created', 1)
 * posthog.metrics.gauge('active_connections', 42)
 * posthog.metrics.histogram('api_latency', 187, { unit: 'ms' })
 * ```
 *
 * Aggregation, series identity, and flush policy live in core's
 * `PostHogMetrics`; this wrapper adapts it to the browser request layer.
 */
declare class PostHogMetrics implements Extension {
    private readonly _instance;
    private readonly _logger;
    private _core;
    private _resolvedFrom;
    constructor(_instance: PostHog);
    initialize(): void;
    private _getCore;
    /** Add to a counter — things that only go up. Value defaults to 1. */
    count(name: string, value?: number, options?: CaptureMetricOptions): void;
    /** Record the current value of something that goes up and down. */
    gauge(name: string, value: number, options?: CaptureMetricOptions): void;
    /** Record one observation of a distribution (latency, payload size). */
    histogram(name: string, value: number, options?: CaptureMetricOptions): void;
    /**
     * Sends the aggregated window now. With a transport, the window is
     * drained synchronously — bypassing the flush serializer, which could be
     * awaiting an in-flight send that will never finish during unload — and
     * the payload is handed to that transport in the same tick, so the
     * pagehide `sendBeacon` drain survives the page going away. A drained
     * window is not retried; the page is gone either way.
     */
    flush(transport?: 'XHR' | 'fetch' | 'sendBeacon'): Promise<void>;
    reset(): void;
    private _createHost;
    private _sendMetricsBatch;
    private _metricsUrl;
}

type PostHogInterface = Omit<PostHog$1, 'config' | 'init' | 'set_config'> & {
    config: PostHogConfig;
    set_config(config: Partial<PostHogConfig>): void;
};
type PostHogConfig = Omit<PostHogConfig$1, 'loaded'> & {
    loaded: (posthog: PostHogInterface) => void;
    /**
     * Disables capturing the `$device_model` super-property.
     *
     * When capturing is enabled (the default), PostHog resolves the hardware model once during init
     * via `navigator.userAgentData.getHighEntropyValues(['model'])` and registers it as the raw OEM
     * code (e.g. `Pixel 7`). This is Chromium-only and only meaningful on Android — it resolves to
     * `undefined` on Safari/Firefox and to an empty string on desktop, in which cases nothing is
     * registered.
     *
     * This opt-out is offered because `getHighEntropyValues` is still experimental and Chromium-only
     * (not yet a cross-browser standard); set it to `true` to skip the call entirely.
     *
     * @default false
     */
    disableDeviceModel?: boolean;
    /**
     * Internal: Extension class overrides for tree-shaking support.
     * When provided, these classes are used instead of the default imports.
     * This enables entrypoints to control which extensions are bundled.
     * @internal
     */
    __extensionClasses?: {
        exceptions?: ExtensionConstructor<PostHogExceptions>;
        historyAutocapture?: ExtensionConstructor<HistoryAutocapture>;
        tracingHeaders?: ExtensionConstructor<TracingHeaders>;
        siteApps?: ExtensionConstructor<SiteApps>;
        sessionRecording?: ExtensionConstructor<SessionRecording>;
        autocapture?: ExtensionConstructor<Autocapture>;
        productTours?: ExtensionConstructor<PostHogProductTours>;
        heatmaps?: ExtensionConstructor<Heatmaps>;
        webVitalsAutocapture?: ExtensionConstructor<WebVitalsAutocapture>;
        exceptionObserver?: ExtensionConstructor<ExceptionObserver>;
        deadClicksAutocapture?: ExtensionConstructor<DeadClicksAutocapture>;
        surveys?: ExtensionConstructor<BrowserSurveys>;
        toolbar?: ExtensionConstructor<Toolbar>;
        experiments?: ExtensionConstructor<WebExperiments>;
        conversations?: ExtensionConstructor<PostHogConversations>;
        featureFlags?: ExtensionConstructor<PostHogFeatureFlags>;
        logs?: ExtensionConstructor<PostHogLogs>;
        metrics?: ExtensionConstructor<PostHogMetrics>;
    };
};
/**
 * Outcome of a remote config fetch: the config, or an explicit failure.
 * @internal
 */
type RemoteConfigResult = RemoteConfigResult$1;
/**
 * Flags returns feature flags and their payloads
 */
interface FlagsResponse extends RemoteConfig {
    featureFlags: Record<string, string | boolean>;
    featureFlagPayloads: Record<string, JsonType>;
    errorsWhileComputingFlags: boolean;
    requestId?: string;
    flags: Record<string, FeatureFlagDetail>;
    evaluatedAt?: number;
    /**
     * Server-controlled gate for minimal `$feature_flag_called` events. `true` only when the
     * project opted in; omitted otherwise. Absence always means full events.
     */
    minimalFlagCalledEvents?: boolean;
}
type SiteAppGlobals = {
    event: {
        uuid: string;
        event: EventName;
        properties: Properties;
        timestamp?: Date;
        elements_chain?: string;
        distinct_id?: string;
    };
    person: {
        properties: Properties;
    };
    groups: Record<string, {
        id: string;
        type: string;
        properties: Properties;
    }>;
};
type SiteAppLoader = {
    id: string;
    init: (config: {
        posthog: PostHog;
        callback: (success: boolean) => void;
    }) => {
        processEvent?: (globals: SiteAppGlobals) => void;
    };
};
type SiteApp = {
    id: string;
    loaded: boolean;
    errored: boolean;
    processedBuffer: boolean;
    processEvent?: (globals: SiteAppGlobals) => void;
};
type SessionStartReason = 'sampling_overridden' | 'recording_initialized' | 'linked_flag_matched' | 'linked_flag_overridden' | typeof SAMPLED | 'session_id_changed' | 'url_trigger_matched' | 'event_trigger_matched';

type PostHogWithFlags = Pick<PostHogInterface, 'setPersonPropertiesForFlags'> & {
    config: Pick<PostHogConfig, 'mask_personal_data_properties' | 'custom_personal_data_properties' | 'detect_google_search_app' | 'disable_capture_url_hashes' | 'custom_campaign_params'>;
};
declare const setAllPersonProfilePropertiesAsPersonPropertiesForFlags: (posthog: PostHogWithFlags) => void;

/**
 * Provides an implementation of sampling that samples based on the distinct ID.
 * Using the provided percentage.
 * Can be used to create a beforeCapture fn for a PostHog instance.
 *
 * Setting 0.5 will cause roughly 50% of distinct ids to have events sent.
 * Not 50% of events for each distinct id.
 *
 * @param percent a number from 0 to 1, 1 means always send and, 0 means never send the event
 */
declare function sampleByDistinctId(percent: number): BeforeSendFn;
/**
 * Provides an implementation of sampling that samples based on the session ID.
 * Using the provided percentage.
 * Can be used to create a beforeCapture fn for a PostHog instance.
 *
 * Setting 0.5 will cause roughly 50% of sessions to have events sent.
 * Not 50% of events for each session.
 *
 * @param percent a number from 0 to 1, 1 means always send and, 0 means never send the event
 */
declare function sampleBySessionId(percent: number): BeforeSendFn;
/**
 * Provides an implementation of sampling that samples based on the event name.
 * Using the provided percentage.
 * Can be used to create a beforeCapture fn for a PostHog instance.
 *
 * @param eventNames an array of event names to sample, sampling is applied across events not per event name
 * @param percent a number from 0 to 1, 1 means always send, 0 means never send the event
 */
declare function sampleByEvent(eventNames: (KnownEventName | string)[], percent: number): BeforeSendFn;
declare const printAndDropEverything: BeforeSendFn;

/**
 * An *unknown* action.
 * This is the most minimal possible shape for an action.
 * Allows for type-safe usage of actions without dependencies.
 */
interface UnknownAction {
    type: string;
    [extraProps: string]: unknown;
}
/**
 * A *dispatching function* (or simply *dispatch function*) is a function that
 * accepts an action or an async action; it then may or may not dispatch one
 * or more actions to the store.
 */
interface Dispatch<A extends UnknownAction = UnknownAction> {
    <T extends A>(action: T): T;
}
/**
 * A middleware is a higher-order function that composes a dispatch function
 * to return a new dispatch function. It often turns async actions into
 * actions.
 *
 * This matches Redux Toolkit's Middleware interface for compatibility.
 */
interface ReduxMiddleware<_DispatchExt = {}, S = any, D extends Dispatch = Dispatch> {
    (api: MiddlewareAPI<D, S>): (next: (action: unknown) => unknown) => (action: unknown) => unknown;
}
/**
 * A middleware API is an object containing the store's dispatch function and getState function.
 * A middleware is given the middleware API as its first parameter.
 */
interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> {
    dispatch: D;
    getState(): S;
}
interface StateEvent {
    type: string;
    payload?: any;
    timestamp: number;
    executionTimeMs?: number;
    prevState: any;
    nextState: any;
    changedState: any;
}
type PostHogStateLogger = (title: string, stateEvent: StateEvent) => void;
interface PostHogStateLoggerConfig<S = any> {
    maskAction?: (action: UnknownAction) => UnknownAction | null;
    maskState?: (state: S, action?: UnknownAction) => S;
    titleFunction?: (stateEvent: StateEvent) => string;
    logger?: PostHogStateLogger;
    /**
     * actions logging is token bucket rate limited to avoid flooding
     * this controls the rate limiter's refill rate, see BucketedRateLimiter docs for details
     * normally this is only changed with posthog support assistance
     */
    rateLimiterRefillRate?: number;
    /**
     * actions logging is token bucket rate limited to avoid flooding
     * this controls the rate limiter's bucket size, see BucketedRateLimiter docs for details
     * normally this is only changed with posthog support assistance
     */
    rateLimiterBucketSize?: number;
    /**
     * Controls how many levels deep the state diffing goes when looking for changed keys
     * Defaults to 5
     * Increase this if you have nested state changes that are not being captured
     * Decrease this if you are seeing too much state in the diffs and want to reduce noise
     * Note that increasing this will increase the CPU cost of diffing, so use with caution
     * and only increase if necessary
     * Normally this is only changed with posthog support assistance
     */
    __stateComparisonDepth?: number;
    /**
     * Which parts of the state event to include in the logged event
     * By default we include, previous and changed keys only
     *
     * NB the more you include the more likely a log will be dropped by rate limiting or max size limits
     */
    include?: {
        prevState?: boolean;
        nextState?: boolean;
        changedState?: boolean;
    };
}
declare function browserConsoleLogger(title: string, stateEvent: StateEvent): void;
/**
 * Logger that sends state events to PostHog session recordings
 * Requires that the loaded posthog instance is provided
 * And returns the function to use as the logger
 *
 * e.g. const config = { logger: sessionRecordingLoggerForPostHogInstance(posthog) }
 */
declare const sessionRecordingLoggerForPostHogInstance: (posthog: PostHog) => PostHogStateLogger;
/**
 * Creates a Kea plugin that logs actions and state changes to a provided logger
 * This can be used as a plugin in any Kea setup to capture state changes
 */
declare function posthogKeaLogger<S = any>(config?: PostHogStateLoggerConfig<S>): {
    name: string;
    events: {
        beforeReduxStore(options: any): void;
    };
};
/**
 * Creates a Redux middleware that logs actions and state changes to a provided logger
 * This can be used as middleware in any Redux store to capture state changes
 *
 * The logging uses token-bucket rate limiting to avoid flooding the logging with many changes
 * by default logging rate limiting captures ten action instances before rate limiting by action type
 * refills at a rate of one token / 1-second period
 * e.g. will capture 1 rate limited action every 1 second until the burst ends
 */
declare function posthogReduxLogger<S = any>(config?: PostHogStateLoggerConfig<S>): ReduxMiddleware<{}, S>;

export { browserConsoleLogger, posthogKeaLogger, posthogReduxLogger, printAndDropEverything, sampleByDistinctId, sampleByEvent, sampleBySessionId, sessionRecordingLoggerForPostHogInstance, setAllPersonProfilePropertiesAsPersonPropertiesForFlags };