posthog-js
1.438.13 · 20 Oct 2026(Apache-2.0 AND MIT)10.1M / weekRepositoryHomepagenpmAtom feed
1421 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
1.425.0
2 Sep 2026Forward generic server-signed identity claims with conversations widget requests.
(2026-09-02)
Minor Changes
Forward generic server-signed identity claims with conversations widget requests.
(2026-09-02)
1.424.1
1 Sep 2026Prevent failed replay network body reads from escaping into the host page's own
fetch()call
(2026-09-01)
1.424.0
1 Sep 2026Add
os.nameandos.versionresource attributes to logs from the browser SDK, overridable vialogs.resourceAttributes
(2026-09-01)
Minor Changes
Add
os.nameandos.versionresource attributes to logs from the browser SDK, overridable vialogs.resourceAttributes
(2026-09-01)
1.423.2
1 Sep 2026Sanitize legacy product tour HTML before rendering
(2026-09-01)
1.423.1
1 Sep 2026Prevent stale session recorders from initializing after consent or session teardown, and dispose of recorders when switching to cookieless mode.
(2026-09-01)
1.423.0
1 Sep 2026Detect the Claude, Codex, and ChatGPT apps from their user agent markers:
$browsernow reports the app name instead ofChrome.ChatGPT versions its apps differently per platform, so its
$browser_versionis not comparable across platforms. (2026-09-01)Synchronize feature flag and early access enrollment persistence across browser tabs. Keep successful partial evaluations authoritative for payload updates and removals, including falsy payload values, while retaining cached state for failed evaluations.
(2026-09-01)Prefer
data-ph-capture-attribute-*values from the closest element when the same property is defined on multiple ancestors.
(2026-09-01)
Minor Changes
Detect the Claude, Codex, and ChatGPT apps from their user agent markers:
$browsernow reports the app name instead ofChrome.ChatGPT versions its apps differently per platform, so its
$browser_versionis not comparable across platforms. (2026-09-01)Synchronize feature flag and early access enrollment persistence across browser tabs. Keep successful partial evaluations authoritative for payload updates and removals, including falsy payload values, while retaining cached state for failed evaluations.
(2026-09-01)
Patch Changes
Prefer
data-ph-capture-attribute-*values from the closest element when the same property is defined on multiple ancestors.
(2026-09-01)Harden the directly importable
getElementsChainStringutility against runtime JavaScript callers that pass a non-array value. It now returns an empty string instead of calling.mapon malformed input.
(2026-09-01)Change
bigintattributes on logs, metrics and spans to send as an int64 rather than as a string.
(2026-09-01)Respect
navigator.globalPrivacyControlwhenrespect_dntis enabled
(2026-09-01)Fix a memory leak in Session Replay recording:
MutationBufferskipped its own cleanup whenever a mutation batch normalized to an empty payload (e.g. a node added and removed within the same task), leaving the buffer holding strong references to DOM nodes indefinitely.
(2026-09-01)Error tracking now drops a known uBlock Origin Lite exception thrown by its Safari extension. Safari masks extension content-script URLs as
webkit-masked-url://hidden/, but also uses that URL for application code, so the filter requires the extension's error signature before dropping an all-masked stack. A remaining unmaskedin_appframe still preserves the exception as first-party.
(2026-09-01)back off support widget polling to stop starving sends
(2026-09-01)Fall back to in-memory storage when neither web storage nor cookies are available, instead of selecting a backend that cannot store anything. In contexts like a
data:URL — a Figma plugin, for example — Chrome disables localStorage and cookies alike, and both the persistence and consent paths previously committed to an unusable store, logging a SecurityError on every capture.cookieStore._is_supported()now round-trips a probe cookie rather than only checking thatdocumentexists, andmemoryStoreno longer reports a stored falsy value (such as the0consent writes for "opted out") as absent.
(2026-09-01)Warn at init when
persistenceis'memory'or'sessionStorage'and nobootstrap.distinctIDis set. In this setup the SDK mints a fresh distinct ID on every page load, so eachidentify()call merges another ID onto the same person. A person can then pass the distinct-ID limit, after which person pages and the session tab load only a truncated slice and the rest of the events look missing even though ingestion is fine. The warning points at the two fixes: switch tolocalStorage+cookie, or keep this persistence and pass a stable ID throughbootstrap.distinctID.
(2026-09-01)Fix an uncaught
TypeErrorin the web vitals attribution bundle. The attributed INP observer readstartTimefrom the first entry without a guard, so a report with no entries (for example after a bfcache restore or soft navigation) threw and stopped the metric capture. Bumpweb-vitalsto 6.2.1, which guards the empty-entry case: instead of throwing, it reports the metric with fallback attribution that carries no interaction details (zeroed input and processing delays).
(2026-09-01)
1.422.5
28 Aug 2026Only updates a dependency:@posthog/browser-common 0.7.0
1.422.4
28 Aug 2026Re-translate popover surveys when the display language changes while the survey is on screen, either from a browser
languagechangeevent or fromidentify()updating thelanguageperson property. In-progress answers are preserved.$survey_questions.questionand$survey_languageonsurvey sent/survey dismissednow report the text and language the user saw when they answered, not the language active when the event fired. Feedback-button (widget) surveys are unchanged.
(2026-08-28)
Patch Changes
Re-translate popover surveys when the display language changes while the survey is on screen, either from a browser
languagechangeevent or fromidentify()updating thelanguageperson property. In-progress answers are preserved.$survey_questions.questionand$survey_languageonsurvey sent/survey dismissednow report the text and language the user saw when they answered, not the language active when the event fired. Feedback-button (widget) surveys are unchanged.
(2026-08-28)
1.422.3
28 Aug 2026Autocapture no longer throws a
RangeErrorinto the host page when it sorts element attributes. It now sorts attribute keys with a plain lexical comparator instead oflocaleCompare, which can throw on browsers with faulty ICU data.
(2026-08-28)
Patch Changes
Autocapture no longer throws a
RangeErrorinto the host page when it sorts element attributes. It now sorts attribute keys with a plain lexical comparator instead oflocaleCompare, which can throw on browsers with faulty ICU data.
(2026-08-28)
1.422.2
28 Aug 2026Session replay can now bound DOM mutation bytes with an opt-in budget. Set
__mutationBytesBucketSize(e.g. 1MB) to enable: mutations beyond the sustained budget (__mutationBytesRefillRate, default 25KB/s) are dropped and the recording resyncs with a full snapshot, keeping recordings from apps with very high DOM churn playable. Off by default.
(2026-08-28)
Patch Changes
Session replay can now bound DOM mutation bytes with an opt-in budget. Set
__mutationBytesBucketSize(e.g. 1MB) to enable: mutations beyond the sustained budget (__mutationBytesRefillRate, default 25KB/s) are dropped and the recording resyncs with a full snapshot, keeping recordings from apps with very high DOM churn playable. Off by default.
(2026-08-28)
1.422.1
27 Aug 2026Narrow the
pinterestentry in the bot-detection blocklist topinterestbot, so real users on Pinterest's in-app browser (whose UA also contains the substringpinterest) are no longer misclassified as bots and silently excluded from analytics. The crawler's other UA variant remains covered by the existing genericbot.htmentry, so no bot-detection coverage is lost.
(2026-08-27)
Patch Changes
Narrow the
pinterestentry in the bot-detection blocklist topinterestbot, so real users on Pinterest's in-app browser (whose UA also contains the substringpinterest) are no longer misclassified as bots and silently excluded from analytics. The crawler's other UA variant remains covered by the existing genericbot.htmentry, so no bot-detection coverage is lost.
(2026-08-27)
1.422.0
27 Aug 2026Report
$sdk_debug_replay_throttled_mutations_droppedon captured events, counting the attribute changes the session recorder discarded during that session. The recorder throttles elements that change hundreds of times a second, and a discardedclassorstylechange never reaches the player — so a recording can keep showing an element the live page had already hidden. Query this property to see whether your app is affected.
(2026-08-27)
1.421.2
27 Aug 2026Fix request timeouts never firing on pages where a browser extension makes
Error.prototype.namenon-writable
(2026-08-27)Fix
logs.captureConsoleLogsset ininit()not enabling console autocapture, captureconsolecalls made before the logs script loads, and drop captured console records when the user opts out
(2026-08-27)Fix session replay and posthog-js leaving each other's
consolewrapper in the call path when either one stops
(2026-08-27)
Patch Changes
Fix request timeouts never firing on pages where a browser extension makes
Error.prototype.namenon-writable
(2026-08-27)Fix
logs.captureConsoleLogsset ininit()not enabling console autocapture, captureconsolecalls made before the logs script loads, and drop captured console records when the user opts out
(2026-08-27)Fix session replay and posthog-js leaving each other's
consolewrapper in the call path when either one stops
(2026-08-27)
1.421.1
27 Aug 2026Use the best available compression for browser feature flag requests, preferring gzip when supported.
(2026-08-27)Drop
sourcesContentfrom the source maps published to npm. The maps themselves still ship, so downstream source-map chaining and the//# sourceMappingURLreferences are unaffected — only the copy of our TypeScript sources embedded in each map is gone, taking the package from 40.8 MB to 17.4 MB unpacked. CDN artifacts are built separately and keep their inlined sources.
(2026-08-27)
Patch Changes
Use the best available compression for browser feature flag requests, preferring gzip when supported.
(2026-08-27)Drop
sourcesContentfrom the source maps published to npm. The maps themselves still ship, so downstream source-map chaining and the//# sourceMappingURLreferences are unaffected — only the copy of our TypeScript sources embedded in each map is gone, taking the package from 40.8 MB to 17.4 MB unpacked. CDN artifacts are built separately and keep their inlined sources.
(2026-08-27)
1.421.0
26 Aug 2026Add the
2026-08-30config defaults. These defaults enable sanitized JSON-LD replay events.
(2026-08-26)
Minor Changes
Add the
2026-08-30config defaults. These defaults enable sanitized JSON-LD replay events.
(2026-08-26)
1.420.0
26 Aug 2026Add opt-in Schema.org JSON-LD capture to session replay through
session_recording.captureJsonLd. When enabled, the recorder emits sanitized JSON-LD as custom replay events and excludes all script elements from replay snapshots.
(2026-08-26)Capture paste interactions with clipboard autocapture without collecting pasted text.
(2026-08-26)Fix session replay playback ending when a recording contains a shadow host the browser refuses. The player now skips that one subtree instead of aborting the rebuild.
(2026-08-26)
Minor Changes
Add opt-in Schema.org JSON-LD capture to session replay through
session_recording.captureJsonLd. When enabled, the recorder emits sanitized JSON-LD as custom replay events and excludes all script elements from replay snapshots.
(2026-08-26)
Patch Changes
Capture paste interactions with clipboard autocapture without collecting pasted text.
(2026-08-26)Fix session replay playback ending when a recording contains a shadow host the browser refuses. The player now skips that one subtree instead of aborting the rebuild.
(2026-08-26)
1.419.4
25 Aug 2026Add typed stable-name lookup for installed browser extensions and use it when independently loaded survey code resolves feature flags.
(2026-08-25)Fix console log autocapture silently failing when an older
posthog-jscore loads a newer logs bundle.
(2026-08-25)browser: refresh configured feature flags when a hidden tab becomes visible
Feature flags now own their automatic refresh timer and visibility listener.
Hidden tabs reload due flags when they become visible. The existing five-minute
default andremote_config_refresh_interval_msbehavior remain unchanged. (2026-08-25)
Patch Changes
Add typed stable-name lookup for installed browser extensions and use it when independently loaded survey code resolves feature flags.
(2026-08-25)Fix console log autocapture silently failing when an older
posthog-jscore loads a newer logs bundle.
(2026-08-25)browser: refresh configured feature flags when a hidden tab becomes visible
Feature flags now own their automatic refresh timer and visibility listener.
Hidden tabs reload due flags when they become visible. The existing five-minute
default andremote_config_refresh_interval_msbehavior remain unchanged. (2026-08-25)
1.419.3
25 Aug 2026Fix surveys recording a response before the respondent finishes, and reordering questions for surveys that use branching, are prefilled, or are resumed
An
initialResponsesprefill passed toposthog.displaySurvey()that neither completes the survey nor auto-advances a question no longer sendssurvey sent, and a partial event carries only the auto-advanced answers. (2026-08-25)
1.419.2
25 Aug 2026Type declarations no longer import the
JSXnamespace fromreact, so they typecheck against@types/reactback to the declared 16.8.0 floor. Component return types are now spelledReactElement<any, any>, which is the definition ofJSX.Element— the same type, so consuming code is unaffected.JSXonly became an exported member of thereacttypes module in@types/react@18.2.6, so projects on older React types previously sawTS2305: Module '"react"' has no exported member 'JSX'when checking these declarations withskipLibCheck: false. (2026-08-25)
1.419.1
25 Aug 2026Declare
reactand@types/reactas optional peer dependencies so theposthog-js/reactentry point can resolve React on strictnode_moduleslayouts — pnpm and bun isolated linkers backed by a global store, where the package is installed outside the project tree and Node's directory walk never reaches the app's React.Projects that do not import
posthog-js/reactare unaffected: the peers are optional, so npm, pnpm, yarn, and bun install them only when React is already present and emit no unmet-peer warnings. (2026-08-25)
1.419.0
25 Aug 2026Web vitals now capture attribution by default for INP and LCP, so a slow interaction or paint arrives with the target element and phase breakdown that make it diagnosable. CLS stays without attribution by default, because its attribution holds detached DOM nodes and can leak memory in single-page apps. Set
capture_performance.web_vitals_attributiontofalseto opt out,truefor every metric, or an array to name the metrics. The captured metric also drops the emptyentriesarray and bounds attribution to a small set of useful fields, and the attributed INP observer no longer collects theprocessedEventEntrieswe never read.
(2026-08-25)
Minor Changes
Web vitals now capture attribution by default for INP and LCP, so a slow interaction or paint arrives with the target element and phase breakdown that make it diagnosable. CLS stays without attribution by default, because its attribution holds detached DOM nodes and can leak memory in single-page apps. Set
capture_performance.web_vitals_attributiontofalseto opt out,truefor every metric, or an array to name the metrics. The captured metric also drops the emptyentriesarray and bounds attribution to a small set of useful fields, and the attributed INP observer no longer collects theprocessedEventEntrieswe never read.
(2026-08-25)
1.418.17
25 Aug 2026Prevent session recordings from emitting failed CSSOM changes and fix shadow DOM, cross-origin iframe, blocked and unsupported canvas, and deep DOM serialization edge cases.
(2026-08-25)Share survey property matching between the browser and React Native SDKs while preserving their existing missing-value behavior.
(2026-08-25)
Patch Changes
Prevent session recordings from emitting failed CSSOM changes and fix shadow DOM, cross-origin iframe, blocked and unsupported canvas, and deep DOM serialization edge cases.
(2026-08-25)Share survey property matching between the browser and React Native SDKs while preserving their existing missing-value behavior.
(2026-08-25)
1.418.16
24 Aug 2026Drop exceptions thrown by user scripts the browser injects into every page (Firefox for iOS, Chrome for iOS) instead of reporting them as the page's own errors. Set
error_tracking.captureExtensionExceptions: trueto keep capturing them.
(2026-08-24)
Patch Changes
Drop exceptions thrown by user scripts the browser injects into every page (Firefox for iOS, Chrome for iOS) instead of reporting them as the page's own errors. Set
error_tracking.captureExtensionExceptions: trueto keep capturing them.
(2026-08-24)
1.418.15
24 Aug 2026Migrate surveys to the shared browser extension lifecycle.
(2026-08-24)
Patch Changes
Migrate surveys to the shared browser extension lifecycle.
(2026-08-24)
1.418.14
24 Aug 2026Migrate browser autocapture to the shared extension lifecycle.
(2026-08-24)Fix logs and metrics batches being dropped instead of retried after HTTP 408
(2026-08-24)
Patch Changes
Migrate browser autocapture to the shared extension lifecycle.
(2026-08-24)Fix logs and metrics batches being dropped instead of retried after HTTP 408
(2026-08-24)
1.418.13
24 Aug 2026add granular automatic pageview options for SPA navigation
capture_pageviewnow accepts an object withpath,search, andhashoptions. Each selected URL component triggers a$pageviewwhen it changes, including direct hash changes used by hash-based routers. The existing'history_change'option continues to capture pathname changes. (2026-08-24)
Patch Changes
add granular automatic pageview options for SPA navigation
capture_pageviewnow accepts an object withpath,search, andhashoptions. Each selected URL component triggers a$pageviewwhen it changes, including direct hash changes used by hash-based routers. The existing'history_change'option continues to capture pathname changes. (2026-08-24)
1.418.12
24 Aug 2026Session replay: fixed a stale element left rendered in the player when a mutation re-added a node id with changed attributes. Affects both
useVirtualDommodes.
(2026-08-24)
1.418.11
24 Aug 2026Stop adding PostHog's optional feature scripts, such as the session replay recorder and exception autocapture, to the page more than once. Sites that proxy PostHog through their own domain, by setting
api_hostto a path like/ingestrather than a full URL, ended up with the same<script>tag three or four times: the check meant to spot the duplicate compared the browser's resolved absolute URL against the relative one, so it never matched. The network tab showed a single request either way, because the browser served the repeats from its cache, which is why this was easy to miss. Nothing measurable got slower as a result, so this is a correctness fix rather than a speed one.
(2026-08-24)When session replay is waiting on a trigger, debug mode now names the conditions that haven't matched yet (for example
buffering: URL condition not matched, or the named trigger group whose condition is pending) instead of only reportingbuffering. Enable it withposthog.debug(). Logged once per change, not once per flush.
(2026-08-24)
1.418.10
21 Aug 2026Guard the replayer's hover handling against non-element and detached hover targets, which previously threw an unhandled
TypeError(querySelectorAllon a node without that method) and stopped session recording playback mid-stream.
(2026-08-21)Keep replay playback running when a recording adopts constructed stylesheets across a document swap. A constructed stylesheet can only be adopted by the document that created it, so a sheet held over a swap is rejected and the error previously stopped the player. Adoption now falls back to whatever is already applied.
(2026-08-21)
1.418.9
21 Aug 2026replay: attribute the backdated sessionIdle marker to the session that went idle, so a rotation-born session's recording no longer starts hours before its first snapshot
(2026-08-21)
1.418.8
21 Aug 2026Fix logs and metrics being silently dropped when an attribute holds a very large integer, a function, a symbol, a sparse array, or a truncated emoji.
Cap log and metric attributes at 20 levels of nesting, 1,000 entries per object and 10,000 values in total, marking anything beyond as[Truncated].
TypeOtlpAnyValue.intValueasstring | number— code reading that field must handle both. (2026-08-21)
Patch Changes
Fix logs and metrics being silently dropped when an attribute holds a very large integer, a function, a symbol, a sparse array, or a truncated emoji.
Cap log and metric attributes at 20 levels of nesting, 1,000 entries per object and 10,000 values in total, marking anything beyond as[Truncated].
TypeOtlpAnyValue.intValueasstring | number— code reading that field must handle both. (2026-08-21)
1.418.7
21 Aug 2026browser: stop the
$posthog_cookielesssentinel from leaking intoidentify()and real events. A tab that missed a cross-tab consent flip could emit the sentinel as a durable distinct_id — merging distinct real users into a single person. It now adopts the identity persisted by the tab that handled consent, falling back to a fresh anonymous device id when persistence is not shared.
(2026-08-21)Render React component stacks as linked exception causes so error tracking identifies the crashing component.
(2026-08-21)
1.418.6
20 Aug 2026- removed
Drop events when a before-send hook throws instead of sending the unmodified event.
(2026-08-20) Stop building a stack frame for a
window.onerrorreport that carries no code position, such as theResizeObserverloop warning. The frame named the document URL rather than a script, so no source map could resolve it. These exceptions now arrive with no stack trace.
(2026-08-20)
Patch Changes
- removed
Drop events when a before-send hook throws instead of sending the unmodified event.
(2026-08-20) Stop building a stack frame for a
window.onerrorreport that carries no code position, such as theResizeObserverloop warning. The frame named the document URL rather than a script, so no source map could resolve it. These exceptions now arrive with no stack trace.
(2026-08-20)
1.418.5
19 Aug 2026Stop counting Chromium
<anonymous>stack frames (extension-injected, devtools or string-evaluated code) as in-app code.
(2026-08-19)
Patch Changes
Stop counting Chromium
<anonymous>stack frames (extension-injected, devtools or string-evaluated code) as in-app code.
(2026-08-19)
1.418.4
19 Aug 2026Fix session recording in the full browser bundles.
array.full.jsandmodule.full.es.jsonly inlined rrweb, so they still fetched the recorder script at runtime - the request the full bundles exist to avoid. They now inline the whole recorder. Also flags the session with$sdk_debug_recording_script_not_loadedwhen the recorder script fails to load, so a blocked recorder is visible in analytics rather than only in the console.
(2026-08-19)
1.418.3
19 Aug 2026Fall back to the synthetic exception stack when a captured
Errorhas no stack, so frameless failures (such as a Firefox networkfetchTypeError) keep their call-site frames and group per call site instead of merging into one issue.
(2026-08-19)
Patch Changes
Fall back to the synthetic exception stack when a captured
Errorhas no stack, so frameless failures (such as a Firefox networkfetchTypeError) keep their call-site frames and group per call site instead of merging into one issue.
(2026-08-19)
1.418.2
19 Aug 2026Fix a Chrome renderer crash (grey "Aw, Snap" tab, "Error code: 5") that could still occur when closing an in-app survey on a heavy page such as a large dashboard.
Closing a survey animated the fade-out with
document.startViewTransition, which snapshots the entire page viewport. The survey applied noview-transition-namescoping, so on a heavy host page capturing that whole-page snapshot could exhaust renderer memory and crash the tab. A previous fix addressed a related crash (a snapshot pointing at a removed node) but left the document-level transition — and its whole-page snapshot cost — in place.The survey renders in an isolated shadow root, so it never needed a document-level transition. The close now fades the popup out with a plain CSS opacity transition scoped to the survey's own container, then unmounts it once the fade has run. No whole-page snapshot, no crash, same fade-out UX. (2026-08-19)
1.418.1
18 Aug 2026Recognise Firefox and Safari extension frames when filtering extension exceptions, and stop counting Safari's masked
webkit-masked-url://frames as in-app code.
(2026-08-18)
Patch Changes
Recognise Firefox and Safari extension frames when filtering extension exceptions, and stop counting Safari's masked
webkit-masked-url://frames as in-app code.
(2026-08-18)
1.418.0
18 Aug 2026Add
cookieWinsOnConflictto keep shared cross-subdomain identity and session state ahead of stale per-origin localStorage, deprecate__preview_cookie_wins_on_conflict, and enable the new behavior for the2026-08-29defaults.
(2026-08-18)
Minor Changes
Add
cookieWinsOnConflictto keep shared cross-subdomain identity and session state ahead of stale per-origin localStorage, deprecate__preview_cookie_wins_on_conflict, and enable the new behavior for the2026-08-29defaults.
(2026-08-18)
1.417.4
17 Aug 2026Take a full snapshot when session recording wakes from idle if DOM mutations were dropped while idle, so replay no longer shows duplicated or overlapping DOM after an idle period.
(2026-08-17)
1.417.3
17 Aug 2026Restore exception autocapture compatibility for posthog-js clients through version 1.141.0.
(2026-08-17)
1.417.2
17 Aug 2026Fix error tracking coercion reporting the wrong exception type for non-
Errorobjects (e.g.TypeError,ReferenceError) that are thrown by browser extensions or other cross-realm code. Previously these always reported as typeError, burying the real type in the message string. Also fixed a localisErrorhelper shadowing the more robust cross-realm-aware implementation, which caused some errors thrown from iframes or extension isolated worlds to be misclassified.
(2026-08-17)
Patch Changes
Fix error tracking coercion reporting the wrong exception type for non-
Errorobjects (e.g.TypeError,ReferenceError) that are thrown by browser extensions or other cross-realm code. Previously these always reported as typeError, burying the real type in the message string. Also fixed a localisErrorhelper shadowing the more robust cross-realm-aware implementation, which caused some errors thrown from iframes or extension isolated worlds to be misclassified.
(2026-08-17)
1.417.1
14 Aug 2026Normalize capture timestamp overrides to equivalent UTC ISO strings in the browser and Node.js SDKs and shared core.
(2026-08-14)Prevent swallowed rrweb observer initialization errors from breaking session replay teardown and subsequent recorder restarts.
(2026-08-14)dead-clicks: treat visibility and focus changes as liveness signals, not dead-click evidence
The dead-click detector treated a
visibilitychangeas evidence a click was dead: it measuredMath.abs(clickTimestamp - lastVisibilityChange)and, once that exceeded the threshold, timed the click out as dead. Because it only recorded the tab becoming visible, any click in a session where the tab had ever been backgrounded (median gap ~1 minute) was flagged.A visibility or focus change near a click is the opposite — a sign the click did something (it woke/focused the tab, opened a new tab, or opened a new window/popup) — so these signals now only ever suppress a dead click, never cause one:
Patch Changes
Normalize capture timestamp overrides to equivalent UTC ISO strings in the browser and Node.js SDKs and shared core.
(2026-08-14)Prevent swallowed rrweb observer initialization errors from breaking session replay teardown and subsequent recorder restarts.
(2026-08-14)dead-clicks: treat visibility and focus changes as liveness signals, not dead-click evidence
The dead-click detector treated a
visibilitychangeas evidence a click was dead: it measuredMath.abs(clickTimestamp - lastVisibilityChange)and, once that exceeded the threshold, timed the click out as dead. Because it only recorded the tab becoming visible, any click in a session where the tab had ever been backgrounded (median gap ~1 minute) was flagged.A visibility or focus change near a click is the opposite — a sign the click did something (it woke/focused the tab, opened a new tab, or opened a new window/popup) — so these signals now only ever suppress a dead click, never cause one:
Visibility changes are recorded in both directions (a click that opens a new tab sends the current tab to
hidden), and a windowfocus/blurobserver is added, since a click that opens a new window/popup may leave the tab visible and only surface as the current window losing focus.A click within a wake-up/interaction window (1s, wide enough for a real "tab back, then click" gesture) of any such change is suppressed.
The visibility signal no longer feeds the dead-marking path at all.
$dead_click_visibility_changed_timeoutstays in the payload (always false) for shape compatibility, and a new$dead_click_focus_changed_delay_msis emitted for observability.Visibility/focus changes are now recorded onto each queued candidate the instant they fire (like scroll), instead of being read from a single shared timestamp when the click is checked ~1s later. A click that hides or blurs the tab (opening a new tab/window) suspends that check while the tab is backgrounded; by the time it resumes the tab has usually returned, and the shared timestamp would have been overwritten by that later transition — losing the click-correlated one and wrongly flagging the click dead. Stamping the candidate as the event fires makes delayed hide→show and blur→focus sequences suppress correctly. (2026-08-14)
1.417.0
13 Aug 2026Default external dependency loading to versioned asset paths with automatic fallback to legacy paths, and add a
strict_script_versioning: 'fallback'mode.
(2026-08-13)
Minor Changes
Default external dependency loading to versioned asset paths with automatic fallback to legacy paths, and add a
strict_script_versioning: 'fallback'mode.
(2026-08-13)
1.416.1
13 Aug 2026Harden the session replay stylesheet inlining budget (
inlineStylesheetBudgetRules):
Patch Changes
Harden the session replay stylesheet inlining budget (
inlineStylesheetBudgetRules):The default budget (10,000 rules) moves from the recorder chunk into posthog-js session recording options, so npm-pinned or cached bundles keep their configured override (including
0to disable) and directrrweb.record()consumers keep unbounded inlining unless they opt in.Deferred inlining is bounded inside a sheet: a resumable cursor stringifies 200 rules per idle slice and emits a sheet's
_cssTextatomically, so monolithic sheets no longer produce one long task and partial CSS never reaches the wire.Deferred sheets are flushed synchronously when recording stops and on
pagehide; residual failure modes are counted via$sdk_debug_replay_deferred_stylesheets_failed/_abandoned.CSSOM-only styles (
insertRuleoutput,adoptedStyleSheets) no longer charge the budget, since deferring<link>sheets buys those pages nothing.Telemetry fixes: full-snapshot duration wraps the whole synchronous task, deferred counts are cumulative per session, new gauges cover non-deferrable rules and idle stringification cost, and duration samples straddling tab suspension are discarded (
$sdk_debug_replay_discarded_duration_samples). (2026-08-13)
1.416.0
12 Aug 2026browser: add
rewriteRequestPathto customize API, feature flag, and asset paths for reverse proxies
(2026-08-12)Add reset options for applying bootstrapped identity, feature flag, and session values after
posthog.reset()while preserving the legacy boolean argument.
(2026-08-12)
Minor Changes
browser: add
rewriteRequestPathto customize API, feature flag, and asset paths for reverse proxies
(2026-08-12)Add reset options for applying bootstrapped identity, feature flag, and session values after
posthog.reset()while preserving the legacy boolean argument.
(2026-08-12)
1.415.7
12 Aug 2026Migrate browser feature flags to the shared extension lifecycle while preserving the public feature flag facade, persistence compatibility, request behavior, and event enrichment.
(2026-08-12)
1.415.6
11 Aug 2026Fix session recording starting from arbitrarily old persisted configs.
Recording configs persisted by SDK versions before 1.347.2 carry no
cache_timestamp. The core freshness check treated these undated configs as always fresh, so the recorder started immediately under their settings. A device whose stored config predated a customer's config change kept recording under the old triggers, sample rate, and masking settings indefinitely.The core now treats undated persisted configs as stale. Recording waits for a fresh remote config before it starts, the same path every dated config older than one hour already takes. The lazy recorder bundle is unchanged: it still accepts undated configs, because old cores that load the latest bundle cannot recover from a rejected config (INC-749). (2026-08-11)
1.415.5
11 Aug 2026Fix a Chrome renderer crash (grey "Aw, Snap" tab) that could occur when closing an in-app survey.
The survey close path wrapped the survey container's DOM removal in
document.startViewTransition. Removing the element inside the transition callback left the captured snapshot pointing at a removed node, which on heavy SPAs triggered a Chromium renderer crash and took down the whole tab.The close path now only animates a fade-out inside the transition and lets React tear the container down once the transition settles. It also guards against overlapping transitions (a second close while one is animating) and always settles the popup state if the transition is skipped or interrupted, so the survey can never be left visible with a stale reference. (2026-08-11)
1.415.4
11 Aug 2026types: accept current and legacy Segment Analytics SDK types in the Segment integration config
(2026-08-11)
Patch Changes
types: accept current and legacy Segment Analytics SDK types in the Segment integration config
(2026-08-11)