UNPKG

posthog-node

Version:
608 lines 29.1 kB
import type { PostHogCoreOptions, FeatureFlagValue, JsonType, PostHogFetchOptions, PostHogFetchResponse, PostHogFlagsAndPayloadsResponse } from '@posthog/core'; import { ContextData, ContextOptions } from './extensions/context/types'; import type { FeatureFlagEvaluations } from './feature-flag-evaluations'; import type { FlagDefinitionCacheProvider } from './extensions/feature-flags/cache'; export type IdentifyMessage = { distinctId: string; properties?: Record<string | number, any>; disableGeoip?: boolean; }; export type SendFeatureFlagsOptions = { onlyEvaluateLocally?: boolean; personProperties?: Record<string, any>; groupProperties?: Record<string, Record<string, any>>; flagKeys?: string[]; }; export type EventMessage = Omit<IdentifyMessage, 'distinctId'> & { distinctId?: string; event: string; groups?: Record<string, string | number>; /** * Attach feature flag values evaluated via `posthog.evaluateFlags()` to this event. * Prefer this over `sendFeatureFlags` — it guarantees the event carries the exact * values the code branched on and avoids a hidden `/flags` request on every capture. */ flags?: FeatureFlagEvaluations; /** * @deprecated Use the `flags` option with a `FeatureFlagEvaluations` object obtained * from `posthog.evaluateFlags()` instead. `sendFeatureFlags` fires a separate `/flags` * request on capture and may return different values than the ones the code branched on. */ sendFeatureFlags?: boolean | SendFeatureFlagsOptions; timestamp?: Date; uuid?: string; /** * Internal flag set by captureException() to indicate this $exception * event originated from the proper exception capture path. Used to warn users who call * capture() with '$exception' directly. */ _originatedFromCaptureException?: boolean; }; export type GroupIdentifyMessage = { groupType: string; groupKey: string; properties?: Record<string | number, any>; distinctId?: string; disableGeoip?: boolean; }; export type PropertyGroup = { type: 'AND' | 'OR'; values: PropertyGroup[] | FlagProperty[]; }; export type FlagProperty = { key: string; type?: string; value: FlagPropertyValue; operator?: string; negation?: boolean; dependency_chain?: string[]; }; export type FlagPropertyValue = string | number | (string | number)[] | boolean; /** * Options for overriding feature flags. * * Supports multiple formats: * - `false` - Clear all overrides * - `string[]` - Enable a list of flags (sets them to `true`) * - `Record<string, FeatureFlagValue>` - Set specific flag values/variants * - `FeatureFlagOverrideOptions` - Set both flag values and payloads */ export type OverrideFeatureFlagsOptions = false | string[] | Record<string, FeatureFlagValue> | FeatureFlagOverrideOptions; export type BaseFlagEvaluationOptions = { groups?: Record<string, string>; personProperties?: Record<string, string>; groupProperties?: Record<string, Record<string, string>>; onlyEvaluateLocally?: boolean; disableGeoip?: boolean; }; export type FlagEvaluationOptions = BaseFlagEvaluationOptions & { sendFeatureFlagEvents?: boolean; }; export type AllFlagsOptions = BaseFlagEvaluationOptions & { flagKeys?: string[]; }; export type FeatureFlagOverrideOptions = { /** * Flag overrides. Can be: * - `false` to clear flag overrides * - `string[]` to enable a list of flags * - `Record<string, FeatureFlagValue>` to set specific values/variants */ flags?: false | string[] | Record<string, FeatureFlagValue>; /** * Payload overrides for flags. * - `false` to clear payload overrides * - `Record<string, JsonType>` to set specific payloads */ payloads?: false | Record<string, JsonType>; }; export type FeatureFlagCondition = { properties: FlagProperty[]; rollout_percentage?: number; variant?: string; aggregation_group_type_index?: number | null; }; export type FeatureFlagBucketingIdentifier = 'distinct_id' | 'device_id' | '' | null; export type BeforeSendFn = (event: EventMessage | null) => EventMessage | null; export type PostHogOptions = Omit<PostHogCoreOptions, 'before_send'> & { persistence?: 'memory'; personalApiKey?: string; privacyMode?: boolean; enableExceptionAutocapture?: boolean; featureFlagsPollingInterval?: number; maxCacheSize?: number; fetch?: (url: string, options: PostHogFetchOptions) => Promise<PostHogFetchResponse>; enableLocalEvaluation?: boolean; /** * Optional cache provider for feature flag definitions. * * Allows custom caching strategies (Redis, database, etc.) for flag definitions * in multi-worker environments. If not provided, defaults to in-memory cache. * * This enables distributed coordination where only one worker fetches flags while * others use cached data, reducing API calls and improving performance. * * @example * ```typescript * import type { FlagDefinitionCacheProvider } from 'posthog-node' * * class RedisCacheProvider implements FlagDefinitionCacheProvider { * // ... implementation * } * * const client = new PostHog('api-key', { * personalApiKey: 'personal-key', * flagDefinitionCacheProvider: new RedisCacheProvider(redis) * }) * ``` */ flagDefinitionCacheProvider?: FlagDefinitionCacheProvider; /** * Allows modification or dropping of events before they're sent to PostHog. * If an array is provided, the functions are run in order. * If a function returns null, the event will be dropped. */ before_send?: BeforeSendFn | BeforeSendFn[]; /** * Evaluation contexts for feature flags. * When set, only feature flags that have at least one matching evaluation tag * will be evaluated for this SDK instance. Feature flags with no evaluation tags * will always be evaluated. * * Examples: ['production', 'backend', 'api'] * * @default undefined */ evaluationContexts?: readonly string[]; /** * Evaluation environments for feature flags. * @deprecated Use evaluationContexts instead. This property will be removed in a future version. */ evaluationEnvironments?: readonly string[]; /** * Additional user agent strings to block from being tracked. * These are combined with the default list of blocked user agents. * * @default [] */ custom_blocked_useragents?: string[]; /** * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION * Enables collection of bot traffic as $bot_pageview events instead of dropping them. * When enabled, events with a $raw_user_agent property that matches the bot detection list * will have their $pageview event renamed to $bot_pageview. * * To use this feature, pass the user agent in event properties: * ```ts * client.capture({ * distinctId: 'user_123', * event: '$pageview', * properties: { * $raw_user_agent: req.headers['user-agent'] * } * }) * ``` */ __preview_capture_bot_pageviews?: boolean; /** * When enabled, all feature flag evaluations will use local evaluation only, * never falling back to server-side evaluation. This prevents unexpected server * requests and associated costs when using local evaluation. * * Flags that cannot be evaluated locally (e.g., those with experience continuity) * will return `undefined` instead of making a server request. * * @default false */ strictLocalEvaluation?: boolean; /** * Controls whether `FeatureFlagEvaluations` filter helpers (`onlyAccessed()` and * `only()`) log warnings when their input is unexpected — for example, calling * `onlyAccessed()` before accessing any flags, or passing unknown keys to `only()`. * * @default true */ featureFlagsLogWarnings?: boolean; /** * Provides the API to extend the lifetime of a serverless invocation until * background work (like flushing analytics events) completes after the response * is sent. * * @experimental Subject to change in a minor release. * * @example * // Vercel * import { waitUntil } from '@vercel/functions' * new PostHog('key', { waitUntil }) */ waitUntil?: (promise: Promise<unknown>) => void; /** * Debounce interval in milliseconds for the `waitUntil`-based flush. * After the last event is enqueued, the SDK waits this long before flushing. * * @experimental Subject to change in a minor release. * @default 50 */ waitUntilDebounceMs?: number; /** * Maximum time in milliseconds to debounce before forcing a flush. * Prevents starvation from rapid concurrent captures. * * @experimental Subject to change in a minor release. * @default 500 */ waitUntilMaxWaitMs?: number; /** * Whether to attach the `$is_server: true` property to every captured event. * * @remarks * Defaults to `true` because this SDK is intended for server-side use, where * the property lets PostHog distinguish server events from browser and * react-native events. Set this to `false` when running the SDK as a * client/CLI so the event is attributed to the device OS normally instead of * being marked as a server event. When `false`, the `$is_server` property is * omitted entirely. * * @default true * @example * // CLI usage: don't mark events as server-side * new PostHog('key', { isServer: false }) */ isServer?: boolean; }; export type PostHogFeatureFlag = { id: number; name: string; key: string; bucketing_identifier?: FeatureFlagBucketingIdentifier; filters?: { aggregation_group_type_index?: number; groups?: FeatureFlagCondition[]; multivariate?: { variants: { key: string; rollout_percentage: number; }[]; }; payloads?: Record<string, string>; }; deleted: boolean; active: boolean; rollout_percentage: null | number; ensure_experience_continuity: boolean; experiment_set: number[]; }; /** * Error type constants for the $feature_flag_error property. * * These values are sent in analytics events to track flag evaluation failures. * They should not be changed without considering impact on existing dashboards * and queries that filter on these values. * * Error values: * ERRORS_WHILE_COMPUTING: Server returned errorsWhileComputingFlags=true * FLAG_MISSING: Requested flag not in API response * QUOTA_LIMITED: Rate/quota limit exceeded * UNKNOWN_ERROR: Unexpected exceptions */ export declare const FeatureFlagError: { readonly ERRORS_WHILE_COMPUTING: "errors_while_computing_flags"; readonly FLAG_MISSING: "flag_missing"; readonly QUOTA_LIMITED: "quota_limited"; readonly UNKNOWN_ERROR: "unknown_error"; }; export type FeatureFlagErrorType = (typeof FeatureFlagError)[keyof typeof FeatureFlagError] | string; /** * Result of evaluating a feature flag, including its value and payload. */ export type FeatureFlagResult = { key: string; enabled: boolean; variant: string | undefined; payload: JsonType | undefined; }; export interface IPostHog { /** * @description Capture allows you to capture anything a user does within your system, * which you can later use in PostHog to find patterns in usage, * work out which features to improve or where people are giving up. * A capture call requires: * @param distinctId which uniquely identifies your user * @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on. * @param properties OPTIONAL | which can be a object with any information you'd like to add * @param groups OPTIONAL | object of what groups are related to this event, example: { company: 'id:5' }. Can be used to analyze companies instead of users. * @param flags OPTIONAL | A `FeatureFlagEvaluations` snapshot from `evaluateFlags()`. Attaches those exact flag values to the event with no extra network call. * @param sendFeatureFlags OPTIONAL | Deprecated — prefer `flags`. Fires a hidden `/flags` request on capture to enrich the event with flag values. */ capture({ distinctId, event, properties, groups, flags, sendFeatureFlags }: EventMessage): void; /** * @description Capture an event immediately. Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls. * @param distinctId which uniquely identifies your user * @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on. * @param properties OPTIONAL | which can be a object with any information you'd like to add * @param groups OPTIONAL | object of what groups are related to this event, example: { company: 'id:5' }. Can be used to analyze companies instead of users. * @param flags OPTIONAL | A `FeatureFlagEvaluations` snapshot from `evaluateFlags()`. Attaches those exact flag values to the event with no extra network call. * @param sendFeatureFlags OPTIONAL | Deprecated — prefer `flags`. Fires a hidden `/flags` request on capture to enrich the event with flag values. */ captureImmediate({ distinctId, event, properties, groups, flags, sendFeatureFlags }: EventMessage): Promise<void>; /** * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog, * and even do things like segment users by these properties. * An identify call requires: * @param distinctId which uniquely identifies your user * @param properties with a dict with any key: value pairs */ identify({ distinctId, properties }: IdentifyMessage): void; /** * @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog. * Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls. * @param distinctId which uniquely identifies your user * @param properties with a dict with any key: value pairs */ identifyImmediate({ distinctId, properties }: IdentifyMessage): Promise<void>; /** * @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call. * This will allow you to answer questions like "Which marketing channels leads to users churning after a month?" * or "What do users do on our website before signing up?" * In a purely back-end implementation, this means whenever an anonymous user does something, you'll want to send a session ID with the capture call. * Then, when that users signs up, you want to do an alias call with the session ID and the newly created user ID. * The same concept applies for when a user logs in. If you're using PostHog in the front-end and back-end, * doing the identify call in the frontend will be enough.: * @param distinctId the current unique id * @param alias the unique ID of the user before */ alias(data: { distinctId: string; alias: string; }): void; /** * @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call. * Useful for edge environments where the usual queue-based sending is not preferable. Do not mix immediate and non-immediate calls. * @param distinctId the current unique id * @param alias the unique ID of the user before */ aliasImmediate(data: { distinctId: string; alias: string; }): Promise<void>; /** * @description PostHog feature flags (https://posthog.com/docs/features/feature-flags) * allow you to safely deploy and roll back new features. Once you've created a feature flag in PostHog, * you can use this method to check if the flag is on for a given user, allowing you to create logic to turn * features on and off for different user groups or individual users. * @param key the unique key of your feature flag * @param distinctId the current unique id * @param options: dict with optional parameters below * @param groups optional - what groups are currently active (group analytics). Required if the flag depends on groups. * @param personProperties optional - what person properties are known. Used to compute flags locally, if personalApiKey is present. * @param groupProperties optional - what group properties are known. Used to compute flags locally, if personalApiKey is present. * @param onlyEvaluateLocally optional - whether to only evaluate the flag locally. Defaults to false. * @param sendFeatureFlagEvents optional - whether to send feature flag events. Used for Experiments. Defaults to true. * * @returns true if the flag is on, false if the flag is off, undefined if there was an error. * * @deprecated Use {@link IPostHog.evaluateFlags} and call `flags.isEnabled(key)` on the * returned snapshot. Will be removed in the next major version. */ isFeatureEnabled(key: string, distinctId: string, options?: { groups?: Record<string, string>; personProperties?: Record<string, string>; groupProperties?: Record<string, Record<string, string>>; onlyEvaluateLocally?: boolean; sendFeatureFlagEvents?: boolean; }): Promise<boolean | undefined>; /** * @description PostHog feature flags (https://posthog.com/docs/features/feature-flags) * allow you to safely deploy and roll back new features. Once you've created a feature flag in PostHog, * you can use this method to check if the flag is on for a given user, allowing you to create logic to turn * features on and off for different user groups or individual users. * @param key the unique key of your feature flag * @param distinctId the current unique id * @param options: dict with optional parameters below * @param groups optional - what groups are currently active (group analytics). Required if the flag depends on groups. * @param personProperties optional - what person properties are known. Used to compute flags locally, if personalApiKey is present. * @param groupProperties optional - what group properties are known. Used to compute flags locally, if personalApiKey is present. * @param onlyEvaluateLocally optional - whether to only evaluate the flag locally. Defaults to false. * @param sendFeatureFlagEvents optional - whether to send feature flag events. Used for Experiments. Defaults to true. * * @returns true or string(for multivariates) if the flag is on, false if the flag is off, undefined if there was an error. * * @deprecated Use {@link IPostHog.evaluateFlags} and call `flags.getFlag(key)` on the * returned snapshot. Will be removed in the next major version. */ getFeatureFlag(key: string, distinctId: string, options?: { groups?: Record<string, string>; personProperties?: Record<string, string>; groupProperties?: Record<string, Record<string, string>>; onlyEvaluateLocally?: boolean; sendFeatureFlagEvents?: boolean; }): Promise<FeatureFlagValue | undefined>; /** * @description Retrieves payload associated with the specified flag and matched value that is passed in. * * IMPORTANT: The `matchValue` parameter should be the value you previously obtained from `getFeatureFlag()`. * If matchValue isn't passed (or is undefined), this method will automatically call `getFeatureFlag()` * internally to fetch the flag value, which could result in a network call to the PostHog server if this flag can * not be evaluated locally. This means that omitting `matchValue` will potentially: * - Bypass local evaluation * - Count as an additional flag evaluation against your quota * - Impact performance due to the extra network request * * Example usage: * ```js * const flagValue = await client.getFeatureFlag('my-flag', distinctId); * const payload = await client.getFeatureFlagPayload('my-flag', distinctId, flagValue); * ``` * * @param key the unique key of your feature flag * @param distinctId the current unique id * @param matchValue The flag value previously obtained from calling `getFeatureFlag()`. Can be a string or boolean. * To avoid extra network calls, pass this parameter when you can. * @param options: dict with optional parameters below * @param onlyEvaluateLocally optional - whether to only evaluate the flag locally. Defaults to false. * * @returns payload of a json type object * * @deprecated Use {@link IPostHog.evaluateFlags} and call `flags.getFlagPayload(key)` on * the returned snapshot. Will be removed in the next major version. */ getFeatureFlagPayload(key: string, distinctId: string, matchValue?: FeatureFlagValue, options?: { onlyEvaluateLocally?: boolean; }): Promise<JsonType | undefined>; /** * @description Get all feature flag values using distinctId from withContext(). */ getAllFlags(options?: AllFlagsOptions): Promise<Record<string, FeatureFlagValue>>; /** * @description Get all feature flag values for a specific user. * * @param distinctId - The user's distinct ID * @param options - Optional configuration for flag evaluation * @returns Promise that resolves to a record of flag keys and their values */ getAllFlags(distinctId: string, options?: AllFlagsOptions): Promise<Record<string, FeatureFlagValue>>; /** * @description Get all feature flag values and payloads using distinctId from withContext(). */ getAllFlagsAndPayloads(options?: AllFlagsOptions): Promise<PostHogFlagsAndPayloadsResponse>; /** * @description Get all feature flag values and payloads for a specific user. * * @param distinctId - The user's distinct ID * @param options - Optional configuration for flag evaluation * @returns Promise that resolves to flags and payloads */ getAllFlagsAndPayloads(distinctId: string, options?: AllFlagsOptions): Promise<PostHogFlagsAndPayloadsResponse>; /** * @description Get a feature flag result using distinctId from withContext(). */ getFeatureFlagResult(key: string, options?: FlagEvaluationOptions): Promise<FeatureFlagResult | undefined>; /** * @description Get the result of evaluating a feature flag, including its value and payload. * This is more efficient than calling getFeatureFlag and getFeatureFlagPayload separately when you need both. * * @example * ```ts * const result = await client.getFeatureFlagResult('my-flag', 'user_123') * if (result) { * console.log('Flag enabled:', result.enabled) * console.log('Variant:', result.variant) * console.log('Payload:', result.payload) * } * ``` * * @param key - The feature flag key * @param distinctId - The user's distinct ID * @param options - Optional configuration for flag evaluation * @returns Promise that resolves to the flag result or undefined */ getFeatureFlagResult(key: string, distinctId: string, options?: FlagEvaluationOptions): Promise<FeatureFlagResult | undefined>; /** * @description Evaluate all feature flags for a user in a single call and return a * {@link FeatureFlagEvaluations} snapshot. Branch on `.isEnabled()` / `.getFlag()`, * then pass the same snapshot to `capture()` via the `flags` option so events carry * the exact flag values the code branched on. * * Prefer this over calling `isFeatureEnabled()` / `getFeatureFlag()` repeatedly and * over `capture({ sendFeatureFlags: true })` — it avoids multiple `/flags` requests * per incoming request. * * @example * ```ts * const flags = await posthog.evaluateFlags('user_123', { personProperties: { plan: 'enterprise' } }) * if (flags.isEnabled('new-dashboard')) { * renderNewDashboard() * } * posthog.capture({ distinctId: 'user_123', event: 'page_viewed', flags }) * ``` * * @param options - Optional configuration for flag evaluation. Pass `flagKeys` to scope the underlying `/flags` request to a subset of flags. */ evaluateFlags(options?: AllFlagsOptions): Promise<FeatureFlagEvaluations>; /** * @description Evaluate all feature flags for a specific user. * * @param distinctId - The user's distinct ID * @param options - Optional configuration for flag evaluation. Pass `flagKeys` to scope the underlying `/flags` request to a subset of flags. */ evaluateFlags(distinctId: string, options?: AllFlagsOptions): Promise<FeatureFlagEvaluations>; /** * @description Sets a groups properties, which allows asking questions like "Who are the most active companies" * using my product in PostHog. * * @param groupType Type of group (ex: 'company'). Limited to 5 per project * @param groupKey Unique identifier for that type of group (ex: 'id:5') * @param properties OPTIONAL | which can be a object with any information you'd like to add */ groupIdentify({ groupType, groupKey, properties }: GroupIdentifyMessage): void; /** * @description Force an immediate reload of the polled feature flags. Please note that they are * already polled automatically at a regular interval. */ reloadFeatureFlags(): Promise<void>; /** * @description Override feature flags locally. Useful for testing and local development. * Overridden flags take precedence over both local evaluation and remote evaluation. * * @example * ```ts * // Clear all overrides * posthog.overrideFeatureFlags(false) * * // Enable a list of flags (sets them to true) * posthog.overrideFeatureFlags(['flag-a', 'flag-b']) * * // Set specific flag values/variants * posthog.overrideFeatureFlags({ 'my-flag': 'variant-a', 'other-flag': true }) * * // Set both flags and payloads * posthog.overrideFeatureFlags({ * flags: { 'my-flag': 'variant-a' }, * payloads: { 'my-flag': { discount: 20 } } * }) * ``` * * @param overrides - Flag overrides configuration */ overrideFeatureFlags(overrides: OverrideFeatureFlagsOptions): void; /** * @description Run a function with specific context that will be applied to all events captured within that context. * @param data Context data to apply (sessionId, distinctId, properties, enableExceptionAutocapture) * @param fn Function to run with the context * @param options Context options (fresh) * @returns The return value of the function */ withContext<T>(data: Partial<ContextData>, fn: () => T, options?: ContextOptions): T; /** * @description Set context without a callback wrapper. Must be called in the same * async scope that makes PostHog calls. Prefer `withContext()` when you can wrap * code in a callback. * @param data Context data to apply (distinctId, sessionId, properties) * @param options Context options (fresh) */ enterContext(data: Partial<ContextData>, options?: ContextOptions): void; /** * @description Get the current context data. * @returns The current context data, or undefined if no context is set */ getContext(): ContextData | undefined; /** * @description Flushes the events still in the queue and clears the feature flags poller to allow for * a clean shutdown. * * @param shutdownTimeoutMs The shutdown timeout, in milliseconds. Defaults to 30000 (30s). */ shutdown(shutdownTimeoutMs?: number): void; /** * @description Waits for local evaluation to be ready, with an optional timeout. * @param timeoutMs - Maximum time to wait in milliseconds. Defaults to 30 seconds. * @returns A promise that resolves to true if local evaluation is ready, false if the timeout was reached. */ waitForLocalEvaluationReady(timeoutMs?: number): Promise<boolean>; /** * @description Returns true if local evaluation is ready, false if it's not. * @returns true if local evaluation is ready, false if it's not. */ isLocalEvaluationReady(): boolean; } //# sourceMappingURL=types.d.ts.map