/**
 * PostHog configuration types
 */

import type { JsonType, Properties } from './common'
import type { LogAttributes } from './capture-log'
import type { BeforeSendFn, CaptureResult } from './capture'
import type { RequestResponse } from './request'
import type { CapturedNetworkRequest, NetworkRequest, SessionRecordingCanvasOptions } from './session-recording'
import type { SegmentAnalytics } from './segment'
import type { PostHog } from './posthog'

export type AutocaptureCompatibleElement = 'a' | 'button' | 'form' | 'input' | 'select' | 'textarea' | 'label'
export type DomAutocaptureEvents = 'click' | 'change' | 'submit'

/**
 * If an array is passed for an allowlist, autocapture events will only be sent for elements matching
 * at least one of the elements in the array. Multiple allowlists can be used
 */
export interface AutocaptureConfig {
    /**
     * List of URLs to allow autocapture on, can be strings to match
     * or regexes e.g. ['https://example.com', 'test.com/.*']
     * this is useful when you want to autocapture on specific pages only
     *
     * if you set both url_allowlist and url_ignorelist,
     * we check the allowlist first and then the ignorelist.
     * the ignorelist can override the allowlist
     */
    url_allowlist?: (string | RegExp)[]

    /**
     * List of URLs to not allow autocapture on, can be strings to match
     * or regexes e.g. ['https://example.com', 'test.com/.*']
     * this is useful when you want to autocapture on most pages but not some specific ones
     *
     * if you set both url_allowlist and url_ignorelist,
     * we check the allowlist first and then the ignorelist.
     * the ignorelist can override the allowlist
     */
    url_ignorelist?: (string | RegExp)[]

    /**
     * List of DOM events to allow autocapture on  e.g. ['click', 'change', 'submit']
     */
    dom_event_allowlist?: DomAutocaptureEvents[]

    /**
     * List of DOM elements to allow autocapture on
     * e.g. ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']
     *
     * We consider the tree of elements from the root to the target element of the click event
     * so for the tree `div > div > button > svg`
     * if the allowlist has `button` then we allow the capture when the `button` or the `svg` is the click target
     * but not if either of the `div`s are detected as the click target
     */
    element_allowlist?: AutocaptureCompatibleElement[]

    /**
     * List of CSS selectors to allow autocapture on
     * e.g. ['[ph-capture]']
     * we consider the tree of elements from the root to the target element of the click event
     * so for the tree div > div > button > svg
     * and allow list config `['[id]']`
     * we will capture the click if the click-target or its parents has any id
     *
     * Everything is allowed when there's no allowlist
     */
    css_selector_allowlist?: string[]

    /**
     * Exclude certain element attributes from autocapture
     * E.g. ['aria-label'] or [data-attr-pii]
     */
    element_attribute_ignorelist?: string[]

    /**
     * When set to true, autocapture will capture the text of any element that is cut or copied.
     */
    capture_copied_text?: boolean
}

export interface RageclickConfig {
    /**
     * List of CSS selectors to ignore rageclicks on
     * e.g. ['.my-calendar-button']
     * we consider the tree of elements from the root to the target element of the click event
     * so for the tree div > div > button > svg
     * and ignore list config `['[id]']`
     * we will ignore the rageclick if the click-target or its parents has any id
     *
     * Nothing is ignored when there's an empty ignorelist, e.g. []
     * If no ignorelist is set, we default to ignoring .ph-no-rageclick
     * If an element has .ph-no-capture, it will always be ignored by rageclick and autocapture
     */
    css_selector_ignorelist?: string[]
    /**
     * Controls automatic exclusion of elements by text content from rageclick detection.
     * Useful for pagination buttons, loading spinners, and other repeatedly-clicked UI elements.
     * - `true` (default): Use default keywords ['next', 'previous', 'prev', '>', '<']
     * - `false`: Disable content-based exclusion
     * - `string[]`: Use custom keywords (max 10 items, otherwise use css_selector_ignorelist)
     *
     * Checks if element text content or aria-label contains any of the keywords (case-insensitive)
     * @default true
     */
    content_ignorelist?: boolean | string[]

    /**
     * Maximum pixel distance between clicks to still be considered a rage click.
     * @default 30
     */
    threshold_px?: number

    /**
     * Number of consecutive clicks within the timeout to qualify as a rage click.
     * @default 3
     */
    click_count?: number

    /**
     * Maximum time window (in milliseconds) between the first and last click.
     * @default 1000
     */
    timeout_ms?: number
}

export interface BootstrapConfig {
    distinctID?: string
    isIdentifiedID?: boolean
    featureFlags?: Record<string, boolean | string>
    featureFlagPayloads?: Record<string, JsonType>

    /**
     * Optionally provide a sessionID, this is so that you can provide an existing sessionID here to continue a user's session across a domain or device. It MUST be:
     * - unique to this user
     * - a valid UUID v7
     * - the timestamp part must be <= the timestamp of the first event in the session
     * - the timestamp of the last event in the session must be < the timestamp part + 24 hours
     * **/
    sessionID?: string
}

export type SupportedWebVitalsMetrics = 'LCP' | 'CLS' | 'FCP' | 'INP'

export interface PerformanceCaptureConfig {
    /**
     *  Works with session replay to use the browser's native performance observer to capture performance metrics
     */
    network_timing?: boolean

    /**
     * Use chrome's web vitals library to wrap fetch and capture web vitals
     *
     * When `cookieless_mode` is active, there is no client-side SessionIdManager; vitals are still
     * captured. Nested `$web_vitals_*_event` payloads omit `$session_id` / `$window_id`; PostHog ingestion assigns
     * `$session_id` server-side for cookieless traffic when project cookieless settings are enabled (same as other events).
     */
    web_vitals?: boolean

    /**
     * We observe very large values reported by the Chrome web vitals library
     * These outliers are likely not real, useful values, and we exclude them
     * You can set this to 0 in order to include all values, NB this is not recommended
     *
     * @default 15 * 60 * 1000 (15 minutes)
     */
    __web_vitals_max_value?: number

    /**
     * By default all 4 metrics are captured
     * You can set this config to restrict which metrics are captured
     * e.g. ['CLS', 'FCP'] to only capture those two metrics
     * NB setting this does not override whether the capture is enabled
     *
     * @default ['LCP', 'CLS', 'FCP', 'INP']
     */
    web_vitals_allowed_metrics?: SupportedWebVitalsMetrics[]

    /**
     * We delay flushing web vitals metrics to reduce the number of events we send
     * This is the maximum time we will wait before sending the metrics
     *
     * @default 5000
     */
    web_vitals_delayed_flush_ms?: number

