New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

posthog-js

Package Overview
Dependencies
Maintainers
21
Versions
1484
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

posthog-js

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

Source
npmnpm
Version
1.441.2
Version published
Weekly downloads
24M
107.57%
Maintainers
21
Weekly downloads
 
Created
Source

PostHog JavaScript package

npm package MIT License

Please see the main PostHog docs.

SDK usage examples and code snippets live in the official documentation so they stay up to date.

Documentation

Single script tag

<script
    src="https://us-assets.i.posthog.com/static/loader.js?project_token=phc_YOUR_PROJECT_TOKEN"
    crossorigin="anonymous"
></script>

crossorigin="anonymous" is recommended but optional on the loader tag. Without it, the loader still works, but uses the browser's default script request mode and has limited cross-origin error reporting. The loader cannot change the mode of its own request after download. The full SDK script it injects always uses crossOrigin = 'anonymous', regardless of the outer tag.

Use eu-assets.i.posthog.com for EU projects. Every project loads the same static file: the loader reads project_token from its own URL, falling back to data-project-token. Putting the token in the URL path instead would require additional routing, as with Sentry's loader.

The small loader exposes queued public SDK methods, including people.set and people.set_once, and asynchronously loads an immutable SDK bundle without forwarding the query string. Its method list is generated from the SDK class during the build, so it stays in sync without bundling the SDK itself. Existing snippet and npm installations are unchanged; use only one installation method per page.

Include the tag before application scripts that call posthog. Do not add async or defer if those scripts need the queue immediately. Calls before the full SDK loads are queued; synchronous getters cannot return SDK values yet. The loader does not buffer browser interactions or errors that happen before the SDK installs its listeners.

AttributePurpose
data-project-tokenProject token fallback when the URL has no project_token value.
data-api-hostIngestion host, including relative proxy paths such as /ingest. Inferred for the standard US/EU asset hosts; required for custom asset hosts.
data-defaultsDefaults snapshot override. If neither this attribute nor data-config.defaults is set, the SDK uses unset.
data-configJSON object with SDK options, applied before initialization. Explicit data-api-host and data-defaults attributes take precedence.
data-defer-initSet to true to wait for an explicit init() call. Defaults to false.

For consent-gated automatic installation, set data-config='{"opt_out_capturing_by_default":true}' on the tag before it executes.

Deferred initialization

Set data-defer-init="true" to download the SDK without automatically initializing it. The default is false. Pass the project token and all configuration to an explicit posthog.init() call instead. The automatic-init token and configuration attributes are not used in this mode.

<script src="https://us-assets.i.posthog.com/static/loader.js" data-defer-init="true" crossorigin="anonymous"></script>
<script>
    posthog.init('phc_TOKEN', {
        api_host: 'https://us.i.posthog.com',
        defaults: '2026-08-30',
    })
    posthog.capture('example event')
</script>

Call init() before other SDK methods. If the SDK is still downloading, initialization and subsequent calls are queued. If it has already downloaded, init() uses the normal SDK API. Deferred initialization supports function-valued configuration, such as before_send, and named instances. It does not defer downloading the scripts and is separate from HTML's defer attribute.

The mutable /static/loader.js and /static/<major>/loader.js aliases embed their SDK build version and load /static/<build-version>/array.js. A cached loader therefore keeps using its matching SDK even when the aliases change. The loader does not fall back to the mutable /static/array.js alias.

To pin the SDK, use /static/<version>/loader.js for a release that includes the loader. An explicitly versioned loader URL keeps loading its versioned sibling array.js. Historical releases without a loader are not changed or backfilled. Reverse proxies and self-hosted deployments must serve the versioned SDK directories as well as the loader, along with the SDK's normal API/config/extension paths.

Fatal automatic-initialization configuration errors are reported even when debug mode is off. Invalid JSON configuration still prevents automatic initialization.

The loader forwards its CSP nonce to the SDK script. Your CSP must still allow the SDK, its extensions, and event ingestion. An existing legacy stub or live global instance takes precedence: the loader never replaces it or switches its project token.

Input value autocapture

Native $autocapture change events support field-level opt-in value capture for eligible inputs, textareas, and single-selects. Values are read from the control's .value when the browser emits change.

Value capture is a separate field-level opt-in: fields marked data-ph-capture-value include $input_value. Configure autocapture.capture_value_css_selector_allowlist with an array of CSS selectors or an (element: Element) => boolean predicate to choose other fields; [] disables value capture. Selectors match the field itself, not its ancestors.

Opted-in values are not automatically redacted. Use the synchronous before_send hook to edit or remove $input_value, or drop the event. Password, hidden, file, checkbox, and action inputs are excluded from value enrichment. Existing sensitive-field exclusions, no-capture markers, and mask_all_text remain protected.

Surveys and capture

Built-in surveys stay hidden while event capture is disabled, including before consent when opt_out_capturing_by_default is enabled. This applies to automatic display, displaySurvey() (including ignoreConditions), and renderSurvey(). Delayed surveys recheck capture before appearing.

canRenderSurvey() and canRenderSurveyAsync() return a disabled reason in this state. Custom integrations can still discover surveys through getActiveMatchingSurveys().

If capture stops while a survey is open, submitting keeps the answers in the form and shows an error. It does not mark the survey complete or clear its saved progress. The person can retry after capture is enabled again.

FAQs

Package last updated on 28 Oct 2026

Related posts