UNPKG

posthog-js

Version:

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

295 lines (294 loc) • 15.4 kB
import type { Client, Extension } from '@posthog/browser-common'; import { FlagsResponse, FeatureFlagsCallback, EarlyAccessFeatureCallback, Properties, JsonType, EarlyAccessFeature, RemoteConfigFeatureFlagCallback, EarlyAccessFeatureStage, FeatureFlagDetail, FeatureFlagResult, FeatureFlagOptions, IsFeatureEnabledOptions, OverrideFeatureFlagsOptions, PostHogConfig } from './types'; import type { PostHog } from './posthog-core'; import { type FeatureFlagsConfigSource } from './feature-flags-config'; import { PERSISTENCE_EARLY_ACCESS_FEATURES, PERSISTENCE_ACTIVE_FEATURE_FLAGS, PERSISTENCE_FEATURE_FLAG_DETAILS, PERSISTENCE_FEATURE_FLAG_ERRORS, PERSISTENCE_FEATURE_FLAG_EVALUATED_AT, PERSISTENCE_FEATURE_FLAG_REQUEST_ID, PERSISTENCE_MINIMAL_FLAG_CALLED_EVENTS, ENABLED_FEATURE_FLAGS, STORED_GROUP_PROPERTIES_KEY, STORED_PERSON_PROPERTIES_KEY, FLAG_CALL_REPORTED, FLAG_CALL_REPORTED_SESSION_ID, PERSISTENCE_FEATURE_FLAG_PAYLOADS, PERSISTENCE_OVERRIDE_FEATURE_FLAGS, PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS } from './constants'; import { type Logger } from '@posthog/core'; type FeatureFlagsState = { [PERSISTENCE_ACTIVE_FEATURE_FLAGS]?: string[]; [ENABLED_FEATURE_FLAGS]?: Record<string, string | boolean>; [PERSISTENCE_FEATURE_FLAG_DETAILS]?: Record<string, FeatureFlagDetail>; [PERSISTENCE_FEATURE_FLAG_PAYLOADS]?: Record<string, JsonType>; [PERSISTENCE_FEATURE_FLAG_REQUEST_ID]?: string; [PERSISTENCE_FEATURE_FLAG_EVALUATED_AT]?: number; [PERSISTENCE_MINIMAL_FLAG_CALLED_EVENTS]?: boolean; [PERSISTENCE_FEATURE_FLAG_ERRORS]?: string[]; [PERSISTENCE_OVERRIDE_FEATURE_FLAGS]?: Record<string, string | boolean>; [PERSISTENCE_OVERRIDE_FEATURE_FLAG_PAYLOADS]?: Record<string, JsonType>; [FLAG_CALL_REPORTED]?: Record<string, string[]>; [FLAG_CALL_REPORTED_SESSION_ID]?: string; [STORED_PERSON_PROPERTIES_KEY]?: Properties; [STORED_GROUP_PROPERTIES_KEY]?: Record<string, Properties>; [PERSISTENCE_EARLY_ACCESS_FEATURES]?: EarlyAccessFeature[]; }; /** * 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. */ export declare const FeatureFlagError: { readonly ERRORS_WHILE_COMPUTING: "errors_while_computing_flags"; readonly FLAG_MISSING: "flag_missing"; readonly QUOTA_LIMITED: "quota_limited"; readonly TIMEOUT: "timeout"; readonly CONNECTION_ERROR: "connection_error"; readonly UNKNOWN_ERROR: "unknown_error"; readonly apiError: (status: number | string) => string; }; export declare const filterActiveFeatureFlags: (featureFlags?: Record<string, string | boolean>) => Record<string, string | boolean>; export declare const parseFlagsResponse: (response: Partial<FlagsResponse>, currentFlags?: Record<string, string | boolean>, currentFlagPayloads?: Record<string, JsonType>, currentFlagDetails?: Record<string, FeatureFlagDetail>, options?: { partialResponse?: boolean; }, responseLogger?: Logger) => FeatureFlagsState | undefined; export declare const QuotaLimitedResource: { readonly FeatureFlags: "feature_flags"; readonly Recordings: "recordings"; }; export type QuotaLimitedResource = (typeof QuotaLimitedResource)[keyof typeof QuotaLimitedResource]; export declare class PostHogFeatureFlags implements Extension { readonly name: import("@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; } export {};