    /**
     * Whether to include attribution data in web vitals metrics.
     * Attribution data includes additional debugging information like
     * which elements caused layout shifts (CLS), timing breakdowns, etc.
     *
     * Disabling this uses a lighter build of the web-vitals library
     * which may help reduce memory usage in SPAs where elements
     * causing layout shifts are removed during navigation.
     *
     * @default false
     */
    web_vitals_attribution?: boolean
}

export interface DeadClickCandidate {
    node: Element
    originalEvent: MouseEvent
    timestamp: number
    // time between click and the most recent scroll
    scrollDelayMs?: number
    // time between click and the most recent mutation
    mutationDelayMs?: number
    // time between click and the most recent selection changed event
    selectionChangedDelayMs?: number
    // time between click and the most recent visibility change event
    visibilityChangedDelayMs?: number
    // if neither scroll nor mutation seen before threshold passed
    absoluteDelayMs?: number
}

/**
 * Controls buffering and payload limits for exception steps added via `addExceptionStep`.
 *
 * NOTE: This type is also defined in `@posthog/core` (exception-steps.ts). Keep both in sync.
 */
export type ExceptionStepsConfig = {
    /**
     * Determines whether PostHog should collect exception steps and attach them to the next captured exception.
     *
     * @default true
     */
    enabled?: boolean

    /**
     * The maximum UTF-8 byte budget for exception steps buffered in memory.
     * Oldest steps are evicted when the budget is exceeded.
     *
     * @default 32768 (~32KB)
     */
    max_bytes?: number
}

export type ExceptionAutoCaptureConfig = {
    /**
     * Determines whether PostHog should capture unhandled errors.
     *
     * @default true
     */
    capture_unhandled_errors?: boolean

    /**
     * Determines whether PostHog should capture unhandled promise rejections.
     *
     * @default true
     */
    capture_unhandled_rejections?: boolean

    /**
     * Determines whether PostHog should capture console errors.
     *
     * @default false
     */
    capture_console_errors?: boolean
}

export type DeadClicksAutoCaptureConfig = {
    /**
     * We'll not consider a click to be a dead click, if it's followed by a scroll within `scroll_threshold_ms` milliseconds
     *
     * @default 100
     */
    scroll_threshold_ms?: number

    /**
     * We'll not consider a click to be a dead click, if it's followed by a selection change within `selection_change_threshold_ms` milliseconds
     *
     * @default 100
     */
    selection_change_threshold_ms?: number

    /**
     * We'll not consider a click to be a dead click, if it's followed by a mutation within `mutation_threshold_ms` milliseconds
     *
     * @default 2500
     */
    mutation_threshold_ms?: number

    /**
     * By default, clicks with modifier keys (ctrl, shift, alt, meta/cmd) held down are not considered dead clicks,
     * since these typically indicate intentional actions like "open in new tab".
     *
     * Set this to true to capture dead clicks even when modifier keys are held.
     *
     * @default false
     */
    capture_clicks_with_modifier_keys?: boolean

    /**
     * List of CSS selectors to ignore dead clicks on
     * e.g. ['.my-download-link']
     * we consider the tree of elements from the root to the target element of the click event
     * so for the tree div > div > a > svg
     * and ignore list config `['[download]']`
     * we will ignore the dead click if the click-target or its parents has any download attribute
     *
     * Nothing is ignored when there's an empty ignorelist, e.g. []
     * If no ignorelist is set, we default to ignoring .ph-no-deadclick and .ph-no-capture
     * A custom ignorelist fully replaces the default — include .ph-no-capture if you want it to suppress dead-click capture as well
     */
    css_selector_ignorelist?: string[]

    /**
     * Allows setting behavior for when a dead click is captured.
     * For e.g. to support capture to heatmaps
     *
     * If not provided the default behavior is to auto-capture dead click events
     *
     * Only intended to be provided by our own SDK
     */
    __onCapture?: ((click: DeadClickCandidate, properties: Properties) => void) | undefined
} & Pick<AutocaptureConfig, 'element_attribute_ignorelist'>

export interface HeatmapConfig {
    /**
     * How often to send batched data in `$heatmap_data` events
     * If set to 0 or not set, sends using the default interval of 1 second
     *
     * @default 1000
     */
    flush_interval_milliseconds: number
}

export type ConfigDefaults = '2026-01-30' | '2025-11-30' | '2025-05-24' | 'unset'

export type ExternalIntegrationKind = 'intercom' | 'crispChat'

export interface ErrorTrackingOptions {
    /**
     * Decide whether exceptions thrown by browser extensions should be captured
     *
     * @default false
     */
    captureExtensionExceptions?: boolean

    /**
     * UNSTABLE: determines whether exception caused by the PostHog SDK will be captured
     *
     * @default false
     */
    __capturePostHogExceptions?: boolean

    /**
     * ADVANCED: alters the refill rate for the token bucket mutation throttling
     * Normally only altered alongside posthog support guidance.
     * Accepts values between 0 and 100
     *
     * @default 1
     */
    __exceptionRateLimiterRefillRate?: number

    /**
     * ADVANCED: alters the bucket size for the token bucket mutation throttling
     * Normally only altered alongside posthog support guidance.
     * Accepts values between 0 and 100
     *
     * @default 10
     */
    __exceptionRateLimiterBucketSize?: number

    /**
     * Controls buffering and payload limits for exception steps added via `addExceptionStep`.
     */
    exception_steps?: ExceptionStepsConfig
}

/**
 * Mask input options for session recording
 */
export interface MaskInputOptions {
    color?: boolean
    date?: boolean
    'datetime-local'?: boolean
    email?: boolean
    month?: boolean
    number?: boolean
    range?: boolean
    search?: boolean
    tel?: boolean
    text?: boolean
    time?: boolean
    url?: boolean
    week?: boolean
    textarea?: boolean
    select?: boolean
    password?: boolean
}

/**
 * Slim DOM options for session recording
 */
export interface SlimDOMOptions {
    script?: boolean
    comment?: boolean
    headFavicon?: boolean
    headWhitespace?: boolean
    headMetaDescKeywords?: boolean
    headMetaSocial?: boolean
    headMetaRobots?: boolean
    headMetaHttpEquiv?: boolean
    headMetaAuthorship?: boolean
    headMetaVerification?: boolean
    headTitleMutations?: boolean
}

