posthog-js
Version:
Posthog-js allows you to automatically capture usage and send events to PostHog.
1,862 lines • 62.3 kB
TypeScript
import { PostHog } from './module';
import { PropertyMatchType, RemoteConfigResult, SurveyActionType, SurveyEventWithFilters } from "@posthog/browser-common";
import { Autocapture } from "@posthog/browser-common/autocapture";
import { ErrorTracking, SurveyPosition } from "@posthog/core";
import { ConsoleLogsLoader } from "@posthog/browser-common/logs-types";
import rageclick_default from "@posthog/browser-common/rageclick";
import { PostHogSurveys } from "@posthog/browser-common/surveys";
import { PostHogFeatureFlags } from "@posthog/browser-common/feature-flags";
import { PostHogLogs } from "@posthog/browser-common/logs";
import { BeforeSendFn, CaptureMetricOptions, CaptureResult, DeadClicksAutoCaptureConfig, EventName, KnownEventName, PostHog as PostHog$1, PostHogConfig, Properties, Properties as Properties$1, SupportedWebVitalsMetrics, ToolbarParams } from "@posthog/types";
//#region lib/src/extensions/replay/external/triggerMatching.d.ts
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];
//#endregion
//#region lib/src/extensions/types.d.ts
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$1): void;
}
//#endregion
//#region lib/src/posthog-conversations-types.d.ts
/**
* 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';
//#endregion
//#region lib/src/extensions/replay/types/rrweb-types.d.ts
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 customEventData<T = unknown> = {
tag: string;
payload: T;
href?: string;
};
type customEvent<T = unknown> = {
type: typeof EventType.Custom;
data: customEventData<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;
};
//#endregion
//#region lib/src/utils/globals.d.ts
interface LazyLoadedDeadClicksAutocaptureInterface {
start: (observerTarget: Node) => void;
stop: () => void;
}
//#endregion
//#region lib/src/extensions/dead-clicks-autocapture.d.ts
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$1): void;
startIfEnabledOrStop(): void;
private _loadScript;
private _start;
stop(): void;
}
//#endregion
//#region lib/src/extensions/exception-autocapture/index.d.ts
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$1): void;
onConfigChange(): void;
captureException(errorProperties: ErrorTracking.ErrorProperties): void;
}
//#endregion
//#region lib/src/extensions/history-autocapture.d.ts
/**
* 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;
private _pendingPageview;
private _isFlushingPageview;
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 _isUrlChanging;
private _flushPendingPageview;
private _setupPopstateListener;
private _setupHashchangeListener;
}
//#endregion
//#region lib/src/extensions/tracing-headers.d.ts
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;
}
//#endregion
//#region lib/src/extensions/web-vitals/index.d.ts
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$1): void;
private get _callbackFlavor();
private _loadScript;
private _maskedURL;
private _flushToCapture;
private _addToBuffer;
private _startCapturing;
}
//#endregion
//#region lib/src/extensions/replay/session-recording.d.ts
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$1): 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$1;
/**
* 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;
flushBeforeIdentityReset(): void;
}
//#endregion
//#region lib/src/heatmaps.d.ts
type HeatmapEventBuffer = {
[key: string]: Properties$1[];
} | undefined;
declare class Heatmaps implements Extension {
instance: PostHog;
rageclicks: rageclick_default;
_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$1): void;
getAndClearBuffer(): HeatmapEventBuffer;
private _onDeadClick;
private _onVisibilityChange;
private _setupListeners;
private _removeListeners;
private _getProperties;
private _onClick;
private _onMouseMove;
private _capture;
private _flush;
}
//#endregion
//#region lib/src/extensions/product-tours/element-inference.d.ts
interface InferredSelector {
autoData: string;
text: string | null;
excludeText?: boolean;
precision?: number;
}
//#endregion
//#region lib/src/posthog-product-tours-types.d.ts
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;
/** 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;
//#endregion
//#region lib/src/posthog-product-tours.d.ts
declare class PostHogProductTours implements Extension {
private _instance;
private _productTourManager;
private _cachedTours;
private get _persistence();
constructor(instance: PostHog);
initialize(): void;
onRemoteConfig(result: RemoteConfigResult$1): 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;
}
//#endregion
//#region lib/src/site-apps.d.ts
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$1): void;
}
//#endregion
//#region lib/src/browser-surveys.d.ts
/** Browser-v1 configuration and lazy-loading adapter for the shared surveys extension. */
declare class BrowserSurveys extends PostHogSurveys {
constructor(instance: PostHog);
}
//#endregion
//#region lib/src/extensions/toolbar.d.ts
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;
}
//#endregion
//#region lib/src/posthog-exceptions.d.ts
declare class PostHogExceptions implements Extension {
private readonly _instance;
private _suppressionRules;
private _errorPropertiesBuilder;
private _exceptionStepsBuffer;
private _exceptionStepsConfig;
constructor(instance: PostHog);
onConfigChange(): void;
onRemoteConfig(result: RemoteConfigResult$1): void;
private get _captureExtensionExceptions();
buildProperties(input: unknown, metadata?: {
handled?: boolean;
syntheticException?: Error;
}): ErrorTracking.ErrorProperties;
addExceptionStep(message: string, properties?: Properties$1): void;
sendExceptionEvent(properties: Properties$1): CaptureResult | undefined;
private _addBufferedExceptionSteps;
private _addDroppedExceptionStep;
private _coerceExceptionStepProperties;
private _getExceptionStepsConfig;
private _matchesSuppressionRule;
private _isExtensionException;
private _isInjectedBrowserScriptException;
private _isPostHogException;
private _isExceptionList;
}
//#endregion
//#region lib/src/web-experiments-types.d.ts
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;
//#endregion
//#region lib/src/web-experiments.d.ts
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;
}
//#endregion
//#region lib/src/extensions/conversations/posthog-conversations.d.ts
declare class PostHogConversations implements Extension {
private _instance;
private _isConversationsEnabled?;
private _conversationsManager;
private _isInitializing;
private _remoteConfig;
private _remoteConfigSuccessful?;
private _loadFailed;
private _resetGeneration;
constructor(_instance: PostHog);
initialize(): void;
onRemoteConfig(result: RemoteConfigResult$1): 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;
}
//#endregion
//#region lib/src/posthog-persistence.d.ts
/**
* PostHog Persistence Object
* @constructor
*/
declare class PostHogPersistence {
private _config;
props: Properties$1;
private _storage;
private _campaign_params_url;
private readonly _name;
_disabled: boolean | undefined;
private _secure;
private _expire_days;
private _default_expiry;
private _cross_subdomain;
private _slotState;
private _splitStorageEligible;
private _storesIdentityInCookie;
private _splitStorage;
private readonly _ownsSplitStorage;
private _pendingSaveTimer;
private _lastSeenCookiePropertiesFingerprint;
private _lastSeenMainCookieValue;
private _cookieIdentityChangePending;
private _cookieSyncSuppressed;
private _pendingCrossTabFeatureFlagChanges;
private _storageMigrationInProgress;
private _localIdentityChangePending;
private _crossTabFeatureFlagIdentityMismatch;
private _metaIdentifierChangePending;
private _metaIdentifierStorageSnapshot;
private readonly _crossTabFeatureFlagHandlers;
private _onStorage?;
/**
* @param {PostHogConfig} config initial PostHog configuration
* @param {boolean=} isDisabled should persistence be disabled (e.g. because of consent management)
* @param {boolean=} allowDisabledRead restore stored state read-only during disabled initialization
*/
constructor(config: PostHogConfig$1, isDisabled?: boolean, ownsSplitStorage?: boolean, allowDisabledRead?: boolean);
markCrossTabFeatureFlagChanges(changes: Record<string, readonly string[] | true>): void;
onCrossTabFeatureFlagChange(handler: () => void): () => void;
destroy(): void;
private _syncCrossTabFeatureFlagProperties;
private _hasCrossTabFeatureFlagIdentityMismatch;
private _rememberCrossTabStorageFingerprint;
private _mergeCrossTabFeatureFlagProperties;
private _reconcileCrossTabFeatureFlagPropertiesBeforeWrite;
private _setCrossTabFeatureFlagChangesPending;
private _markAllCrossTabFeatureFlagChangesPending;
private _markLoadedCrossTabFeatureFlagChangesPending;
private _mergePendingCrossTabFeatureFlagChanges;
private _markPendingCrossTabFeatureFlagChanges;
private _saveDebounceMs;
private _rememberCurrentCookieProperties;
/**
* Adopt shared-cookie changes made by a sibling subdomain without replacing
* localStorage-only or pending in-memory properties. Returns true when a new
* non-empty cookie snapshot was observed.
*/
syncCookieProperties(): boolean;
private _syncCookieProperties;
consumeCookieIdentityChange(): boolean;
_beginCookieSyncSuppression(ignoreDisabled?: boolean): boolean;
_publishSuppressedCookieSnapshot(): void;
_endCookieSyncSuppression(publish?: boolean): void;
/**
* Returns whether persistence is disabled. Only available in SDKs > 1.257.1. Do not use on extensions, otherwise
* it'll break backwards compatibility for any version before 1.257.1.
*/
isDisabled?(): boolean;
private _buildStorage;
private _groupEntryName;
private _resolveSplitStorage;
properties(): Properties$1;
/**
* Reload persisted properties from storage.
*
* @param allowDisabled - Read without migration writes while disabled, for initial identity restoration
* or when shared consent changed before the in-memory disabled state was reconciled.
*/
load(allowDisabled?: boolean): void;
private _loadGroupEntries;
private _mainCarriesGroupKey;
private _groupEntryIsStale;
/**
* Refresh a single key from on-disk storage into `this.props` without
* touching the rest. Used by `SessionIdManager` on the cross-tab idle
* path so we can pick up a sibling tab's SESSION_ID write without
* either:
* - flushing our own (potentially stale) whole-props blob to storage
* via `flush()`, which would clobber the sibling's write, or
* - replacing all of `props` via `load()`, which would discard any
* in-memory writes that haven't yet been debounced to storage.
*/
refreshKey(prop: string): void;
private _refreshKeys;
/**
* Refresh the Meta identifier keys from storage, so a sibling tab's update is not lost.
* capture() calls this on every event, so it parses storage only when storage has changed
* since the identifiers last matched it. A full parse on each click made INP regress.
*/
refreshMetaIdentifiers(): void;
private _rememberMetaIdentifierStorageSnapshot;
private _storageSnapshot;
/**
* NOTE: Saving frequently causes issues with Recordings and Consent Management Platform (CMP) tools which
* observe cookie changes, and modify their UI, often causing infinite loops.
* As such callers of this should ideally check that the data has changed beforehand
*/
save(): void;
/**
* Force any pending debounced save to land in storage immediately.
* No-op when there is no pending timer — crucially, this means the
* `beforeunload` / `pagehide` listeners installed in the constructor
* cannot accidentally resurrect a storage entry that `remove()` or
* `clear()` just deleted. Without this guard, the listener would
* call `_writeNow()` and write the in-memory `props` (now `{}`) back
* to storage, breaking `posthog.reset()` / opt-out flows.
*/
flush(): void;
private _writeNow;
private _writeNowSplit;
private _partitionProps;
private _entryFingerprint;
private _writeEntry;
remove({ keepGroupEntries }?: {
keepGroupEntries?: boolean;
}): void;
clear(): void;
/**
* @param {Object} props
* @param {*=} default_value
* @param {number=} days
*/
register_once(props: Properties$1, default_value: any, days?: number): boolean;
/**
* @param {Object} props
* @param {number=} days
*/
register(props: Properties$1, days?: number): boolean;
unregister(propOrProps: string | readonly string[]): void;
update_campaign_params(): Properties$1 | undefined;
update_search_keyword(): void;
update_referrer_info(): void;
set_initial_person_info(): void;
get_initial_props(): Properties$1;
safe_merge(props: Properties$1): Properties$1;
update_config(config: PostHogConfig$1, oldConfig: PostHogConfig$1, isDisabled?: boolean): void;
private _truncateExistingPersonInfoForCookie;
set_disabled(disabled: boolean): void;
set_cross_subdomain(cross_subdomain: boolean): void;
set_secure(secure: boolean): void;
set_event_timer(event_name: string, timestamp: number): void;
remove_event_timer(event_name: string): number;
get_property(prop: string): any;
set_property(prop: string, to: any): void;
private _setProp;
private _deleteProp;
private _markGroupDirty;
private _slotWriteState;
}
//#endregion
//#region lib/src/posthog-featureflags.d.ts
/** Legacy constructor and configuration mapping for the shared flags extension. */
declare class PostHogFeatureFlags$1 extends PostHogFeatureFlags {
readonly name: import("@posthog/browser-common").ExtensionToken<PostHogFeatureFlags$1>;
private readonly _mutableConfigSource;
private readonly _instance;
constructor(instance: PostHog);
protected get _crossTabPersistence(): PostHogPersistence | undefined;
updateConfig(config: PostHogConfig$1, remoteRequestsDisabled: boolean): void;
}
//#endregion
//#region lib/src/posthog-logs.d.ts
/** Legacy configuration, log context, and console script loading. */
declare class PostHogLogs$1 extends PostHogLogs {
private readonly _instance;
readonly name: import("@posthog/browser-common").ExtensionToken<PostHogLogs$1>;
constructor(_instance: PostHog);
protected get _isRequestReady(): boolean;
protected _getConsoleLoader(): ConsoleLogsLoader | undefined;
}
//#endregion
//#region lib/src/posthog-metrics.d.ts
/**
* 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;
private _stopNetworkMetrics;
private _disposed;
constructor(_instance: PostHog);
initialize(): void;
onConfigChange(): 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;
/**
* Stops everything this extension installed: the global `fetch` and
* `XMLHttpRequest` wrappers, and the aggregator's pending window and timer.
* `shutdown()` calls this after its final flush, so a shut down instance
* leaves nothing behind in the page.
*/
dispose(): void;
private _createHost;
private _sendMetricsBatch;
private _metricsUrl;
}
//#endregion
//#region lib/src/extensions/webmcp.d.ts
declare class WebMCP {
private readonly _instance;
private _isPatched;
constructor(_instance: PostHog);
initialize(): void;
startIfEnabled(): void;
private _wrapTool;
private _captureToolCall;
}
//#endregion
//#region lib/src/types.d.ts
type PostHogInterface = Omit<PostHog$1, 'config' | 'init' | 'set_config'> & {
config: PostHogConfig$1;
set_config(config: Partial<PostHogConfig$1>): void;
};
type PostHogConfig$1 = Omit<PostHogConfig, '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$1>;
logs?: ExtensionConstructor<PostHogLogs$1>;
metrics?: ExtensionConstructor<PostHogMetrics>;
webMCP?: ExtensionConstructor<WebMCP>;
};
};
/**
* Outcome of a remote config fetch: the config, or an explicit failure.
* @internal
*/
type RemoteConfigResult$1 = RemoteConfigResult;
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';
//#endregion
//#region lib/src/customizations/setAllPersonProfilePropertiesAsPersonPropertiesForFlags.d.ts
type PostHogWithFlags = Pick<PostHogInterface, 'setPersonPropertiesForFlags'> & {
config: Pick<PostHogConfig$1, '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;
//#endregion
//#region lib/src/customizations/before-send.d.ts
/**
* 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;
//#endregion
//#region lib/src/customizations/bot-detection.d.ts
/**
* Opt-in heuristic that flags user agents whose Chrome token appears without
* the usual AppleWebKit / Safari tokens that real Chrome always emits. Legit
* mobile WebViews and custom WebView apps CAN omit these, so this is a
* client-side-only signal — intended for callers who want to filter or tag
* events in `before_send`, not a universal blocklist entry.
*
* This is deliberately a standalone utility (not wired into the default
* blocklist) so default SDK behavior is unchanged. Server-side rules remain
* the primary bot-detection surface — see posthog/posthog#109617 and #109620.
*
* @example
* ```ts
* import { isLikelyWebViewBot } from 'posthog-js/customizations'
*
* posthog.init('PROJECT_TOKEN', {
* before_send: (event) => {
* if (event && isLikelyWebViewBot(navigator.userAgent)) {
* event.properties.$suspected_webview_bot = true
* }
* return event
* },
* })
* ```
*/
declare function isLikelyWebViewBot(ua: string | undefined): boolean;
//#endregion
//#region lib/src/customizations/posthogReduxLogger.d.ts
/**
* 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>;
//#endregion
export { browserConsoleLogger, isLikelyWebViewBot, posthogKeaLogger, posthogReduxLogger, printAndDropEverything, sampleByDistinctId, sampleByEvent, sampleBySessionId, sessionRecordingLoggerForPostHogInstance, setAllPersonProfilePropertiesAsPersonPropertiesForFlags };