export interface SessionRecordingOptions {
    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default 'ph-no-capture'
     */
    blockClass?: string | RegExp

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default null
     */
    blockSelector?: string | null

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default 'ph-ignore-input'
     */
    ignoreClass?: string | RegExp

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default 'ph-mask'
     */
    maskTextClass?: string | RegExp

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     */
    maskTextSelector?: string | null

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     */
    maskTextFn?: ((text: string, element?: HTMLElement) => string) | null

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     */
    maskAllInputs?: boolean

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     */
    maskInputOptions?: Partial<MaskInputOptions>

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     */
    maskInputFn?: ((text: string, element?: HTMLElement) => string) | null

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default {}
     */
    slimDOMOptions?: true | Partial<SlimDOMOptions> | 'all'

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default false
     */
    collectFonts?: boolean

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default true
     */
    inlineStylesheet?: boolean

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default false
     */
    recordCrossOriginIframes?: boolean

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default false
     */
    recordHeaders?: boolean

    /**
     * Derived from `rrweb.record` options
     * @see https://github.com/rrweb-io/rrweb/blob/master/guide.md
     * @default false
     */
    recordBody?: boolean

    /**
     * Allows local config to override remote canvas recording settings from the flags response
     */
    captureCanvas?: SessionRecordingCanvasOptions

    /**
     * Modify the network request before it is captured. Returning null or undefined stops it being captured
     */
    maskCapturedNetworkRequestFn?: ((data: CapturedNetworkRequest) => CapturedNetworkRequest | null | undefined) | null

    /** @deprecated - use maskCapturedNetworkRequestFn instead  */
    maskNetworkRequestFn?: ((data: NetworkRequest) => NetworkRequest | null | undefined) | null

    /**
     * ADVANCED: while a user is active we take a full snapshot of the browser every interval.
     * For very few sites playback performance might be better with different interval.
     * Set to 0 to disable
     *
     * @default 1000 * 60 * 5 (5 minutes)
     */
    full_snapshot_interval_millis?: number

    /**
     * ADVANCED: whether to partially compress rrweb events before sending them to the server,
     * defaults to true, can be set to false to disable partial compression
     * NB requests are still compressed when sent to the server regardless of this setting
     *
     * @default true
     */
    compress_events?: boolean

    /**
     * ADVANCED: Controls when session recording considers the user idle.
     *
     * If no replay user interaction occurs for this many milliseconds, the recorder marks the recording idle,
     * emits a `sessionIdle` replay marker, flushes buffered replay events, and drops most subsequent replay
     * events until user activity resumes. If activity resumes before `session_idle_timeout_seconds`, recording
     * continues under the same `$session_id`.
     *
     * This does not control `$session_id` rotation. Session rotation is controlled by `session_idle_timeout_seconds`,
     * so this value should be lower than `session_idle_timeout_seconds * 1000`.
     *
     * @default 1000 * 60 * 5 (5 minutes)
     */
    session_idle_threshold_ms?: number

    /**
     * ADVANCED: alters the refill rate for the token bucket mutation throttling
     * Normally only altered alongside posthog support guidance.
     * Accepts values between 0 and 100
     *
     * @default 10
     */
    __mutationThrottlerRefillRate?: number

    /**
     * ADVANCED: alters the bucket size for the token bucket mutation throttling
     * Normally only altered alongside posthog support guidance.
     * Accepts values between 0 and 100
     *
     * @default 100
     */
    __mutationThrottlerBucketSize?: number

    /**
     * When true, minimum duration is checked against the actual buffer data (first to last timestamp)
     * rather than session duration. This ensures recordings are not sent until they contain the minimum
     * duration of actual data, even across page navigations.
     *
     * @default false
     */
    strictMinimumDuration?: boolean

    /**
     * The sample rate for session recordings, a number between 0 and 1.
     * For example, 0.5 means roughly 50% of sessions will be recorded.
     *
     * When `undefined`, falls back to the remote config setting.
     * When set, takes precedence over the remote config.
     *
     * @default undefined
     */
    sampleRate?: number
}

// we used to call a request that was sent to the queue with options attached `RequestQueueOptions`
// so we can't call the options used to configure the behavior of the RequestQueue that as well,
// so instead we call them config
export interface RequestQueueConfig {
    /**
     *  ADVANCED - alters the frequency which PostHog sends events to the server.
     *  generally speaking this is only set when apps have automatic page refreshes, or very short visits.
     *  Defaults to 3 seconds when not set
     *  Allowed values between 250 and 5000
     * */
    flush_interval_ms?: number
}

/**
 * Survey configuration options
 */
export interface SurveyConfig {
    prefillFromUrl?: boolean
    autoSubmitIfComplete?: boolean
    autoSubmitDelay?: number
}

/**
 * Options for the captureLog API and posthog.logger convenience methods.
 */
export interface LogCaptureOptions {
    /**
     * The service name for log records.
     * Maps to the OTel resource attribute 'service.name'.
     *
     * @default 'unknown_service'
     */
    serviceName?: string
    /**
     * The deployment environment for log records (e.g. 'production', 'staging').
     * Maps to the OTel resource attribute 'deployment.environment'.
     */
    environment?: string
    /**
     * The service version for log records (e.g. '1.2.3').
     * Maps to the OTel resource attribute 'service.version'.
     */
    serviceVersion?: string
    /**
     * Additional resource attributes applied to all log records.
     * These describe the service/deployment, not individual log entries.
     * Named fields (serviceName, environment, serviceVersion) are set first;
     * resourceAttributes can override them.
     *
     * @example { 'host.name': 'web-01', 'cloud.region': 'us-east-1' }
     */
    resourceAttributes?: LogAttributes
    /**
     * Flush interval in milliseconds for batched log records.
     *
     * @default 3000
     */
    flushIntervalMs?: number
    /**
     * Maximum number of log records to buffer before forcing a flush.
     *
     * @default 100
     */
    maxBufferSize?: number
    /**
     * Maximum number of log records accepted per flush interval. Subsequent calls
     * within the same window are dropped with a single warning, protecting
     * against runaway loggers flooding the network.
     *
     * @default 1000
     */
    maxLogsPerInterval?: number
}

/**
 * Logs configuration options
 */
export interface LogsConfig extends LogCaptureOptions {
    captureConsoleLogs?: boolean
}

// See https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options
type NextOptions = { revalidate: false | 0 | number; tags: string[] }

/**
 * Configuration options for the PostHog JavaScript SDK.
 * @see https://posthog.com/docs/libraries/js#config
 */
export interface PostHogConfig {
    /** URL of your PostHog instance.
     *
     * @default 'https://us.i.posthog.com'
     */
    api_host: string

    /**
     * URL to use for feature flag requests specifically.
     * If not set, feature flag requests will use the URL derived from `api_host`.
     * This is useful when you want to route feature flag requests to a different endpoint than other analytic APIs.
     *
     * @default null
     */
    flags_api_host?: string | null

    /**
     * If using a reverse proxy for `api_host` then this should be the actual PostHog app URL (e.g. https://us.posthog.com).
     * This ensures that links to PostHog point to the correct host.
     *
     * @default null
     */
    ui_host: string | null

    /**
     * The transport method to use for API requests.
     *
     * @default 'fetch'
     */
    api_transport?: 'XHR' | 'fetch'

    /**
     * The token for your PostHog project.
     * It should NOT be provided manually in the config, but rather passed as the first parameter to `posthog.init()`.
     */
    token: string

    /**
     * The name this instance will be identified by.
     * You don't need to set this most of the time,
     * but can be useful if you have several Posthog instances running at the same time.
     *
     * @default 'posthog'
     */
    name: string

    /**
     * Determines whether PostHog should autocapture events.
     * This setting does not affect capturing pageview events (see `capture_pageview`).
     *
     * by default autocapture is ignored on elements that match a `ph-no-capture` css class on the element or a parent
     * @default true
     */
    autocapture: boolean | AutocaptureConfig

    /**
     * Determines whether PostHog should capture rage clicks.
     *
     * by default rageclicks are ignored on elements that match a `ph-no-capture` or `ph-no-rageclick` css class on the element or a parent
     * @default true
     */
    rageclick: boolean | RageclickConfig

    /**
     * Determines if cookie should be set on the top level domain (example.com).
     * If PostHog-js is loaded on a subdomain (test.example.com), and `cross_subdomain_cookie` is set to false,
     * it'll set the cookie on the subdomain only (test.example.com).
     *
     * NOTE: It will be set to `false` if we detect that the domain is a subdomain of a platform that is excluded from cross-subdomain cookie setting.
     * The current list of excluded platforms is `herokuapp.com`, `vercel.app`, and `netlify.app`.
     *
     * @see `isCrossDomainCookie`
     * @default true
     */
    cross_subdomain_cookie: boolean

    /**
     * Determines how PostHog stores information about the user. See [persistence](https://posthog.com/docs/libraries/js#persistence) for details.
     *
     * @default 'localStorage+cookie'
     */
    persistence: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie' | 'sessionStorage'

    /**
     * The name for the super properties persistent store
     *
     * @default ''
     */
    persistence_name: string

    /** @deprecated - Use 'persistence_name' instead */
    cookie_name?: string

    /**
     * List of custom property names that should be stored in cookies (in addition to the default ones)
     * when using 'localStorage+cookie' persistence mode. This allows these properties to be shared
     * across subdomains when cross_subdomain_cookie is enabled.
     *
     * @default []
     */
    cookie_persisted_properties?: readonly string[]

    /**
     * A function to be called once the PostHog scripts have loaded successfully.
     *
     * @param posthog_instance - The PostHog instance that has been loaded.
     */
    loaded: (posthog_instance: PostHog) => void

    /**
     * Determines whether PostHog should save referrer information.
     *
     * @default true
     */
    save_referrer: boolean

    /**
     * Determines whether PostHog should save marketing parameters.
     * These are `utm_*` paramaters and friends.
     *
     * @see {CAMPAIGN_PARAMS} from './utils/event-utils' - Default campaign parameters like utm_source, utm_medium, etc.
     * @default true
     */
    save_campaign_params: boolean

    /** @deprecated - Use `save_campaign_params` instead */
    store_google?: boolean

    /**
     * Used to extend the list of campaign parameters that are saved by default.
     *
     * @see {CAMPAIGN_PARAMS} from './utils/event-utils' - Default campaign parameters like utm_source, utm_medium, etc.
     * @default []
     */
    custom_campaign_params: string[]

    /**
     * Used to extend the list of user agents that are blocked by default.
     *
     * @see {DEFAULT_BLOCKED_UA_STRS} from './utils/blocked-uas' - Default list of blocked user agents.
     * @default []
     */
    custom_blocked_useragents: string[]

    /**
     * Determines whether PostHog should be in debug mode.
     * You can enable this to get more detailed logging.
     *
     * You can also enable this on your website by appending `?__posthog_debug=true` at the end of your URL
     * You can also call `posthog.debug()` in your code to enable debug mode
     *
     * @default false
     */
    debug: boolean

    /** @deprecated Use `debug` instead */
    verbose?: boolean

    /**
     * Determines whether PostHog should capture pageview events automatically.
     * Can be:
     * - `true`: Capture regular pageviews (default)
     * - `false`: Don't capture any pageviews
     * - `'history_change'`: Only capture pageviews on history API changes (pushState, replaceState, popstate)
     *
     * @default true
     */
    capture_pageview: boolean | 'history_change'

    /**
     * Determines whether PostHog should capture pageleave events.
     * If set to `true`, it will capture pageleave events for all pages.
     * If set to `'if_capture_pageview'`, it will only capture pageleave events if `capture_pageview` is also set to `true` or `'history_change'`.
     *
     * @default 'if_capture_pageview'
     */
    capture_pageleave: boolean | 'if_capture_pageview'

    /**
     * Determines the number of days to store cookies for.
     *
     * @default 365
     */
    cookie_expiration: number

    /**
     * Determines whether PostHog should upgrade old cookies.
     * If set to `true`, the library will check for a cookie from our old js library and import super properties from it, then the old cookie is deleted.
     * This option only works in the initialization, so make sure you set it when you create the library.
     *
     * @default false
     */
    upgrade: boolean

    /**
     * Determines whether PostHog should disable session recording.
     *
     * @default false
     */
    disable_session_recording: boolean

    /**
     * Determines whether PostHog should disable persistence.
     * If set to `true`, the library will not save any data to the browser. It will also delete any data previously saved to the browser.
     *
     * @default false
     */
    disable_persistence: boolean

    /** @deprecated - use `disable_persistence` instead */
    disable_cookie?: boolean

    /**
     * Determines whether PostHog should disable all surveys functionality.
     *
     * @default false
     */
    disable_surveys: boolean

    /**
     * Determines whether PostHog should disable automatic display of surveys. If this is true, popup or widget surveys will not be shown when display conditions are met.
     *
     * @default false
     */
    disable_surveys_automatic_display: boolean

    /**
     * Determines whether PostHog should disable all product tours functionality.
     *
     * @default true (disabled until feature is ready for GA)
     */
    disable_product_tours: boolean

    /**
     * Survey-specific configuration options.
     *
     * @default undefined
     */
    surveys?: SurveyConfig

    /**
     * Logs-specific configuration options.
     *
     * @default undefined
     */
    logs?: LogsConfig

    /**
     * Determines whether PostHog should disable all conversations functionality.
     *
     * @default false
     */
    disable_conversations: boolean

    /**
     * Verified distinct_id for HMAC-based identity verification.
     * When both `identity_distinct_id` and `identity_hash` are provided,
     * products like conversations use server-verified identity instead of
     * anonymous session identifiers.
     *
     * Can be set at init time or later via `posthog.setIdentity()`.
     *
     * @example
     * ```js
     * posthog.init('phc_...', {
     *     identity_distinct_id: 'user_123',
     *     identity_hash: 'a1b2c3d4e5f6...',
     * })
     * ```
     */
    identity_distinct_id?: string

    /**
     * HMAC-SHA256 of `identity_distinct_id` using the project's API secret.
     * Must be provided together with `identity_distinct_id`.
     */
    identity_hash?: string

    /**
     * Determines whether PostHog should disable web experiments.
     *
     * Currently disabled while we're in BETA. It will be toggled to `true` in a future release.
     *
     * @default true
     */
    disable_web_experiments: boolean

    /**
     * Determines whether PostHog should disable any external dependency loading.
     * This will prevent PostHog from requesting any external scripts such as those needed for Session Replay, Surveys or Site Apps.
     *
     * @default false
     */
    disable_external_dependency_loading: boolean

    /**
     * A function to be called when a script is being loaded.
     * This can be used to modify the script before it is loaded.
     * This is useful for adding a nonce to the script, for example.
     *
     * @param script - The script element that is being loaded.
     * @returns The modified script element, or null if the script should not be loaded.
     */
    prepare_external_dependency_script?: (script: HTMLScriptElement) => HTMLScriptElement | null

    /**
     * A function to be called when a stylesheet is being loaded.
     * This can be used to modify the stylesheet before it is loaded.
     * This is useful for adding a nonce to the stylesheet, for example.
     *
     * @param stylesheet - The stylesheet element that is being loaded.
     * @returns The modified stylesheet element, or null if the stylesheet should not be loaded.
     */
    prepare_external_dependency_stylesheet?: (stylesheet: HTMLStyleElement) => HTMLStyleElement | null

    /**
     * Where to inject external dependency scripts (recorder, surveys, etc.) in the DOM.
     * - 'body': Injects scripts into document.body (legacy behavior)
     * - 'head': Injects scripts into document.head (avoids SSR hydration errors)
     *
     * @default 'body' (or 'head' when defaults >= '2026-01-30')
     */
    external_scripts_inject_target?: 'body' | 'head'

    /**
     * Determines whether PostHog should enable recording console logs.
     *
     * This is related to the Session Recording feature. For more session recording
     * settings, see the `session_recording` and `capture_performance` configuration option.
     * When undefined, it falls back to the remote config setting.
     *
     * @default undefined
     */
    enable_recording_console_log?: boolean

    /**
     * Determines whether PostHog should use secure cookies.
     * If this is `true`, PostHog cookies will be marked as secure,
     * meaning they will only be transmitted over HTTPS.
     *
     * @default window.location.protocol === 'https:'
     */
    secure_cookie: boolean

    /**
     * Determines if users should be opted out of PostHog tracking by default,
     * requiring additional logic to opt them into capturing by calling `posthog.opt_in_capturing()`.
     *
     * @default false
     */
    opt_out_capturing_by_default: boolean

    /**
     * Determines where we'll save the information about whether users are opted out of capturing.
     *
     * @default 'localStorage'
     */
    opt_out_capturing_persistence_type: 'localStorage' | 'cookie'

    /**
     * Determines if users should be opted out of browser data storage by this PostHog instance by default,
     * requiring additional logic to opt them into capturing by calling `posthog.opt_in_capturing()`.
     *
     * @default false
     */
    opt_out_persistence_by_default?: boolean

    /**
     * Determines if users should be opted out of user agent filtering such as googlebot or other bots.
     * If this is set to `true`, PostHog will set `$browser_type` to either `bot` or `browser` for all events,
     * but will process all events as if they were from a browser.
     *
     * @default false
     */
    opt_out_useragent_filter: boolean

    /** @deprecated Use `consent_persistence_name` instead. This will be removed in a future major version. **/
    opt_out_capturing_cookie_prefix: string | null

    /**
     * Determines the key for the cookie / local storage used to store the information about whether users are opted in/out of capturing.
     * When `null`, we used a key based on your token.
     *
     * @default null
     * @see `ConsentManager._storageKey`
     */
    consent_persistence_name: string | null

    /**
     * Determines if users should be opted in to site apps.
     *
     * @default false
     */
    opt_in_site_apps: boolean

    /**
     * Determines whether PostHog should respect the Do Not Track header when computing
     * consent in `ConsentManager`.
     *
     * @see `ConsentManager`
     * @default false
     */
    respect_dnt: boolean

    /**
     * A list of properties that should never be sent with capture calls.
     *
     * @default []
     */
    property_denylist: string[]

    /** @deprecated - use `property_denylist` instead  */
    property_blacklist?: string[]

    /**
     * A list of headers that should be sent with requests to the PostHog API.
     *
     * @default {}
     */
    request_headers: { [header_name: string]: string }

    /** @deprecated - use `request_headers` instead  */
    xhr_headers?: { [header_name: string]: string }

    /**
     * A function that is called when a request to the PostHog API fails.
     *
     * @param error - The `RequestResponse` object that occurred.
     */
    on_request_error?: (error: RequestResponse) => void

    /** @deprecated - use `on_request_error` instead  */
    on_xhr_error?: (failedRequest: XMLHttpRequest) => void

    /**
     * Determines whether PostHog should batch requests to the PostHog API.
     *
     * @default true
     */
    request_batching: boolean

    /**
     * Determines the maximum length of the properties string that can be sent with capture calls.
     *
     * @default 65535
     */
    properties_string_max_length: number

    /**
     * Configuration defaults for breaking changes. When set to a specific date,
     * enables new default behaviors that were introduced on that date.
     *
     * - `'unset'`: Use legacy default behaviors
     * - `'2025-05-24'`: Use updated default behaviors (e.g. capture_pageview defaults to 'history_change')
     * - `'2025-11-30'`: Defaults from '2025-05-24' plus additional changes (e.g. strict minimum duration for replay and rageclick content ignore list defaults to active)
     * - `'2026-01-30'`: Defaults from '2025-11-30' plus external_scripts_inject_target defaults to 'head' (avoids SSR hydration errors)
     *
     * @default 'unset'
     */
    defaults: ConfigDefaults

    /**
     * EXPERIMENTAL: Defers initialization of non-critical extensions (autocapture, session recording, etc.)
     * to the next event loop tick using setTimeout. This reduces main thread blocking during SDK
     * initialization for better page load performance, while keeping critical functionality
     * (persistence, sessions, capture) available immediately.
     *
     * When enabled:
     * - Persistence, sessions, and basic capture work immediately
     * - Extensions (autocapture, recording, heatmaps, etc.) start after yielding back to the browser
     *
     * @default false (will be true for defaults >= '2025-11-06' in the future)
     * @experimental
     */
    __preview_deferred_init_extensions: boolean

    /**
     * Determines the session recording options.
     *
     * For more session recording settings, see the `enable_recording_console_log` and `capture_performance` configuration option.
     *
     * @see `SessionRecordingOptions`
     * @default {}
     */
    session_recording: SessionRecordingOptions

    /**
     * Determines the error tracking options.
     *
     * @see `ErrorTrackingOptions`
     * @default {}
     */
    error_tracking: ErrorTrackingOptions

    /**
     * Determines the session idle timeout in seconds.
     *
     * If no events are captured for this many seconds, the next event starts a
     * new session with a new `$session_id` (and `$window_id`). The SDK may also proactively reset the stored session
     * after the timeout while the page is idle, so the next event creates a new session.
     *
     * Session recording has a separate idle threshold: `session_recording.session_idle_threshold_ms`. That setting
     * only controls when the user is considered idle, it does not rotate `$session_id`.
     *
     * Must be between 60 seconds and 10 hours. Values outside this range are clamped.
     *
     * @default 30 * 60 -- 30 minutes
     */
    session_idle_timeout_seconds: number

    /**
     * Prevent autocapture from capturing any attribute names on elements.
     *
     * @default false
     */
    mask_all_element_attributes: boolean

    /**
     * Prevent autocapture from capturing `textContent` on elements.
     *
     * @default false
     */
    mask_all_text: boolean

    /**
     * Mask personal data properties from the current URL.
     * This will mask personal data properties such as advertising IDs (gclid, fbclid, etc.), and you can also add
     * custom properties to mask with `custom_personal_data_properties`.
     * @default false
     * @see {PERSONAL_DATA_CAMPAIGN_PARAMS} - Default campaign parameters that are masked by default.
     * @see {PostHogConfig.custom_personal_data_properties} - Custom list of personal data properties to mask.
     */
    mask_personal_data_properties: boolean

    /**
     * Custom list of personal data properties to mask.
     *
     * E.g. if you added `email` to this list, then any `email` property in the URL will be masked.
     * https://www.example.com/login?email=john.doe%40example.com => https://www.example.com/login?email=<MASKED>
     *
     * @default []
     * @see {PostHogConfig.mask_personal_data_properties} - Must be enabled for this to take effect.
     */
    custom_personal_data_properties: string[]

    /**
     * One of the very first things the PostHog library does when init() is called
     * is make a request to the /flags endpoint on PostHog's backend.
     * This endpoint contains information on how to run the PostHog library
     * so events are properly received in the backend, and it also contains
     * feature flag evaluation information for the current user.
     *
     * This endpoint is required to run most features of this library.
     * However, if you're not using any of the described features,
     * you may wish to turn off the call completely to avoid an extra request
     * and reduce resource usage on both the client and the server.
     *
     * WARNING: Disabling this will also prevent remote configuration from loading,
     * which could mean features like web vitals, surveys, and other features configured
     * in PostHog settings are disabled unless explicitly enabled via client-side config.
     * When setting this to true, make sure to explicitly configure any features you
     * want to use (e.g., capture_performance, autocapture, etc.) in your SDK's init config.
     *
     * @default false
     */
    advanced_disable_flags?: boolean

    /**
     * @deprecated Use `advanced_disable_flags` instead. This will be removed in a future major version.
     *
     * One of the very first things the PostHog library does when init() is called
     * is make a request to the /decide endpoint on PostHog's backend.
     * This endpoint contains information on how to run the PostHog library
     * so events are properly received in the backend.
     *
     * This endpoint is required to run most features of the library.
     * However, if you're not using any of the described features,
     * you may wish to turn off the call completely to avoid an extra request
     * and reduce resource usage on both the client and the server.
     *
     * @default false
     */
    advanced_disable_decide?: boolean

    /**
     * Will keep /flags running, but without evaluating any feature flags.
     * Useful for when you need to load the config data associated with the flags endpoint
     * (e.g. /flags?v=2&config=true) without evaluating any feature flags.  Most folks use this
     * to save money on feature flag evaluation (by bootstrapping feature flags on the server side).
     *
     * @default false
     */
    advanced_disable_feature_flags: boolean

    /**
     * Stops from firing feature flag requests on first page load.
     * Only requests feature flags when user identity or properties are updated,
     * or you manually request for flags to be loaded.
     *
     * @default false
     */
    advanced_disable_feature_flags_on_first_load: boolean

    /**
     * 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', 'web', 'checkout']
     *
     * @default undefined
     */
    evaluation_contexts?: readonly string[]

    /**
     * List of feature flag keys to remotely evaluate for this SDK instance.
     * When set, only these flags are evaluated by `/flags`; omitted flags are not remotely evaluated.
     * Dependencies of the requested flags may still be evaluated internally by PostHog.
     * If unset, all eligible flags are evaluated.
     *
     * Examples: ['checkout-redesign', 'new-onboarding']
     *
     * @default undefined
     */
    flag_keys?: readonly string[]

    /**
     * Evaluation environments for feature flags.
     * @deprecated Use evaluation_contexts instead. This property will be removed in a future version.
     */
    evaluation_environments?: readonly string[]

    /**
     * Determines whether PostHog should disable toolbar metrics.
     * This is our internal instrumentation for our toolbar in your website.
     *
     * @default false
     */
    advanced_disable_toolbar_metrics: boolean

    /**
     * Determines whether PostHog should only evaluate feature flags for surveys.
     * Useful for when you want to use this library to evaluate feature flags for surveys only but you have additional feature flags
     * that you evaluate on the server side.
     *
     * @default false
     */
    advanced_only_evaluate_survey_feature_flags: boolean
    /**
     * When this is enabled, surveys will always be initialized, regardless of the /flags response or remote config settings.
     * This is useful if you want to use surveys but disable all other flag-dependent functionality.
     * Used internally for displaying external surveys without making a /flags request.
     *
     * @default false
     */
    advanced_enable_surveys: boolean

    /**
     * Sets timeout for fetching feature flags
     *
     * @default 3000
     */
    feature_flag_request_timeout_ms: number

    /**
     * Sets the maximum age (in milliseconds) for cached feature flag values.
     * When the cache is older than this value:
     * - `getFeatureFlag()` will return `undefined` instead of stale cached values
     * - `$feature/` properties will not be attached to events
     * - A background refresh will be triggered automatically
     *
     * This prevents stale feature flag values from being used when the `/flags` request
     * fails (e.g., due to ad blockers or network issues).
     *
     * When not set or set to `0`, cache expiration is disabled (cached values never expire).
     */
    feature_flag_cache_ttl_ms?: number

    /**
     * When enabled, `$feature_flag_called` event deduplication is scoped to the current session.
     *
     * By default, the SDK deduplicates `$feature_flag_called` events globally and only re-emits
     * them when `identify` (with a new distinct ID) or `reset` is called. This can be problematic
     * for experiments: if a flag is checked before an experiment starts, the event is cached and
     * won't fire again for that user until identify/reset, meaning the experiment never sees the event.
     *
     * When this option is `true`, the deduplication cache is keyed on the session ID, so each new
     * session will re-emit `$feature_flag_called` for every flag that is checked.
     *
     * @default false
     */
    advanced_feature_flags_dedup_per_session: boolean

    /**
     * Sets timeout for fetching surveys
     *
     * @default 10000
     */
    surveys_request_timeout_ms: number

    /**
     * Controls how often feature flags are automatically refreshed in long-running sessions.
     *
     * By default, feature flags are refreshed every 5 minutes (300000ms) to pick up server-side
     * flag changes without requiring a page reload. This is useful for SPAs and long-running tabs.
     *
     * **Tradeoffs:**
     * - **Shorter intervals**: Feature flag changes propagate faster, but increases network requests and server load.
     * - **Longer intervals**: Reduces network traffic (better for mobile/battery), but flag changes take longer to propagate.
     * - **Disabled (0)**: No background refreshes. Flags only update on page load or manual `reloadFeatureFlags()` calls.
     *   Use this if you control flag updates manually or have infrequent flag changes.
     *
     * Note: Refreshes are automatically skipped when the browser tab is hidden or no document is available.
     *
     * @default 300000 (5 minutes)
     */
    remote_config_refresh_interval_ms?: number

    /**
     * Function to get the device ID.
     * This doesn't usually need to be set, but can be useful if you want to use a custom device ID.
     *
     * @param uuid - The UUID we would use for the device ID.
     * @returns The device ID.
     *
     * @default (uuid) => uuid
     */
    get_device_id: (uuid: string) => string

    /**
     * This function or array of functions - if provided - are called immediately before sending data to the server.
     * It allows you to edit data before it is sent, or choose not to send it all.
     * if provided as an array the functions are called in the order they are provided
     * any one function returning null means the event will not be sent
     */
    before_send?: BeforeSendFn | BeforeSendFn[]

    /** @deprecated - use `before_send` instead */
    sanitize_properties: ((properties: Properties, event_name: string) => Properties) | null

    /** @deprecated - use `before_send` instead */
    _onCapture: (eventName: string, eventData: CaptureResult) => void

    /**
     * Determines whether to capture performance metrics.
     * These include Network Timing for Session Replay and Web Vitals.
     *
     * The `network_timing` option is only used by the Session Replay feature.
     * For more session recording settings, see the `session_recording` and `enable_recording_console_log` configuration option.
     *
     * When `undefined`, fallback to the remote configuration.
     * If `false`, neither network timing nor web vitals will work.
     * If an object, that will override the remote configuration.
     *
     * @see {PerformanceCaptureConfig}
     * @default undefined
     */
    capture_performance?: boolean | PerformanceCaptureConfig

    /**
     * Determines whether to disable compression when sending events to the server.
     * WARNING: Should only be used for testing. Could negatively impact performance.
     *
     * @default false
     */
    disable_compression: boolean

    /**
     * An object containing the `distinctID`, `isIdentifiedID`, and `featureFlags` keys,
     * where `distinctID` is a string, and `featureFlags` is an object of key-value pairs.
     *
     * Since there is a delay between initializing PostHog and fetching feature flags,
     * feature flags are not always available immediately.
     * This makes them unusable if you want to do something like redirecting a user
     * to a different page based on a feature flag.
     *
     * You can, therefore, fetch the feature flags in your server and pre-fill them here,
     * allowing PostHog to know the feature flag values immediately.
     *
     * After the SDK fetches feature flags from PostHog, it will use those flag values instead of bootstrapped ones.
     *
     * @default {}
     */
    bootstrap: BootstrapConfig

    /**
     * The segment analytics object.
     *
     * @see https://posthog.com/docs/libraries/segment
     */
    segment?: SegmentAnalytics

    /**
     * Determines whether to capture heatmaps.
     *
     * @see {HeatmapConfig}
     * @default undefined
     */
    capture_heatmaps?: boolean | HeatmapConfig

    /* @deprecated - use `capture_heatmaps` instead */
    enable_heatmaps?: boolean

    /**
     * Determines whether to capture dead clicks.
     *
     * by default dead clicks are ignored on elements that match a `ph-no-capture` or `ph-no-deadclick` css class on the element or a parent
     *
     * @see {DeadClicksAutoCaptureConfig}
     * @default undefined
     */
    capture_dead_clicks?: boolean | DeadClicksAutoCaptureConfig

    /**
     * Determines whether to capture exceptions.
     *
     * @see {ExceptionAutoCaptureConfig}
     * @default undefined
     */
    capture_exceptions?: boolean | ExceptionAutoCaptureConfig

    /**
     * Determines whether to disable scroll properties.
     * These allow you to keep track of how far down someone scrolled in your website.
     *
     * @default false
     */
    disable_scroll_properties?: boolean

    /**
     * Let the pageview scroll stats use a custom css selector for the root element, e.g. `main`
     * It will use `window.document.documentElement` if not specified.
     */
    scroll_root_selector?: string | string[]

    /**
     * You can control whether events from PostHog-js have person processing enabled with the `person_profiles` config setting.
     * There are three options:
     * - `person_profiles: 'always'` - we will process persons data for all events
     * - `person_profiles: 'never'` - we won't process persons for any event. This means that anonymous users will not be merged once they sign up or login, so you lose the ability to create funnels that track users from anonymous to identified. All events (including `$identify`) will be sent with `$process_person_profile: False`.
     * - `person_profiles: 'identified_only'` _(default)_ - we will only process persons when you call `posthog.identify`, `posthog.alias`, `posthog.setPersonProperties`, `posthog.group`, `posthog.setPersonPropertiesForFlags` or `posthog.setGroupPropertiesForFlags` Anonymous users won't get person profiles.
     *
     * @default 'identified_only'
     */
    person_profiles?: 'always' | 'never' | 'identified_only'

    /** @deprecated - use `person_profiles` instead  */
    process_person?: 'always' | 'never' | 'identified_only'

    /**
     * Client side rate limiting
     */
    rate_limiting?: {
        /**
         * The average number of events per second that should be permitted
         *
         * @default 10
         */
        events_per_second?: number

        /**
         * How many events can be captured in a burst. This defaults to 10 times the events_per_second count
         *
         * @default 10 * `events_per_second`
         */
        events_burst_limit?: number
    }

    /**
     * Used when sending data via `fetch`, use with care.
     * This is intentionally meant to be used with NextJS `fetch`
     *
     * Incorrect `cache` usage may cause out-of-date data for feature flags, actions tracking, etc.
     * See https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options
     */
    fetch_options?: {
        cache?: RequestCache
        next_options?: NextOptions
    }

    /**
     * Used to change the behavior of the request queue.
     * This is an advanced feature and should be used with caution.
     */
    request_queue_config?: RequestQueueConfig

    /**
     * Used to set-up external integrations with PostHog data - such as session replays, distinct id, etc.
     */
    integrations?: Record<ExternalIntegrationKind, boolean>

    /**
     * Enables cookieless mode. In this mode, PostHog will not set any cookies, or use session or local storage. User
     * identity is handled by generating a privacy-preserving hash on PostHog's servers.
     *
     * Web Vitals (`capture_performance.web_vitals`) are supported: metrics are sent without client session IDs;
     * ingestion assigns `$session_id` when cookieless mode is enabled for the project.
     *
     * - 'always' - enable cookieless mode immediately on startup, use this if you do not intend to show a cookie banner
     * - 'on_reject' - enable cookieless mode only if the user rejects cookies, use this if you want to show a cookie banner. If the user accepts cookies, cookieless mode will not be used, and PostHog will use cookies and local storage as usual.
     *
     * Note that you MUST enable cookieless mode in your PostHog project's settings, otherwise all your cookieless events will be ignored. We plan to remove this requirement in the future.
     * */
    cookieless_mode?: 'always' | 'on_reject'

    /**
     * A hostname pattern to match test environments. When the current hostname matches,
     * `setInternalOrTestUser()` is called automatically on startup, enabling person processing
     * and setting `$internal_or_test_user: true`.
     *
     * Can be a string (exact match) or RegExp (pattern match).
     * Set to `null` to explicitly disable (useful when using `defaults: '2026-01-30'`).
     *
     * @default undefined (when defaults is before '2026-01-30')
     * @default /^(localhost|127\.0\.0\.1)$/ (when defaults >= '2026-01-30')
     *
     * @example
     * ```js
     * // Exact match
     * posthog.init('token', { internal_or_test_user_hostname: 'example.com' })
     *
     * // Regex pattern
     * posthog.init('token', { internal_or_test_user_hostname: /\.local$/ })
     *
     * // Disable
     * posthog.init('token', { internal_or_test_user_hostname: null })
     * ```
     */
    internal_or_test_user_hostname?: string | RegExp | null

    /**
     * Display language override for Product Tours.
     *
     * Must be a valid BCP 47 language code.
     *
     * In the future this will be used for Surveys and other products that
     * deliver in-app experiences to end-users.
     */
    override_display_language?: string | null

    /**
     * A list of hostnames for which to inject PostHog tracing headers to all requests
     * (X-POSTHOG-DISTINCT-ID, X-POSTHOG-SESSION-ID, X-POSTHOG-WINDOW-ID). Used to link
     * frontend sessions to backend traces (see https://posthog.com/docs/llm-analytics/link-session-replay).
     */
    addTracingHeaders?: string[]

    // ------- PREVIEW CONFIGS -------

    /**
     * @deprecated Use {@link addTracingHeaders} instead. Kept for backwards compatibility.
     */
    __add_tracing_headers?: string[]

    /**
     * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION
     * Whether to use the new /flags/ endpoint
     * */
    __preview_flags_v2?: boolean

    /**
     * PREVIEW - MAY CHANGE WITHOUT WARNING - ONLY USE WHEN TALKING TO POSTHOG SUPPORT
     * Enables deprecated eager loading of session recording code, not just rrweb and network plugin
     * we are switching the default to lazy loading because the bundle will ultimately be 18% smaller then
     * keeping this around for a few days in case there are unexpected consequences that testing did not uncover
     * */
    __preview_eager_load_replay?: boolean

    /**
     * Prevents posthog-js from using the `navigator.sendBeacon` API to send events.
     * Enabling this option may hurt the reliability of sending $pageleave events
     */
    __preview_disable_beacon?: boolean

    /**
     * Disables sending credentials when using XHR requests.
     */
    __preview_disable_xhr_credentials?: boolean

    /**
     * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION
     * Loads external dependency bundles (for example recorder.js and toolbar.js) from
     * semver-qualified asset paths such as /static/1.370.0/recorder.js instead of the
     * legacy /static/recorder.js?v=1.370.0 form.
     *
     * When set to a string, that string is treated as an asset host override for any
     * /static/* asset path while leaving non-static asset paths unchanged.
     */
    __preview_external_dependency_versioned_paths?: boolean | string

    /**
     * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION
     * Enables collection of bot traffic as $bot_pageview events with detailed bot detection
     * properties instead of dropping them entirely. Use it alongside opt_out_useragent_filter
     */
    __preview_capture_bot_pageviews?: boolean

    // ------- RETIRED CONFIGS - NO REPLACEMENT OR USAGE -------

    /**
     * @deprecated - does nothing
     * was present only for PostHog testing of replay lazy loading
     * */
    __preview_lazy_load_replay?: boolean

    /** @deprecated - NOT USED ANYMORE, kept here for backwards compatibility reasons */
    api_method?: string

    /** @deprecated - NOT USED ANYMORE, kept here for backwards compatibility reasons */
    inapp_protocol?: string

    /** @deprecated - NOT USED ANYMORE, kept here for backwards compatibility reasons */
    inapp_link_new_window?: boolean

    /**
     * @deprecated - THIS OPTION HAS NO EFFECT, kept here for backwards compatibility reasons.
     * Use a custom transformation or "Discard IP data" project setting instead: @see https://posthog.com/tutorials/web-redact-properties#hiding-customer-ip-address.
     */
    ip: boolean
}
