Compare Versions - posthog-js
npm/posthog-js/Compare Versions
1.422.4
Patch Changes
- #4626
3c650a1Thanks @nandinitiw! - Re-translate popover surveys when the display language changes while the survey is on screen, either from a browserlanguagechangeevent 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) - Updated dependencies [
3c650a1]:- @posthog/core@1.49.2
1.422.3
Patch Changes
- #4669
d0279e5Thanks @posthog! - Autocapture no longer throws aRangeErrorinto 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) - Updated dependencies [
d0279e5]:- @posthog/browser-common@0.6.2
1.422.2
Patch Changes
- #4665
d5ef459Thanks @fasyy612! - 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) - Updated dependencies [
d5ef459]:- @posthog/types@1.407.1
1.422.1
Patch Changes
- #4636
74ff567Thanks @yfwmaniish! - Narrow thepinterestentry 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) - Updated dependencies [
74ff567]:- @posthog/core@1.49.1
- @posthog/browser-common@0.6.1
1.422.0
Minor Changes
- #4658
db8687cThanks @posthog! - Report$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
Patch Changes
-
#4653
712223aThanks @posthog! - Fix request timeouts never firing on pages where a browser extension makesError.prototype.namenon-writable (2026-08-27) -
#4036
718beeeThanks @emmayusufu! - Fixlogs.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) -
#4036
718beeeThanks @emmayusufu! - Fix session replay and posthog-js leaving each other'sconsolewrapper in the call path when either one stops (2026-08-27) -
Updated dependencies [
718beee,712223a]:- @posthog/core@1.49.0
1.421.1
Patch Changes
-
#4657
9c09bd4Thanks @marandaneto! - Use the best available compression for browser feature flag requests, preferring gzip when supported. (2026-08-27) -
#4520
362d081Thanks @veksa! - DropsourcesContentfrom 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) -
Updated dependencies [
7902e44,e899b1c]:- @posthog/core@1.48.12
1.420.0
Minor Changes
- #4640
0d2cf49Thanks @robbie-c! - Add opt-in Schema.org JSON-LD capture to session replay throughsession_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
-
#4635
ab1383aThanks @robbie-c! - Capture paste interactions with clipboard autocapture without collecting pasted text. (2026-08-26) -
#4594
1d88b4eThanks @posthog! - 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) -
Updated dependencies [
ab1383a,0d2cf49]:- @posthog/types@1.406.2
1.419.4
Patch Changes
-
#4592
ca540f9Thanks @dustinbyrne! - Add typed stable-name lookup for installed browser extensions and use it when independently loaded survey code resolves feature flags. (2026-08-25) -
#4533
53fcb2dThanks @dustinbyrne! - Fix console log autocapture silently failing when an olderposthog-jscore loads a newer logs bundle. (2026-08-25) -
#4476
ed4dd97Thanks @posthog! - fix(browser): refresh configured feature flags when a hidden tab becomes visibleFeature flags now own their automatic refresh timer and visibility listener. Hidden tabs reload due flags when they become visible. The existing five-minute default and
remote_config_refresh_interval_msbehavior remain unchanged. (2026-08-25) -
Updated dependencies [
53fcb2d,ca540f9,ed4dd97]:- @posthog/browser-common@0.6.0
- @posthog/types@1.406.1
1.419.3
Patch Changes
-
#4548
fe933d8Thanks @posthog! - Fix surveys recording a response before the respondent finishes, and reordering questions for surveys that use branching, are prefilled, or are resumedAn
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
Patch Changes
-
#4645
cb7cc12Thanks @turnipdabeets! - Type declarations no longer import theJSXnamespace 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
Patch Changes
-
#4638
d166e54Thanks @github-actions! - Declarereactand@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
Minor Changes
- #4598
334159bThanks @posthog! - 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. Setcapture_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)
Patch Changes
- Updated dependencies [
334159b]:- @posthog/types@1.406.0
1.418.17
Patch Changes
-
#4612
e8a2c2aThanks @marandaneto! - 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) -
#4611
d4eee8fThanks @marandaneto! - Share survey property matching between the browser and React Native SDKs while preserving their existing missing-value behavior. (2026-08-25) -
Updated dependencies [
930de19,d4eee8f]:- @posthog/core@1.48.11
- @posthog/browser-common@0.5.2
1.418.16
Patch Changes
- #4607
7ec4f0dThanks @posthog! - 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. Seterror_tracking.captureExtensionExceptions: trueto keep capturing them. (2026-08-24) - Updated dependencies [
7ec4f0d]:- @posthog/types@1.405.3
1.418.15
Patch Changes
- #4532
60ee0acThanks @dustinbyrne! - Migrate surveys to the shared browser extension lifecycle. (2026-08-24) - Updated dependencies [
60ee0ac]:- @posthog/browser-common@0.5.1
1.418.14
Patch Changes
-
#4513
cb7e4a6Thanks @dustinbyrne! - Migrate browser autocapture to the shared extension lifecycle. (2026-08-24) -
#4623
be299dfThanks @turnipdabeets! - Fix logs and metrics batches being dropped instead of retried after HTTP 408 (2026-08-24) -
Updated dependencies [
be299df]:- @posthog/core@1.48.10
1.418.13
Patch Changes
-
#4418
be2161dThanks @posthog! - feat: add granular automatic pageview options for SPA navigationcapture_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) -
Updated dependencies [
be2161d]:- @posthog/types@1.405.2
1.418.11
Patch Changes
-
#4603
ca030a6Thanks @martinfrancois! - Stop 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 settingapi_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) -
#4453
325870aThanks @posthog! - When session replay is waiting on a trigger, debug mode now names the conditions that haven't matched yet (for examplebuffering: 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
Patch Changes
-
#4451
e1d993cThanks @posthog! - Guard the replayer's hover handling against non-element and detached hover targets, which previously threw an unhandledTypeError(querySelectorAllon a node without that method) and stopped session recording playback mid-stream. (2026-08-21) -
#4557
4451274Thanks @posthog! - 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.6
Patch Changes
-
#4578
bae46bfThanks @marandaneto! - Drop events when a before-send hook throws instead of sending the unmodified event. (2026-08-20) -
#4582
aef2f49Thanks @ablaszkiewicz! - Stop building a stack frame for awindow.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) -
Updated dependencies [
bae46bf,aef2f49]:- @posthog/core@1.48.6
1.418.5
Patch Changes
- #4572
9701637Thanks @ablaszkiewicz! - Stop counting Chromium<anonymous>stack frames (extension-injected, devtools or string-evaluated code) as in-app code. (2026-08-19) - Updated dependencies [
9701637]:- @posthog/core@1.48.5
1.418.4
Patch Changes
- #4309
b564d61Thanks @posthog! - Fix 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
Patch Changes
- #4558
3f9ba71Thanks @posthog! - Fall back to the synthetic exception stack when a capturedErrorhas 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) - Updated dependencies [
3f9ba71]:- @posthog/core@1.48.4
1.418.2
Patch Changes
-
#4555
3e0edffThanks @HaynesPostHog! - Fix 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
Patch Changes
- #4549
0599fe0Thanks @ablaszkiewicz! - Recognise Firefox and Safari extension frames when filtering extension exceptions, and stop counting Safari's maskedwebkit-masked-url://frames as in-app code. (2026-08-18) - Updated dependencies [
0599fe0]:- @posthog/core@1.48.3
1.418.0
Minor Changes
- #4496
1ade666Thanks @marandaneto! - AddcookieWinsOnConflictto 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)
Patch Changes
- Updated dependencies [
1ade666]:- @posthog/types@1.405.0
1.417.3
Patch Changes
- #4540
ce8fc13Thanks @marandaneto! - Restore exception autocapture compatibility for posthog-js clients through version 1.141.0. (2026-08-17)
1.417.2
Patch Changes
- #4413
7b61aa4Thanks @posthog! - 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) - Updated dependencies [
7b61aa4]:- @posthog/core@1.48.2
1.417.1
Patch Changes
-
#4521
0a0206fThanks @marandaneto! - Normalize capture timestamp overrides to equivalent UTC ISO strings in the browser and Node.js SDKs and shared core. (2026-08-14) -
#4523
6230b5bThanks @marandaneto! - Prevent swallowed rrweb observer initialization errors from breaking session replay teardown and subsequent recorder restarts. (2026-08-14) -
#4503
eb05237Thanks @pauldambra! - fix(dead-clicks): treat visibility and focus changes as liveness signals, not dead-click evidenceThe 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)
- Visibility changes are recorded in both directions (a click that opens a new tab sends the current tab to
-
Updated dependencies [
0a0206f,eb05237]:- @posthog/core@1.48.1
- @posthog/types@1.404.1
1.417.0
Minor Changes
- #4485
8bc63c3Thanks @dustinbyrne! - Default external dependency loading to versioned asset paths with automatic fallback to legacy paths, and add astrict_script_versioning: 'fallback'mode. (2026-08-13)
Patch Changes
- Updated dependencies [
8bc63c3]:- @posthog/types@1.404.0
1.416.1
Patch Changes
-
#4443
b2c6830Thanks @arnohillen! - 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)
- 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
-
Updated dependencies [
c9086de,b2c6830]:- @posthog/core@1.48.0
- @posthog/types@1.403.1
1.416.0
Minor Changes
-
#4495
e4b9947Thanks @marandaneto! - feat(browser): addrewriteRequestPathto customize API, feature flag, and asset paths for reverse proxies (2026-08-12) -
#4493
e34ebf9Thanks @marandaneto! - Add reset options for applying bootstrapped identity, feature flag, and session values afterposthog.reset()while preserving the legacy boolean argument. (2026-08-12)
Patch Changes
1.415.7
Patch Changes
- #4318
847d963Thanks @dustinbyrne! - Migrate 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
Patch Changes
-
#4500
d773405Thanks @ksvat! - Fix 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
Patch Changes
-
#4497
d62e42eThanks @hpouillot! - Fix 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
Patch Changes
- #4494
deb6bb0Thanks @marandaneto! - fix(types): accept current and legacy Segment Analytics SDK types in the Segment integration config (2026-08-11) - Updated dependencies [
deb6bb0]:- @posthog/types@1.402.3
1.415.3
Patch Changes
-
#4488
23db844Thanks @TueHaulund! - fix(replay): never ship a buffer swapped in by a re-entrant session rotation mid-flush (2026-08-11) -
#4474
e06bf52Thanks @dependabot! - dependencies updates: - Updated dependencydompurify@^3.4.13↗︎ (from^3.4.12, independencies) (2026-08-11) -
#4435
1cbbe6aThanks @arnohillen! - fix(replay): stop dropping adopted stylesheets that arrive before the host's shadow root is attached. When the recorder's full snapshot races a web component's hydration, the AdoptedStyleSheet event can be recorded before the mutation that attaches the host's shadow root. The replayer silently dropped those styles for the rest of the page view, so components styled viashadowRoot.adoptedStyleSheets(Stencil, Lit) rendered completely unstyled. The replayer now constructs the stylesheet even when the shadow root does not exist yet and keeps retrying adoption until it is attached. (2026-08-11)
1.415.2
Patch Changes
- #4316
f999394Thanks @dustinbyrne! - Support removing multiple persisted properties in one operation. (2026-08-11) - Updated dependencies [
f999394]:- @posthog/browser-common@0.5.0
1.415.1
Patch Changes
- #4477
6f9adf8Thanks @TueHaulund! - fix(replay): don't open a recording that holds only idle lifecycle markers (2026-08-10)
1.415.0
Minor Changes
-
#4436
80f15a3Thanks @jakesciotto! - feat(surveys): optional intro screen shown before the first questionSurveys can now display an intro screen before question 1, configured via the new
displayIntroScreen,introScreenHeader,introScreenDescription,introScreenDescriptionContentType, andintroScreenButtonTextappearance fields. The intro is dismissed with a button and records no response, does not affect completion or partial-response metrics, does not re-fire "survey shown", and is skipped when a survey is resumed with answers in progress. Intro copy is translatable like the thank-you message.renderSurveysPreviewacceptspreviewPageIndex: -1(exported asINTRO_SCREEN_PREVIEW_INDEX) to preview the intro screen. (2026-08-10)
Patch Changes
- Updated dependencies [
80f15a3]:- @posthog/core@1.47.0
1.414.0
Minor Changes
- #4330
5bd8b83Thanks @darkopia! - Addposthog.conversations.getUnavailableReason()to expose why the conversations API is unavailable (bundle blocked/failed to load, disabled in project, remote config pending/failed, still initializing, …) instead of collapsing every case intoisAvailable() === false. Lets callers that fall back to another channel record the specific cause.ConversationsUnavailableReasonis exported from the package entry points, so consumers can name the type. (2026-08-07)
1.413.3
Patch Changes
-
#4414
1b88c2fThanks @marandaneto! - Clear properties registered for a session when the PostHog session rotates. (2026-08-06) -
#4374
b39b577Thanks @dustinbyrne! - Persist in-place object and array mutations when properties are re-registered. (2026-08-06) -
#4434
75fb719Thanks @arnohillen! - Make the session replay attribute masking options mutually exclusive: when bothmaskAllElementAttributesandmaskAttributeFnare set, the coarse option wins and the callback is ignored (with a console warning), so a callback can no longer accidentally unmask whatmaskAllElementAttributeshides. (2026-08-06) -
Updated dependencies [
64ba193,75fb719]:- @posthog/core@1.46.9
- @posthog/types@1.402.2
1.413.1
Patch Changes
-
#4390
1160403Thanks @posthog! - Contain and log recorder-owned callback failures while preserving exceptions from patched native host APIs. Keep recording mutations from adopted cross-realm nodes. (2026-08-05) -
#4286
d108d66Thanks @posthog! - fix(replay): preserve privacy masking for initial network metadataInitial navigation and performance-timing entries are now passed through
maskCapturedNetworkRequestFn, including when they have no method. URL rewrites are respected. When the callback returns nullish for an initial entry, replay-required timing metadata is retained without its URL, headers, or body so method-gated callbacks do not drop the metadata or expose deliberately filtered customer data. Derived server-timing entries are also suppressed when this strict fallback is used. Enforced PostHog filtering and payload cleaning still run first. (2026-08-05) -
Updated dependencies [
d108d66]:- @posthog/types@1.402.1
1.413.0
Minor Changes
- #4376
2da12b8Thanks @posthog! - Add attribute-level masking to session replay:maskAttributeFnprovides per-attribute control over the final serialized value, whilemaskAllElementAttributesmasks all source DOM string attributes (including rendering attributes and synthesized form values) at the cost of replay fidelity. (2026-08-05)
Patch Changes
1.412.2
Patch Changes
- #4417
3acadfeThanks @marandaneto! - fix(replay): discard held interaction-less recordings when a background document unloads without ever becoming visible (2026-08-05)
1.412.1
Patch Changes
- #4404
a348fb3Thanks @dependabot! - Update PostCSS to include upstream security fixes. (2026-08-05)
1.412.0
Minor Changes
-
#4320
837363eThanks @posthog! - Bound the main-thread cost of the recorder's initial full snapshot, and start measuring it.stringifyStylesheetreadscssTextfor every CSSRule of every stylesheet, all inside the one uninterruptible task that takes the full snapshot. On CSS-heavy pages that is the dominant cost, and it has been observed freezing the UI (no rendering, scrolling, or cursor movement) for seconds. The existingmaxDepthguard doesn't help, since it only bounds deep DOMs, not wide ones or heavy CSS.Stylesheet inlining now stops after a budget of CSSRules per snapshot (
session_recording.inlineStylesheetBudgetRules, default 10,000; set0for the previous unbounded behaviour). Sheets past the budget are serialized without_cssText, keepingrel/hrefso replay can load them remotely, and are then inlined one per idle callback and delivered as attribute mutations. Replay fidelity is preserved; the work is just no longer one long blocking task.The snapshot's cost is also now measured and reported on captured events, so slow snapshots are visible without a browser profile:
$sdk_debug_replay_slowest_full_snapshot_ms,$sdk_debug_replay_slowest_full_snapshot_stylesheet_ms,$sdk_debug_replay_slowest_full_snapshot_nodes,$sdk_debug_replay_slowest_full_snapshot_css_rules,$sdk_debug_replay_deferred_stylesheets, and, for the incremental path,$sdk_debug_replay_slowest_mutation_batch_ms. (2026-08-05)
1.411.0
Minor Changes
-
#4266
43d1850Thanks @posthog! - feat: add opt-incapture_performance.__preview_web_vitals_soft_navsto fix inflated web vitals on single-page appsClient-side route changes in SPAs previously left web vitals (LCP especially) accumulating against the original hard-navigation timestamp, inflating the top tail of Core Web Vitals. Setting
capture_performance: { __preview_web_vitals_soft_navs: true }now scopes metrics to the browser's Soft Navigation entries so each route change starts a fresh measurement window. It's a preview option because it relies on Chrome's experimental Soft Navigation Detection API and loads pinned stable web-vitals 6.x callbacks; when disabled (the default), the existing web-vitals 5.x behavior remains unchanged. (2026-08-04)
Patch Changes
- #4287
d3c4538Thanks @posthog! - Keep$referring_domainand canonicalutm_*/campaign parameters on minimal$feature_flag_calledevents. Previously the minimal allowlist stripped every campaign parameter, so a flag-called event landing first in a session could set the session's UTM attribution and channel type to NULL in web analytics. (2026-08-04) - Updated dependencies [
d3c4538,43d1850]:- @posthog/core@1.46.7
- @posthog/types@1.401.0
1.410.10
Patch Changes
-
#4271
3d4e2fdThanks @felipeatom! - Fix inline surveys rendering an empty container when a stale persisted question index (left over from a prior completion) points past the last question. When the persisted index is out of range the whole in-progress record is now discarded and the survey starts fresh, instead of clamping the index while keeping the equally-stale responses and visited indices. Restored visited indices are also filtered to valid questions so the Back button can never navigate to a non-existent question and re-empty the container. (2026-08-04) -
#4412
5f2b78aThanks @TueHaulund! - fix(replay): hold fresh interaction-less session recordings until there is evidence someone caresA tab that loads but never sees any user interaction (prefetched pages, background tabs, in-app browser preloads) no longer ships a billable recording while it sits untouched. Like rotation-born sessions, a fresh recording epoch is held until there is evidence someone cares about it: a user interaction, an event trigger match, or an explicit override (
posthog.startSessionRecording(...)) releases the hold and ships the buffer on the normal flush cadence, so released recordings are playable from the session's start. A clean unload also ships a fresh-start hold, so passive visits (reading, watching a video) are still captured exactly as before; rotation-born holds are discarded on unload as before. A held buffer that reaches the size cap is dropped to bound memory, and a later release takes a fresh full snapshot so the recording resumes playable. (2026-08-04) -
#4410
064874aThanks @ioannisj! - Fix held rotation-born session replay buffers not flushing when a V2 event trigger matches (2026-08-04) -
#4343
83a9b67Thanks @arnohillen! - Session replay no longer freezes the page re-encoding base64 images that are already small. When canvas recording is enabled, every<img>with adata:URL was synchronously redrawn and re-encoded throughcanvas.toDataURLduring full snapshots and attribute mutations. The encode cost scales with pixel dimensions, not payload size, so a page of base64 lazy-load placeholders (measured: 18 images of 4096x3072 at ~33KB each) blocked the main thread for 7+ seconds to produce outputs that were larger than the inputs. Recompression now skips data URLs under 100KB (where it cannot save meaningful payload), keeps the original when the re-encoded output is not smaller, and memoizes by input so repeated snapshots and src-swapping mutations never pay for the same image twice. Genuinely large base64 images are still recompressed as before. (2026-08-04) -
#4339
f865818Thanks @posthog! - Report privacy-aware dropped-event count, page and session context in the client rate limit warning (2026-08-04) -
Updated dependencies [
f865818]:- @posthog/types@1.400.2
1.410.9
Patch Changes
-
#4314
feb9e2aThanks @posthog! - fix: warn whenreset()silently opts the user back outreset()clears stored consent along with the rest of the user's state. Withopt_out_capturing_by_default, this returns the instance to the opted-out default, so callingreset()afteropt_in_capturing()would stop capturing without warning. It now logs a warning when that happens and documents the required ordering. (2026-08-04) -
#4288
877418eThanks @posthog! - Fix event-triggered survey popup delays resetting on every page navigation. The popup delay now resumes from when the trigger fired (persisted for the session) instead of restarting a fresh countdown on each page load, so a survey configured with an event/action trigger and a popup delay no longer gets lost when the user navigates before the delay elapses. (2026-08-04) -
Updated dependencies [
feb9e2a]:- @posthog/types@1.400.1
1.410.7
Patch Changes
- #4400
9811a43Thanks @marandaneto! - Avoid promoting handled transport failures to error logs in surveys, product tours, remote config, conversations, and logs while preserving error severity for HTTP and unexpected failures. (2026-08-04)
1.410.6
Patch Changes
- #4407
6d5e314Thanks @ioannisj! - Fix session replay shipping one billable recording per session rotation for tabs the user never interacts with. A session born from an idle rotation now holds its buffer until the first user interaction, then ships a recording playable from the session's start; without interaction nothing is sent — a further rotation, stop, opt-out, or page unload discards the held data instead of shipping it. An event trigger match (for example record-on-exception) also releases the hold, since it is explicit intent to record the session. (2026-08-03)
1.410.5
Patch Changes
- #4273
8ec3499Thanks @felipeatom! - Fix selector-widget surveys being abruptly removed while open when their trigger element is unmounted from the DOM (e.g. a dropdown or menu that hosts the trigger closes). The survey is now kept in place while open and only torn down once the user has closed it. Also fixes a related leak where, if the selector resolved to a different element while the survey was open, the old element's click listener was never removed and kept dispatching the show-widget event for the lifetime of the page. (2026-08-03)
1.410.4
Patch Changes
- #4235
7db0e8cThanks @hpouillot! - Preserve messages, source locations, and existing stacks from browser errors that do not provide a same-realmErrorobject. (2026-08-03) - Updated dependencies [
7db0e8c]:- @posthog/core@1.46.5
1.410.3
Patch Changes
- #4399
662fb4cThanks @christiaan-ph! - Conversations widget: bullet and numbered lists in a support reply now keep their markers on host pages with an aggressive CSS reset (for example Tailwind preflight'sol, ul { list-style: none }). The widget renders into the host page's DOM, so the list style is now set inline on<ul>,<ol>, and<li>rather than left to the page's own styles. (2026-08-03)
1.410.2
Patch Changes
-
#4334
bd93230Thanks @posthog! - Conversations widget: treat a network-level message send failure (ad blocker, offline, CORS, page teardown) as transient — the widget now shows a "check your connection" message and logs atwarninstead oferror, so these benign failures no longer show up as captured exceptions in error tracking. (2026-08-03) -
#4341
d68e607Thanks @posthog! - Prevent duplicate snippet loaders from replacing an initialized instance or replaying queued calls more than once, and warn with actionable guidance wheninit()is called again with a different project token (2026-08-03)
1.410.1
Patch Changes
- #4386
0854095Thanks @marandaneto! - Prevent the inline canvas recording worker from requesting an unusable source map from its blob URL. (2026-08-03) - Updated dependencies [
eb0a793]:- @posthog/core@1.46.3
1.410.0
Minor Changes
- #4125
fde7145Thanks @DerGeraetK! - Addsession_recording.samplingto disable or throttle mousemove capture (and optionally mouseInteraction) in session replay. Canvas recording now merges its canvas sampling with user-provided sampling instead of overwriting it. (2026-08-03)
Patch Changes
1.409.6
Patch Changes
- #4299
8a7bb3fThanks @posthog! - Mark our bundles as third-party code in the source maps we publish (thex_google_ignoreListextension). Browser devtools now attributeconsole.*messages to the code that called them instead of to posthog-js's console wrapper, which previously showed every message as coming fromlogs.tswhencaptureConsoleLogsor session replay'senable_recording_console_logwas enabled. (2026-08-03) - Updated dependencies [
7c3a9af]:- @posthog/core@1.46.2
1.409.5
Patch Changes
- #4354
6c500f1Thanks @ablaszkiewicz! - Fail open when an error tracking suppression rule cannot be evaluated, so an unknown operator or a key outside$exception_types/$exception_valuesno longer drops the exception. (2026-07-31)
1.409.4
Patch Changes
- #4338
c458807Thanks @turnipdabeets! - Fix canvases staying blank after seeking in session replay by re-sending one frame per canvas after each full snapshot (2026-07-31)
1.409.3
Patch Changes
1.409.2
Patch Changes
- #4340
4b8867cThanks @marandaneto! - Avoid redacting session replay network bodies when timestamps or UUID fragments resemble social security or credit card numbers. (2026-07-31) - Updated dependencies [
4b8867c]:- @posthog/browser-common@0.3.1
1.409.1
Patch Changes
- #4301
4b36c44Thanks @dustinbyrne! - Add the browser-v1 client adapter for shared extensions, including analytics, request, persistence, replayed remote-config outcomes, and synchronous best-effort cleanup. (2026-07-31) - Updated dependencies [
6b48a59]:- @posthog/browser-common@0.3.0
1.409.0
Minor Changes
- #4308
6e7f3aeThanks @ablaszkiewicz! - Emit the release id that posthog-cli injects into your bundle as$release_idon$exceptionevents, so PostHog can attach exceptions to a release without joining through symbol sets. AddsgetInjectedReleaseId()to@posthog/core. The property is only attached when an injected release id can be read. (2026-07-30)
Patch Changes
- Updated dependencies [
6e7f3ae]:- @posthog/core@1.46.0
1.408.3
Patch Changes
-
#4327
232b06aThanks @github-actions! - Refresh campaign parameters after SPA URL changes. (2026-07-30) -
#4328
95a3d02Thanks @marandaneto! - Fixidentify()creating a person profile when the supplied ID already matches an anonymously persisted distinct ID. (2026-07-30)
1.408.2
Patch Changes
- #4325
3bd8a2dThanks @marandaneto! - Fix dead-click false positives on WebKit when the SDK uses an iframe-sourced MutationObserver fallback. (2026-07-30) - Updated dependencies [
3bd8a2d]:- @posthog/browser-common@0.2.5
- @posthog/core@1.45.3
1.408.1
Patch Changes
- #4226
3b02a78Thanks @ksvat! - The replayer can now yield to the event loop while fast-forwarding to a seek target, via the new opt-inseekYieldBudgetMsplayer config. Seeking in a long, event-dense recording rebuilds the target frame by re-applying every event since the last full snapshot in one uninterrupted main-thread pass, which can block the page for many seconds and trigger the browser's "Page Unresponsive" dialog; when a yield budget is set, the rebuild runs in time-budgeted chunks instead, and a newer seek cancels any rebuild still in flight so rapid scrubbing only pays for the last seek. A superseded rebuild also resets the machine'slastPlayedEventso the next seek performs a full rebuild rather than trusting a partially-applied history. The default (0) keeps the previous fully-synchronous behavior. (2026-07-30)
1.408.0
Minor Changes
-
#4270
92427a1Thanks @turnipdabeets! - Add canvas mask regions to session replay canvas capture:session_recording.canvasCapture.maskRegionsFnis called once per canvas per captured frame, and the returned regions (CSS pixels, relative to the canvas) are painted black in the captured frame before it is encoded — letting apps that render into canvas (e.g. Flutter web via CanvasKit) mask content that DOM-based masking cannot see.The return value decides what happens to that canvas's frame:
[]— nothing to mask; the frame is recorded as is.null— regions could not be computed; the frame is skipped rather than recorded unmasked.maskRegionsFnnot set — canvases are recorded unmasked and canvas capture behavior is unchanged.
Configuring
maskRegionsFnalso disables canvas pixel serialization in DOM full snapshots (rr_dataURL) — that path never sees the mask regions, so skipping it closes the route that could otherwise embed unmasked canvas stills in a snapshot; the canvas repaints from the masked frame stream instead. Every canvas the provider answers — with regions or[]— re-sends an unchanged frame as a keyframe every 30s, so after a full snapshot or a seek an idle canvas repaints within at most 30s.An app whose real provider only exists once its runtime has booted chooses what happens in between by what it declares in
posthog.init: a function covering the whole canvas blacks those frames out,() => nullskips them, and declaring nothing records them. Client-side only, cannot be set via remote configuration. (2026-07-29)
Patch Changes
- Updated dependencies [
92427a1]:- @posthog/types@1.399.0
1.407.8
Patch Changes
-
#4311
c1818e2Thanks @marandaneto! - fix(react): restore CommonJS default import interop in UMD bundlesReact hooks used without a
PostHogProvidernow receive the default PostHog instance again when the UMD build is loaded through CommonJS. (2026-07-29)
1.407.7
Patch Changes
-
#4304
c7099e9Thanks @lucasheriques! - fix(surveys): only wait for feature flags on surveys that repeatSurveys stopped being shown while feature flags were still loading, even when a cached enabled value for their internal targeting flag was already available. Popover and widget surveys recovered on the next evaluation, but a survey your own code renders (type
api) is evaluated once, so it was dropped for that page load and never reappeared.That wait is only needed for surveys that repeat, where stored per-survey state is keyed by iteration and cannot be relied on to record that someone already answered. Other surveys keep one stable key that already prevents a repeat display, so they are now evaluated against the cached flag right away. (2026-07-29)
-
Updated dependencies [
c7099e9]:- @posthog/core@1.45.2
1.407.6
Patch Changes
- #4305
b4250a7Thanks @marandaneto! - Fix extension bundles when used with the slim no-external browser build. (2026-07-29)
1.407.5
Patch Changes
- #4278
a19ba65Thanks @marandaneto! - Fix paused replay seeks at an exact full snapshot timestamp so the snapshot frame is rebuilt before playback pauses. (2026-07-28)
1.407.4
Patch Changes
- #4290
a08c226Thanks @marandaneto! - Send session recording request timestamps in request bodies instead of query strings. (2026-07-28)
1.407.3
Patch Changes
-
#4214
f7399a0Thanks @felipeatom! - FixcanRenderSurvey/canRenderSurveyAsyncreporting a survey as renderable before its event/action activation trigger has fired. Surveys gated on a "User sends events" filter are now only eligible once the trigger event is received. (2026-07-27) -
#4231
eabe2efThanks @marandaneto! - Send analytics request timestamps in capture bodies while retaining query timestamps for session recordings. (2026-07-27) -
#4102
fa4844bThanks @marandaneto! - Send SDK library identity in feature flag person properties instead of URL query parameters. (2026-07-27) -
#4220
11330b3Thanks @SegFaultZero! - fix(replay): prevent server timings from dropped ingestion requests causing an endless capture loop (2026-07-27) -
Updated dependencies [
7210789]:- @posthog/browser-common@0.2.2
1.407.2
Patch Changes
- #4224
ba7042bThanks @turnipdabeets! - Fix session replay recordings being unplayable after the session rotated in a tab with no user interaction. When a session expired and rotated (for example in a long-lived background tab), a recorder that had not yet seen user interaction kept attributing snapshots — including full snapshots — to the previous session, so the new session never received a playable full snapshot. The recorder now restarts on rotation in this state, re-syncs its session id from the session manager if they ever diverge, and flushes its buffer on the normal cadence before the first user interaction instead of holding data until the next rotation or page unload. (2026-07-23)
1.407.1
Patch Changes
- #4218
33f0bd7Thanks @marandaneto! - Send ISO feature flag timestamps in request bodies, use numericsent_atquery timestamps for capture POSTs, and preserve_cache busting for dynamic GET requests. (2026-07-23)
1.407.0
Minor Changes
-
#4222
0f2407bThanks @turnipdabeets! - feat: add a default-value option toisFeatureEnabledisFeatureEnabled(key, { defaultValue: false })now returns the given default when the flag has no value — flags not loaded yet, or no flag with that key — and the return type narrows toboolean. The option name is the same in posthog-js, posthog-js-lite, and posthog-react-native. WithoutdefaultValue, behavior is unchanged:boolean | undefined. (2026-07-22)
Patch Changes
-
#4203
90e7483Thanks @posthog! - fix(conversations): let users start a new conversation while a ticket is still openThe support widget now surfaces the ticket list navigation (and its "New conversation" button) whenever the user has any ticket, instead of only when they have multiple tickets or a single resolved one. Previously a user sitting on one open, unresolved ticket was locked into that conversation with no way to raise a second issue. (2026-07-22)
-
#4221
da6e082Thanks @posthog! - fix(exception-autocapture): don't throw when the page's onerror handler is non-callableThe wrapped
window.onerror,window.onunhandledrejection, andconsole.errorhandlers chained to the page's original handler using optional chaining, which only guards againstnull/undefined. When a page had one of these set to a truthy non-callable value (e.g. viaObject.defineProperty, or clobbered by another script/extension), our wrapper threw aTypeErrorfrom inside its own handler. We now check the original handler is actually callable before invoking it and fall back tofalseotherwise. (2026-07-22) -
#4209
569fc62Thanks @posthog! - Session recording no longer emits an uncaughtTypeError: Illegal invocationfrom the input observer's synchronous native-setter call. The previous fix only guarded the deferred hooked setter; the synchronousoriginal.set.call(this, value)still ran with a non-nativethis(a proxy, custom element, or cross-realm object) and threw inside the host page's own assignment. The recorder now probes the native getter — which fails the same internal-slot brand check as the setter — before forwarding: a non-nativethisis skipped, so the recorder no longer re-throws from its own frame, while genuine elements (including file inputs that legitimately throw on a programmatic value) keep their native behavior. The input event handler andgetInputTypeare similarly guarded against reading native accessors on a non-nativethis. (2026-07-22) -
#4068
d5e1188Thanks @posthog! - Fix event-triggered surveys re-displaying in a fresh session without their trigger firing. A non-repeatable event/action-triggered survey that was shown but never dismissed or answered had its activation persisted indefinitely, so it kept being treated as "triggered" on later page loads. The persisted activation is now scoped to the triggering session: it still survives a reload within that session, but a brand-new session drops it until the trigger fires again. Repeatable surveys are unaffected. (2026-07-22) -
#4205
de3ad61Thanks @posthog! - Warn when session recording masking options inposthog.initshadow the project-level "Privacy and masking" setting. Client-side masking still intentionally takes precedence, but previously the override was silent — a developer could set masking in the dashboard and see it quietly ignored because their SDK config diverged. The recorder now logs a console warning (in debug mode) naming the diverging fields so the precedence is self-explaining. (2026-07-22) -
Updated dependencies [
0f2407b]:- @posthog/core@1.45.0
- @posthog/types@1.398.0
1.406.2
Patch Changes
-
#4206
a3112d9Thanks @posthog! - fix(surveys): stop recurring surveys re-showing off a stale internal targeting flagRecurring surveys could re-display and record a duplicate response when the eligibility check ran against a cached internal targeting flag before fresh flags had loaded. The display loop now waits for feature flags to actually load before trusting the internal targeting flag, and forces a flag reload after a survey is completed so the flag recomputes promptly. (2026-07-21)
1.406.1
Patch Changes
- #4127
220fa2cThanks @sarmah-rup! - Don't let save_referrer overwrite a $referrer / $referring_domain that was explicitly set via posthog.register(), so registered attribution values survive pageviews in SPA and iframe contexts (2026-07-21)
1.406.0
Minor Changes
- #4194
d39b903Thanks @dustinbyrne! - Move shared browser utility implementations into@posthog/browser-commonand consume them directly fromposthog-js. (2026-07-21)
Patch Changes
- #4204
ba977d0Thanks @turnipdabeets! - Keep autocapture off when a remote config response omitsautocapture_opt_out. The SDK now retains the last known server value for the missing-field case, the same as when the config fetch fails, instead of enabling autocapture. Values persisted by earlier SDK versions are still trusted; a browser holding a stale value corrects itself on the first config response that includes the field. (2026-07-21) - Updated dependencies [
d39b903]:- @posthog/browser-common@0.2.0
1.405.3
Patch Changes
- #4200
91505baThanks @pauldambra! - fix: apply the active full snapshot interval as soon as a recording trigger matches (2026-07-21)
1.405.2
Patch Changes
- #4198
fbfc84fThanks @pauldambra! - feat: make the pending session recording trigger buffer interval configurable (2026-07-20) - Updated dependencies [
fbfc84f]:- @posthog/types@1.397.1
1.405.1
Patch Changes
- #4193
dec8fe7Thanks @turnipdabeets! - Internal restructuring of remote config failure handling across SDK extensions; no behavior change. (2026-07-20)
1.405.0
Minor Changes
-
#4172
9621830Thanks @haacked! - send minimal$feature_flag_calledevents when the server enables itWhen the v2
/flagsresponse carriesminimalFlagCalledEvents: true(or, for posthog-node local evaluation, the flag-definitions payload carriesminimal_flag_called_events: true) and the evaluated flag is not linked to an experiment ($feature_flag_has_experiment === false),$feature_flag_calledevents are rebuilt from a strict allowlist of flag-evaluation, processing-control, and SDK-identity properties. Super properties,$set/$set_once, the$feature/<key>enumeration,$active_feature_flags, and the context envelope are stripped. Any missing signal (no gate on the response, bootstrapped or locally injected flags,has_experimentunknown) falls back to the full event, and experiment-linked flags always send the full envelope. The gate is stored alongside the cached flags (posthog-js persistence, posthog-node poller state) and is server-controlled, with no SDK-side configuration.before_sendruns after the filter and may re-add stripped properties. (2026-07-20)
Patch Changes
- Updated dependencies [
9621830]:- @posthog/core@1.44.0
1.404.1
Patch Changes
- #4191
66c1666Thanks @turnipdabeets! - Honour the project-level autocapture opt-out when the remote config request fails. Previously a failed config fetch (network error, timeout, blocked request) enabled autocapture on opted-out projects and persisted that state for later page loads. Autocapture now keeps the last successfully received server value, and stays off until the first successful config response. (2026-07-17)
1.404.0
Minor Changes
- #4149
607bf54Thanks @pauldambra! - Add dead swipe detection to dead clicks autocapture. When dead clicks autocapture is enabled, touch swipe gestures that produce no observable screen change (no scroll, mutation, selection or visibility change) are now captured as$dead_swipeevents, surfacing failed navigations on touch devices. Configurable viacapture_dead_swipes(defaulttrue) andswipe_threshold_px(default30) on thecapture_dead_clicksconfig. Swipes over surfaces whose response cannot be observed (canvas, video and other media elements under the finger) are skipped, and captures are limited per page load viamax_dead_swipes_per_page_load(default10). (2026-07-16)
Patch Changes
- #4171
df17ddcThanks @posthog! - Catch synchronous throws from a monkey-patchedwindow.fetchso they no longer escape as unhandled exceptions. A synchronous throw is now routed through the same handling as an async rejection, so the request queue retries instead of the error leaking into error tracking. (2026-07-16) - Updated dependencies [
607bf54]:- @posthog/types@1.397.0
1.403.0
Minor Changes
-
#4159
fad6d9aThanks @haacked! - add$feature_flag_has_experimentto$feature_flag_calledevents$feature_flag_calledevents now carry a$feature_flag_has_experimentboolean sourced from the server'shas_experimentflag metadata (the/flags?v=2response for remote evaluation, the/api/feature_flag/local_evaluationdefinitions for posthog-node local evaluation). The property is only sent when the server explicitly reportshas_experiment; it is omitted entirely when the value is unknown (older servers, missing metadata, bootstrapped or locally injected flags). (2026-07-16)
Patch Changes
- Updated dependencies [
fad6d9a]:- @posthog/core@1.43.0
- @posthog/types@1.396.0
1.402.3
Patch Changes
-
#4157
4a2ecf5Thanks @posthog! - Session recording no longer emits an uncaughtNotAllowedError("Sharing constructed stylesheets in multiple documents is not allowed") when a page assigns aCSSStyleSheetconstructed in a different document toadoptedStyleSheets. That assignment is the host page's own invalid operation, but the recorder's patched setter sat on the call stack, so the exception was attributed to rrweb and churned fingerprints in error tracking. The recorder now contains this specific rejection (matched by its standardizedNotAllowedErrorname, so it works even when the setter throws from an iframe realm) and skips recording those sheets, while still re-throwing any other native-setter error so host-page behaviour is preserved. (2026-07-15) -
#4158
0dc389eThanks @posthog! - fix(replay): session recording no longer throwsTypeError: Converting circular structure to JSONwhen replay event data contains a circular reference. The circular-reference guard now also detects cycles that pass through an array, and affected events are captured with[Circular]markers instead of surfacing an unhandled error and being dropped. (2026-07-15) -
Updated dependencies [
fc2cb2e]:- @posthog/core@1.42.1
1.402.2
Patch Changes
- #4151
81adbfdThanks @posthog! - Session recording no longer emits an uncaughtTypeError: Illegal invocationwhen a programmatic input-value change happens on an object that is not a genuine native input element (for example a proxy on the element prototype chain). The recorder drops that one replay update instead of throwing. (2026-07-15)
1.402.1
Patch Changes
-
#4117
1eddff7Thanks @DanielVisca! - add the posthog.metrics API (count, gauge, histogram) to posthog-node — alphaBackend services can now record metrics through the same statsd-style pre-aggregating client the browser SDK ships, with no OpenTelemetry setup:
const client = new PostHog('phc_...', { metrics: { serviceName: 'billing-worker' } }) client.metrics.count('invoices.processed', 1, { attributes: { plan: 'pro' } }) client.metrics.gauge('queue.depth', 42) client.metrics.histogram('job.duration', 187, { unit: 'ms' })Samples aggregate in memory and flush as OTLP/JSON to
/i/v1/metrics(one data point per series per window). Pending metrics are flushed onshutdown(). Core gains_sendMetricsBatchonPostHogCoreStateless(same outcome contract as_sendLogsBatch) and a sharedresolveMetricsConfig, so any core-based SDK can hostPostHogMetrics. (2026-07-15) -
Updated dependencies [
1eddff7]:- @posthog/core@1.42.0
1.402.0
Minor Changes
- #4143
0e8ad14Thanks @robbie-c! - Stamp the current hostname as$snapshot_hoston every$snapshotevent the session recorder sends. The value is derived from the page URL after it passes through the existing replay URL masking pipeline (maskCapturedNetworkRequestFn/ deprecatedmaskNetworkRequestFn, hash stripping, personal-data query-param masking), so it cannot bypass a customer's masking config. When masking removes the URL or the masked result doesn't parse as a URL, the property is omitted entirely. This gives ingestion consumers a per-message host signal even for mid-session snapshot batches that contain no URL-bearing events. (2026-07-15)
1.401.0
Minor Changes
- #4129
800af7cThanks @pauldambra! - feat: addsession_recording.attributeFilteroption that passes an attribute allowlist through to the native MutationObserver, so mutations to unlisted attributes (e.g. animation-driven inlinestylechurn) never cost recording CPU (port of upstream rrweb #1873) (2026-07-15)
Patch Changes
- Updated dependencies [
800af7c]:- @posthog/types@1.395.0
1.400.1
Patch Changes
- #4090
6dd8827Thanks @lucasheriques! - chore: survey seen-key and repeat-activation helpers now live in @posthog/core, shared by the web and React Native SDKs. Core's survey enums are now const-object literal unions (matching the web SDK's existing pattern), so the same values type-check across both SDKs. No behavior change. Type-level note: enum members no longer work as standalone type annotations (e.g.SurveyType.Popoveras a type); use the exported union types instead. Runtime values are unchanged. (2026-07-14) - Updated dependencies [
6dd8827]:- @posthog/core@1.41.1
1.400.0
Minor Changes
- #4101
dc2aa5bThanks @posthog! - Normalize the error tracking rate-limiter config to first-class options. The browser SDK now readsexceptionRateLimiterRefillRate/exceptionRateLimiterBucketSizeonerror_tracking, with the previous double-underscore__exceptionRateLimiterRefillRate/__exceptionRateLimiterBucketSizeoptions deprecated but still honoured as a fallback. The option shape (ExceptionRateLimiterConfig) and default-resolution logic (resolveExceptionRateLimiterConfig) now live in@posthog/coreand are shared between the browser and Node SDKs. (2026-07-14)
Patch Changes
- #4140
1eabd30Thanks @turnipdabeets! - HandlesendBeaconquota rejections instead of silently dropping events. A beacon rejected by the browser (over the page's shared ~64KiB in-flight keepalive quota) is now split in half and re-sent recursively so the batch delivers as far as the quota allows; a rejected payload that cannot be split falls back to a non-keepalive fetch and logs a warning. Previously the boolean return ofsendBeaconwas ignored and an over-quota unload batch was lost with no signal. (2026-07-14) - Updated dependencies [
dc2aa5b]:- @posthog/core@1.41.0
- @posthog/types@1.394.0
1.399.5
Patch Changes
-
#4134
ab10064Thanks @posthog! - Bound autocapture's DOM ancestor walks against abnormal host-page DOM trees.autocapturePropertiesForElementandshouldCaptureElementnow stop climbing theparentNodechain after 1000 ancestors or if they revisit a node (only possible when a page patchesparentNode, since native DOMs cannot contain cycles), instead of walking indefinitely. WhenshouldCaptureElementcannot finish checking ancestors forph-no-capture/ph-sensitive, it fails closed and reports the element as not capturable. Behavior on normal DOM trees is unchanged. (2026-07-14) -
#4141
17d956cThanks @posthog! - Log network-level fetch failures from posthog-js's own request layer (ad blocker, dropped connection, CORS, page teardown) atwarninstead oferror. The browser rejects these with a genericTypeError(Failed to fetch, Firefox'sNetworkError..., or Safari'sLoad failed); they are already caught and retried by the request queue, so they are expected noise rather than SDK errors —_fetchnow gives them the samewarntreatment as our own timeout aborts. Genuine, unexpected errors still log aterror. (2026-07-14)
1.399.4
Patch Changes
- #4139
7c339beThanks @turnipdabeets! - Encode uncompressedsendBeaconbodies as base64 form data so the beacon keeps a CORS-simple content type. Previously an uncompressed unload beacon was sent asapplication/json, which forces a CORS preflight — a preflight cannot complete while the page unloads, so on cross-origin hosts the browser silently dropped the POST and the final batch of events was lost. Compression is inactive whenever the remote config request fails (flaky network, blocked endpoint), when the config response omitssupportedCompression, or withdisable_compression: true. (2026-07-13)
1.399.3
Patch Changes
- #4133
4ebb618Thanks @mikenicholls88! - MakejsonStringifycircular-safe so event serialization never throws. Previously a captured property holding a circular value — most commonly a DOM node that retains a React fiber pointing back at the element — madeJSON.stringifythrowConverting circular structure to JSON; withcapture_exceptionsenabled that throw was recaptured as a new$exception, at times in a loop. On a throw we now fall back tosafeJsonStringifyfrom@posthog/core. The fast (non-circular) path is unchanged, and only true cycles become"[Circular]", so shared-but-acyclic references keep their real values. (2026-07-13)
1.399.2
Patch Changes
- #4118
f630394Thanks @posthog! - Fix aRangeError: Maximum call stack size exceededoriginating from the shared rrwebpatch()helper. It patches shared globals such asElement.prototype.attachShadow(shadow-dom-manager) and the DOM/canvas observers, so multiple recorder instances or repeated start/stop cycles wrap the same global more than once. Previously an out-of-order restore silently no-op'd, leaving the wrapper in the call path; repeated cycles grew the wrapper chain without bound until a real call walked a chain deep enough to overflow the stack. Wrappers now delegate through a mutable per-layer link so any layer can be torn down even when newer wrappers sit on top of it, keeping the chain bounded. Recording behavior is unchanged. This applies the same fix as #4063 (fetch/XHR) to the shared helper so every rrweb-record caller inherits the bounded-chain behavior. (2026-07-10)
1.399.1
Patch Changes
-
#4122
c915581Thanks @github-actions! - FixTypeError: handlePageUnload is not a functionthrown on page unload when a version-skewed lazy-loaded surveys chunk produces a survey manager whose prototype lackshandlePageUnload. The delegated call inPostHogSurveys.handlePageUnload()now guards the method as well as the receiver. (2026-07-09) -
#4124
562ceebThanks @posthog! - Session recording no longer crashes on startup when a CDN-loaded recorder chunk runs against an older bundled core. Calls intoSessionIdManager.on/onSessionIdare now guarded so a core without those methods degrades gracefully instead of throwing aTypeErrorduringstart(). (2026-07-09)
1.399.0
Minor Changes
-
#4115
86bb3a5Thanks @DanielVisca! - add the posthog.metrics API (count, gauge, histogram) — alphaA statsd-style pre-aggregating metrics client for the PostHog Metrics product (alpha). Samples are folded into per-series aggregates in memory (counts sum, gauges keep the last value, histograms accumulate buckets) and flushed periodically as OTLP/JSON to
/i/v1/metrics— one data point per series per flush window, no matter how many calls. No OpenTelemetry SDK setup required:posthog.metrics.count('orders_created', 1) posthog.metrics.gauge('active_connections', 42) posthog.metrics.histogram('api_latency', 187, { unit: 'ms' })Configure via
metrics: { serviceName, environment, flushIntervalMs, maxSeriesPerFlush, beforeSend, ... }. (2026-07-08)
Patch Changes
- Updated dependencies [
86bb3a5]:- @posthog/core@1.40.0
- @posthog/types@1.393.0
1.398.7
Patch Changes
-
#4113
45f17eeThanks @TueHaulund! - fix session replay leaking a shadow-root observer when a same-origin iframe is removedFollow-up to the shadow-observer iframe-teardown fix:
takeFullSnapshot'sonSerializeregisters every shadow root with the top-level document, so a root nested in a same-origin iframe was keyed to the wrong document and its observer/buffer were not disconnected when that iframe was removed (they lingered until the next full snapshot).addShadowRootnow derives the owning document from the host element, so per-document teardown matches iframe-nested roots too. (2026-07-08)
1.398.6
Patch Changes
- #4114
c75c0baThanks @hpouillot! - fix: avoid throwing when rrweb recorder cleanup cannot remove a listener (2026-07-08)
1.398.5
Patch Changes
- #4103
be8242aThanks @rafaeelaudibert! - Publish the code-split ESM toolbar bundle when the build emits one. The release tooling now recursively includesdist/toolbar/(with explicit JS content types for the strict-MIME ESM chunks) across the immutable, major-alias, and compatibility upload prefixes, and the workflow accepts the canonicaltoolbar.js/toolbar.csslayout. This is a no-op against today's single-file build. (2026-07-08)
1.398.4
Patch Changes
-
#4104
ec5e401Thanks @TueHaulund! - fix session recordings missing their initial full snapshot after an idle session-id rotationWhen the session id rotated while the recorder was idle, the restarted recorder's Meta and FullSnapshot were appended to the previous session's buffer and shipped under the old session id, leaving the new recording unplayable until the next periodic snapshot. The buffer now rebinds on any session-id change regardless of idle state, and as a safety net the recorder requests a full snapshot whenever an incremental is about to ship for a session that has not produced one. (2026-07-08)
1.398.3
Patch Changes
-
#4112
38bb185Thanks @TueHaulund! - fix session replay silently dropping shadow DOM mutations after an iframe teardownThe single shared ShadowDomManager observes every shadow root on the page, but MutationBuffer.reset() disconnected it. That reset fires whenever any one buffer is torn down, so an iframe being removed or navigating away disconnected every shadow-root observer page-wide. Shadow DOM content (for example a widget mounted in an open shadow root) then stopped recording until the next periodic full snapshot re-registered it. Buffer teardown now releases only its own resources; global shadow observation is reset by takeFullSnapshot and on recording stop. (2026-07-08)
1.398.2
Patch Changes
-
#4063
24aadd5Thanks @posthog! - Fix aRangeError: Maximum call stack size exceededthat could originate from the sharedpatch()fetch/XHR wrapper. posthog-js wrapswindow.fetchin two independent places (tracing headers and session-recording network capture), so their restores routinely ran out of order. Previously an out-of-order restore silently no-op'd, leaving the wrapper in the call path; repeated start/stop cycles grew the wrapper chain without bound until a realfetchwalked a chain deep enough to overflow the stack. Wrappers now delegate through a mutable link so any layer can be torn down even when newer wrappers sit on top of it, keeping the chain bounded. Header-injection and network-capture behavior is unchanged. (2026-07-07) -
#4100
e250a24Thanks @marandaneto! - Stop adding the gzip compression query parameter to browser SDK requests. (2026-07-07) -
#4083
f07e241Thanks @posthog! - fix(replay): harden session-replay network capture so instrumentation that throws (e.g.new Request()rejecting a URL/method) degrades gracefully and never breaks or misattributes the host application's ownxhr.open()/fetch()calls (2026-07-07)
1.398.1
Patch Changes
- #4096
5013ab6Thanks @marandaneto! - Stop sending the deprecatedverquery parameter to capture and session recording endpoints. (2026-07-07)
1.398.0
Minor Changes
- #4070
ef119bfThanks @posthog! - Add adisableAutofocussurvey appearance option. When set, open-text survey questions no longer steal focus when they render, which is useful for embedded (inline) surveys that shouldn't grab the caret or scroll the page on load. Defaults tofalse, preserving the existing autofocus behavior. (2026-07-06)
1.397.0
Minor Changes
- #4089
cc340dbThanks @bs1180! - feat(web): add aposthog-js/customizationssubpath entry point exposing the optional customizations (setAllPersonProfilePropertiesAsPersonPropertiesForFlags, thebefore-sendsampling helpers, and the redux/kea loggers) as a proper ES module with bundled types, replacing the internalposthog-js/lib/src/customizationsdeep import. Also fixes the TypeScript definitions sosetAllPersonProfilePropertiesAsPersonPropertiesForFlagsaccepts the instance passed to theloadedcallback (the documented usage), and theloadedcallback's instance type now includesconfig. (2026-07-06)
1.396.9
Patch Changes
- #4077
2595440Thanks @pauldambra! - fix(web): stop retrying log batches forever when requests die before an HTTP response (status 0, e.g. an ad blocker) — after 3 consecutive such failures while the browser reports itself online, the logs pipeline stops sending and drops batches instead of buffering and retrying for the life of the page; theonlineevent reopens it, and genuine offline periods still queue for the reconnect flush (2026-07-06)
1.396.8
Patch Changes
- #4062
2af0026Thanks @posthog! - fix(web): prevent an infinite-recursion stack overflow in the logs console capture. The console wrapper's own capture path can emit internal debug lines through PostHog's logger, which wrote back to the wrapped console and re-entered capture until the stack blew (RangeError: Maximum call stack size exceeded). The wrapper now exposes the original console method via__rrweb_original__(so the internal logger bypasses it) and guards against re-entrancy from any code that logs mid-capture. (2026-07-06)
1.396.7
Patch Changes
- #4080
08cd27bThanks @marandaneto! - fix(web): stop repeatedly hitting blocked feature flag and conversations polling endpoints after consecutive status-0 failures (2026-07-06)
1.396.6
Patch Changes
-
#4053
45d1b36Thanks @posthog! - feat(web): add a gracefulshutdown()to the browser client for parity with posthog-node, so isomorphic teardown code (e.g. the Nuxt module) that callsposthog.shutdown()on the client no longer throwsTypeError: shutdown is not a function. It best-effort flushes the queued events and always resolves. (2026-07-03) -
#4054
f0657ebThanks @posthog! - fix(web): detect our own feature-flag request timeouts via atimedOutflag instead of the abort reason, so they are logged atwarn(noterror) on browsers that don't propagatecontroller.abort(reason)— keeping benign timeouts out of error tracking's console-error capture (2026-07-03) -
#4031
94a0530Thanks @posthog! - Improve survey display reliability:- posthog-js: refresh the cached
$surveysdefinitions after a short TTL (stale-while-revalidate) so server-side changes such as switching a survey from popover to API propagate to long-lived tabs without a page reload. - posthog-js: add
posthog.surveys.markSurveyAsSeen(surveyId, { iteration })so custom integrators that render surveys through their own backend can honour the "already seen" and wait-period checks. - posthog-react-native: guarantee the survey
Modalnotifies its parent on close even when iOSModal.onDismissfails to fire, so the transparent full-screen modal can no longer stay mounted intercepting touches and freezing the app. (2026-07-03)
- posthog-js: refresh the cached
-
Updated dependencies [
45d1b36]:- @posthog/types@1.392.1
1.396.5
Patch Changes
- #4050
d7cf13bThanks @turnipdabeets! - Prevent uncaughtgetComputedStylecrashes in heatmaps and autocapture when the event target is a cross-realm element (e.g. from an iframe or synthetic event) (2026-07-02) - Updated dependencies [
5e7e132]:- @posthog/core@1.39.5
1.396.4
Patch Changes
-
#4035
18e543bThanks @posthog! - fix(web): isolateonFeatureFlagscallbacks so a throwing user handler no longer breaks the remaining callback chain or gets misattributed as an SDK error (2026-07-01) -
#4039
15bcb42Thanks @github-actions! - fix(replay): measure$snapshot_bytesas UTF-8 byte length instead of UTF-16 string length, so non-ASCII session replay payloads are counted accurately against the message size limit (2026-07-01)
1.396.3
Patch Changes
- #4020
e0ad8efThanks @posthog! - FixTypeError: ....at is not a functionthrown by the bundledweb-vitalsdependency on browsers that predateArray.prototype.at()(Chrome <92, iOS Safari <15.4). The web-vitals entrypoints now install a tinyArray.prototype.atpolyfill before web-vitals runs, so web vitals capture works again on older browsers instead of crashing with an unhandled error. (2026-06-30)
1.396.2
Patch Changes
- #4003
b6261e7Thanks @marandaneto! - Include a Promise polyfill in the IE11 bundle and avoid Promise-dependent async compression paths when Promise support is unavailable. (2026-06-29)
1.396.1
Patch Changes
- #3999
cdeae17Thanks @marandaneto! - Fall back to uncompressed browser requests when gzip encoding fails. (2026-06-29)
1.396.0
Minor Changes
- #3987
74cc6bbThanks @TueHaulund! - Add aget_current_urlconfig option that overrides the URL used for client-side URL targeting — session replay URL triggers, the session replay URL blocklist, survey URL display conditions, product tour URL conditions, web experiment URL conditions, and autocapture URL allow/ignore lists. These match againstwindow.location.hrefdirectly, which does not reflect a$current_urlrewritten inbefore_send. Apps where the browser URL is not meaningful for targeting (e.g. Electron/desktop builds served from a generated host) can now return the logical URL to match against. Defaults towindow.location.hrefwhen not set. (2026-06-29)
Patch Changes
- Updated dependencies [
74cc6bb]:- @posthog/types@1.392.0
1.395.0
Minor Changes
- #3977
6200888Thanks @turnipdabeets! - AddgetAllFeatureFlags(), which returns all currently loaded feature flags as structuredFeatureFlagResults (key,enabled,variant,payload). It is a synchronous read of the cached flags and does not send a$feature_flag_calledevent. (2026-06-26)
Patch Changes
- Updated dependencies [
6200888]:- @posthog/core@1.38.0
1.393.6
Patch Changes
- #3965
6ef9179Thanks @marandaneto! - Handle request serialization errors without throwing or blocking queued requests. (2026-06-26)
1.393.5
Patch Changes
- #3960
619d318Thanks @marandaneto! - Improve console log capture performance for truncated large objects. (2026-06-25)
1.393.4
Patch Changes
- #3942
c9c8925Thanks @hpouillot! - Fix browser console log capture when session activity timestamps are missing and refresh session attributes for each log. (2026-06-24) - Updated dependencies [
c9c8925]:- @posthog/core@1.37.2
1.393.1
Patch Changes
- #3919
99bad9cThanks @pauldambra! - Session replay network capture: add an opt-in streaming reader for request/response bodies that stops at the payload size limit instead of buffering the whole body and then discarding it — bounding memory and pre-request latency when a body is very large. It reads only a clone of the body, so it never consumes the stream the page itself reads, and always resolves (never rejects) into the page'sfetch. Off by default; enabled fordefaults: '2026-06-25'and settable directly viasession_recording.streamNetworkBody. (2026-06-24) - Updated dependencies [
99bad9c]:- @posthog/types@1.391.1
1.393.0
Minor Changes
-
#3921
c28b161Thanks @marandaneto! - Adddisable_capture_url_hashesto strip URL fragments from automatically captured URLs. It is disabled by default for backwards compatibility, and enabled automatically whenconfig.defaultsis'2026-06-25'or later. Enabling it (either explicitly or via the'2026-06-25'defaults) is a breaking behavior change for SPAs that rely on URL hashes for routing or analytics, because hash-based routes will be collapsed to the same URL without the fragment in fields such as$current_url,$initial_current_url,$session_entry_url, autocapture$elements[*].attr__href,$external_click_url, replayhrefURLs, heatmaps, web vitals$current_url, logsurl.full, conversationscurrent_url/request_url, or Next.js Pages Router$pageview$current_url.If you only want to capture some hashes, leave hash capture enabled and use
before_sendto remove or redact sensitive hash values before events are sent. (2026-06-23)
Patch Changes
- Updated dependencies [
c28b161]:- @posthog/core@1.36.0
- @posthog/types@1.391.0
1.392.0
Minor Changes
-
#3895
ce528edThanks @turnipdabeets! - Console log auto-capture (logs: { captureConsoleLogs: true }) now flows through the same pipeline asposthog.captureLog(),posthog.logger.*, and PostHog's other SDKs, instead of OpenTelemetry. As a result:- the bundled OpenTelemetry dependencies are removed, shrinking the lazily-loaded logs chunk
- auto-captured console logs now run through
logs.beforeSend(the same hook ascaptureLog/logger.*), so you can redact or drop sensitive console output before it's sent. To treat console logs differently from manual logs, branch on the record'slog.sourceattribute: auto-captured console logs set it toconsole.<method>(e.g.console.error), while manualcaptureLog/logger.*logs leave it unset - console logs now link to the person's profile: they carry the person id as
posthogDistinctId, the attribute PostHog uses to associate logs with a person (docs). The old path useddistinct_id, which isn't used for person linking by default, so console logs previously didn't appear on person profiles unless you'd configured a custom key.
Console logs keep their
posthog-browser-logsservice.name, theirconsoleinstrumentation scope, and theirlog.source: console.<level>attribute.As part of moving onto the shared pipeline, console records now use PostHog's standard log field names — the same ones programmatic web logs and other SDKs use, and the ones the Logs UI surfaces. For the fields below the values are unchanged — only the attribute names/locations differ:
distinct_id→posthogDistinctId(record attribute)location.href→url.full(record attribute; same value — the page URL)session.id(resource attribute) →sessionId(record attribute) — renamed and movedhostandwindow.idmove from resource attributes to record attributes (names unchanged)- records also now carry the standard SDK context shared by other logs, including
feature_flags
For most projects this needs no action — these are already the canonical log fields. The only thing to update is a saved Logs query or dashboard built specifically on an old console attribute name, for example:
attributes.distinct_id→attributes.posthogDistinctIdattributes.location.href→attributes.url.fullresource.attributes.session.id→attributes.sessionIdresource.attributes.host/resource.attributes.window.id→attributes.host/attributes.window.id(2026-06-22)
Patch Changes
- Updated dependencies [
ce528ed]:- @posthog/core@1.35.4
1.391.9
Patch Changes
- #3922
26aa9baThanks @posthog! - Exception autocapture: posthog-js's own fetch timeout now aborts with an explicit, descriptive reason (PostHog request timed out after <n>ms) instead of a reason-lessDOMException: AbortError: signal is aborted without reason. This keepsname === 'AbortError'so existing timeout handling (e.g. feature flag timeout detection) is unchanged, but makes our own timeouts identifiable and stops them being re-captured as noise by console-error exception autocapture. (2026-06-22)
1.391.8
Patch Changes
- #3908
1fce04fThanks @marandaneto! - Apply CSP stylesheet preparation hook to Product Tours styles. (2026-06-22)
1.391.7
Patch Changes
- #3914
dac4edbThanks @pauldambra! - Session replay network capture: redact credential-bearing headers on both request and response (previously only request), and match credential-shaped custom header names by substring (e.g.x-gist-encoded-user-token) in addition to the exact deny list - avoiding accidental capture of tokens/cookies in recordings. (2026-06-22)
1.391.6
Patch Changes
-
#3901
049eeb6Thanks @marandaneto! - Stop adding the unusedbeaconquery parameter to browser SDK sendBeacon requests. (2026-06-22) -
#3900
3ee8667Thanks @marandaneto! - Stop adding the unusedipquery parameter to browser SDK requests. (2026-06-22)
1.391.5
Patch Changes
- #3915
beaccc3Thanks @pauldambra! - Session replay: apply the existing base64 image size cap (maxBase64ImageLength) to SVG<image>elements withdata:URIs on bothhrefandxlink:href. Previously the cap only covered<img>elements, so large inline data URIs inside SVGs were recorded in full - this also covers them in mutations, replacing oversized ones with the striped placeholder. (2026-06-22)
1.391.4
Patch Changes
- #3913
ee9f2a8Thanks @pauldambra! - Session replay network capture: expand the default payload host deny list to skip third-party analytics, RUM, and session-replay telemetry whose payloads have no replay value - Datadog, Segment, RudderStack, Amplitude, Mixpanel, Hotjar (both.comand.io), and FullStory. Also covers both Google Analytics beacon hosts (google-analytics.com, plusanalytics.google.comwhich gtag uses when Google Signals is enabled) and widens New Relic tonr-data.net. (2026-06-22)
1.391.3
Patch Changes
-
#3909
ab4a220Thanks @marandaneto! - Avoidstyle-src-attrCSP violations when diffing rrweb style mutations. (2026-06-22) -
#3912
78ac40cThanks @pauldambra! - Session replay network capture: never record binary/asset response or request bodies (image, video, audio, font, octet-stream, pdf, zip, wasm) even whenrecordBodyis enabled - they bloat recordings, duplicate what the replay already shows, and the body is no longer read. (2026-06-22)
1.391.2
Patch Changes
- #3903
6b21f77Thanks @marandaneto! - Validate custom event UUID overrides and generate new UUIDs when invalid. (2026-06-19) - Updated dependencies [
6b21f77]:- @posthog/core@1.35.3
- @posthog/types@1.390.2
1.391.1
Patch Changes
-
#3899
d090a7cThanks @lucasheriques! - Surveys: re-check eligibility when a popover's display delay elapses, instead of only re-checking the URL.A survey with a display delay could be queued while a visitor was still anonymous (the targeting flag passed for the anonymous profile), and then displayed after the delay even though
identify()had reloaded feature flags and the survey's internal targeting flag was now false for the identified profile (e.g. a "show once per user" survey the person had already dismissed). The delayed display now re-runs the full display predicate (eligibility, URL/device/selector conditions, event/action trigger, and feature flags) before rendering, so a survey that became ineligible during the delay is no longer shown. Pending delayed surveys are also cancelled promptly when a later evaluation cycle finds them ineligible. (2026-06-19)
1.391.0
Minor Changes
-
#3885
5392a55Thanks @pauldambra! - feat(replay): capture canvas at reduced resolutionAdds
session_recording.canvasCapture.resolutionScale- a(0, 1]fraction of the canvas display size to capture replay frames at. The captured bitmap is downscaled (pixel-area savings are quadratic) while the canvas's true display size is still recorded, so playback stretches the smaller frame back to the correct dimensions and aspect ratio - only sharpness drops, never layout. It defaults to1(full resolution, matching today's behaviour), and the latestdefaultsbundle (2026-05-30) opts new installs into0.6.The canvas's true display size travels with each frame through the encode worker (as required message fields), so the encoded reply is always drawn back to the correct dimensions — no per-canvas state is retained on the main thread, and downscaling can never mislabel a canvas's dimensions. At full resolution the captured pixels are unchanged (the quality resampling hint is only applied when actually downscaling); the emitted
drawImagenow always uses the explicit destination-size form, which is pixel-equivalent on replay.Mechanically,
@posthog/rrweb's canvas FPS-snapshot observer takes an optionalcanvasResolutionScalerecord option and downscales each captured frame accordingly. (2026-06-19)
Patch Changes
- Updated dependencies [
5392a55]:- @posthog/types@1.390.1
1.390.2
Patch Changes
-
#3868
a5dd54aThanks @pauldambra! - fix(replay): scope the session-recording flushed-size tracker to the session$sdk_debug_replay_flushed_sizewas stored as a single device-global value in persistence and only reset on an in-page session rotation, so it leaked across page loads and tabs and over-counted on returning visitors. The tracker now keys the running total to the current session id, so a new session starts from zero and a fresh load reading an ongoing session sees the correct total.The internal persistence key backing this counter (
$sess_rec_flush_size) was also unintentionally attached to every captured event as a super-property; it is now marked hidden so it no longer ships on events. The value remains available on session-replay debug events as$sdk_debug_replay_flushed_size. (2026-06-17)
1.390.1
Patch Changes
-
#3784
e25e629Thanks @lucasheriques! - Surveys: event-triggered surveys are now scoped to the page load the event fired in, and only persist across a page reload once they have actually been shown.Previously an event armed a survey by writing it to localStorage, where it stayed until shown. Because the activation survived reloads and the URL condition was only checked at display time, a survey armed by an exit-intent event (which fires as the user is leaving or reloading) could surface on a later page load with no event behind it. Activations now live in memory until the survey is shown, so an armed-but-unshown survey no longer reappears after a reload.
Once a survey is shown it is promoted to persistence, so a non-repeatable survey survives a reload and re-displays until the user dismisses or answers it (instead of vanishing if they reload before interacting). Repeatable surveys (
schedule: 'always'or "Show every time the event is captured") are still consumed when shown, so each captured trigger shows them once. Product tours follow the same model. Cross-page deferral (arm on one full page load, display on a later one) is no longer supported via event triggers; use audience targeting for that. (2026-06-17)
1.390.0
Minor Changes
-
#3869
81b79fbThanks @turnipdabeets! - Add abeforeSendoption to the logs config, so you can inspect, redact, or drop log records before they're sent:posthog.init('<token>', { logs: { beforeSend: (log) => { // return null to drop the log, or return the (optionally modified) log to keep it if (log.body.includes('password')) { return null } return log }, }, })beforeSendaccepts a single function or an array of functions (applied left to right); returningnullfrom any of them drops the record. It runs for logs sent via bothposthog.captureLog()andposthog.logger.*. (2026-06-17)
Patch Changes
- Updated dependencies [
81b79fb]:- @posthog/types@1.390.0
1.389.1
Patch Changes
- #3875
43b4137Thanks @marandaneto! - Limit retries for transport failures without an HTTP response. (2026-06-17)
1.389.0
Minor Changes
- #3865
b469830Thanks @turnipdabeets! - The browser's programmatic logs API (posthog.captureLog()/posthog.logger.*) now runs through the shared@posthog/corelogs pipeline that React Native already uses — no change to the public API or existing behavior. Log delivery is more resilient as a result: oversized batches are split automatically, failed sends retry with exponential backoff, and delivery resumes when the browser comes back online. (2026-06-17)
Patch Changes
- Updated dependencies [
b469830]:- @posthog/core@1.35.0
- @posthog/types@1.389.0
1.388.2
Patch Changes
- #3870
5edfee1Thanks @turnipdabeets! - FixupdateFlags(flags, payloads, { merge: true })baking an active feature flag override into the stored flags. The merge now seeds from the raw stored flags rather than the override-applied values, so clearing the override afterwards correctly restores the original flag. (2026-06-17)
1.388.1
Patch Changes
- #3851
5c453cdThanks @marandaneto! - Apply CSP nonce preparation hooks to style and script elements appended by site apps. (2026-06-17)
1.388.0
Minor Changes
- #3863
b6bc9beThanks @marandaneto! - Add autocapture-only CSS selector opt-outs for web interactions. (2026-06-17)
Patch Changes
- Updated dependencies [
b6bc9be]:- @posthog/types@1.388.0
1.387.0
Minor Changes
- #3709
c6c163aThanks @posthog! - AddunsetPersonProperties()to remove person properties, the counterpart tosetPersonProperties(). Previously the only way to unset a person property was to hand-pass a$unsetarray inside acapture()call. (2026-06-16)
Patch Changes
-
#3756
b3ec845Thanks @archievi! - Drop the event and log a warning when abefore_sendhook removes thetokenproperty, instead of silently sending an event that ingest rejects with a 401. (2026-06-16) -
#3860
c9c7df1Thanks @marandaneto! - Add$unsetto capture options and pass it through in browser capture payloads. (2026-06-16) -
#3855
fadaa4fThanks @haacked! - Stop sending theipquery parameter on feature flag requests. The flags endpoint ignores it, and some ad blockers match/flags…ip=to block flag evaluation on any domain. Dropping it from flag requests avoids the block with no functional change. Event and session recording requests are unchanged. (2026-06-16) -
#3830
0d837f5Thanks @dustinbyrne! - Avoid reloading exception and dead-click autocapture external scripts when they are already present. (2026-06-16) -
#3853
f95a0ecThanks @TueHaulund! - Capture native Fullscreen API transitions in session replay. Entering native fullscreen (element.requestFullscreen()) is rendered by the browser via the UA:fullscreenpseudo-class with no DOM mutation, so the recorder previously captured nothing and replays showed the element at its pre-fullscreen size with drifted click coordinates. The recorder now emits a reserved custom event onfullscreenchange(standard pluswebkit/moz/MSprefixes), and the replayer re-applies fullscreen layout to the element on playback (including when scrubbing into a fullscreen region) via a reservedrr_fullscreenattribute, consistent with rrweb's existingrr_*attribute namespace.Known limitation: fullscreen of an element inside a same-origin iframe is recorded against the
<iframe>element rather than the inner element, so replay pins the iframe. (2026-06-16) -
Updated dependencies [
b3ec845,c9c7df1,c6c163a]:- @posthog/core@1.33.0
- @posthog/types@1.387.0
1.386.8
Patch Changes
- #3838
3094f73Thanks @TueHaulund! - fix(replay): discard the prior session's buffer when start() bails out a pending stop(). On a stopSessionRecording() → reset() → identify(newUser) → startSessionRecording() sequence, stopSessionRecording() takes the async compression-drain path, deferring its buffer flush and teardown. start() correctly invalidates that pending cleanup so the new recorder survives, but it left the stopped session's snapshot buffer in place. The re-entrant session-id restart then flushed those previous-user snapshots under the OLD session id, producing a mixed-distinct_id session that server-sideany(distinct_id)attribution resolves to the wrong person — recordings showing the previous user's identity. start() now clears that stale buffer alongside invalidating the compression queue, matching the drop-trailing-data trade-off the bailed-out stop() path already accepts. (2026-06-15)
1.386.7
Patch Changes
-
#3837
29bf8e3Thanks @marandaneto! - Add missing bugs metadata to package manifests. (2026-06-15) -
#3832
d3a9462Thanks @archievi! - Surveys: guard the remaining unprotectedlocalStorageaccesses (reset()and thelastSeenSurveyDatewrite) so aSecurityErrorin cross-origin iframes is swallowed instead of bubbling up to user monitoring. (2026-06-15) -
Updated dependencies [
29bf8e3]:- @posthog/core@1.32.4
- @posthog/types@1.386.4
1.386.6
Patch Changes
-
#3804
a27b163Thanks @pauldambra! - fix(product-tours): drop the cached tours blob when product tours is not enabledTours fetched while product tours was enabled are cached under
ph_product_toursin the main persistence blob. Once product tours is disabled (remote config or thedisable_product_toursoption) that cache was never cleaned up, so a potentially large stale blob kept riding on every persistence write — and on every cross-tabstorageevent those writes broadcast.onRemoteConfignow clears the cached tours whenever product tours resolves to disabled; they are re-fetched if it is ever re-enabled. (2026-06-11)
1.386.5
Patch Changes
- #3801
bd06ac7Thanks @ksvat! - fix(replay): prevent silent recorder teardown on session-id rotation. When the session id rotates during active rrweb capture,_updateWindowAndSessionIdscallsstop()then synchronouslystart('session_id_changed'). Ifstop()took the_stopAfterCompressionQueueDrainspath (which fires whenever the compression queue is non-empty — common during steady recording), its async cleanup would later resolve and call_teardown()against the freshly-started recorder, stopping rrweb, removing event listeners, and emptying the V2 trigger-group matchers. From that point on, the recorder'sstatusgetter kept reportingactive/sampled(the_strategyreference was still set), but rrweb was no longer producing events, no listeners were registered, and no$snapshotdata reached the server — the session looked recording-eligible from event metadata yet produced no replay.start()now invalidates the compression-queue state (generation bump plus reset of the stop-in-progress flag and queued-event count), so any pending cleanup from a priorstop()bails at its existing generation check and a laterstop()of the new recorder is not mistaken for the old in-progress one. Affects long-running tabs that rotate session id mid-use (idle timeout, session-past-max-length, orposthog.reset()). (2026-06-11)
1.386.4
Patch Changes
- #3767
fdc07f3Thanks @arnohillen! - replay: jump scrolls instantly when seeking past pages that usescroll-behavior: smooth. During fast-forward the replayer applied scrolls withbehavior: 'auto', which inherits the page's CSSscroll-behavior— so on sites that setscroll-behavior: smooth(e.g. Silk bottom sheets/modals) a seeked scroll animated from 0 instead of jumping, leaving scroll-revealed content (the open sheet) out of view and showing only the backdrop until the animation caught up. Sync scrolls now usebehavior: 'instant', matching the method's stated intent that smooth scrolling be disabled while fast-forwarding. Full snapshot rebuilds apply their initial offset withbehavior: 'instant'too, so the document-level scroll doesn't animate either. (2026-06-11)
1.386.3
Patch Changes
-
#3760
5ddfd44Thanks @benben! - fix(conversations): re-attach the support widget after SPA navigations that replacedocument.body(e.g. Turbo Drive), so the widget no longer disappears until a full page reload (2026-06-11) -
#3690
dbf2377Thanks @pauldambra! - fix(sessionid): keep the session id stable across tabsA session now rotates only when every tab has been idle past the timeout, rather than whenever a single background tab decides it is idle. On the active event path an idle tab re-reads the session id from storage before rotating: if a sibling tab kept the session alive it does not rotate, and if a sibling already rotated it adopts that id instead of minting a new one. This removes spurious cross-tab session fragmentation (inflated session counts, truncated session durations, split replays). When a sibling session is adopted,
onSessionIdhandlers fire withchangeReason.crossTabAdoption: trueso session recording, pageview state, and session-scoped properties follow the new session. Whenpersistence_save_debounce_ms > 0(the2026-05-30default) the refresh reads only the session-id key so it cannot clobber a sibling's write.Note: projects with significant multi-tab usage will see fewer but longer sessions after upgrading — this is a correction of previously over-counted sessions, not a traffic change. (2026-06-11)
-
#3795
21441a8Thanks @pauldambra! - fix(persistence): stop per-request metadata rewriting the split-storage entries on every load$feature_flag_evaluated_at,$feature_flag_request_id, and$surveys_loaded_atchange on every/flags(or/surveys) load even when the flag and survey content is unchanged. Withsplit_storageenabled that made the multi-hundred-KB__flags/__surveyslocalStorage entries dirty on every SPA navigation, re-broadcasting the full payload to every open same-origin tab via cross-tabstorageevents — the exact pressure the split exists to remove. These keys are now marked volatile: a value-only change neither dirties the group nor alters its fingerprint, so the write is skipped and the freshest value rides along on the next real content write. Adding or deleting a volatile key still writes through (presence is fingerprinted, the moving value is not), and the in-memory value is always current — only the on-disk copy may lag until the next content change. (2026-06-11) -
Updated dependencies [
dbf2377]:- @posthog/types@1.386.3
- @posthog/core@1.32.3
1.386.1
Patch Changes
-
#3780
93e0461Thanks @dustinbyrne! - Fix stale sampled-in session replay decisions after the configured replay sample rate changes. (2026-06-10) -
#3788
6da86d0Thanks @TueHaulund! - fix(replay): never record or flush snapshots while the sampling decision is missingWhen the stored sampling decision was wiped while the recorder was running (e.g. by
posthog.reset()), the undecided session reported anactivestatus and could leak short junk recordings from sessions that then decided not to record. Sampling decisions are now persisted tagged with the session id they were made for ('!' + sessionIdwhen sampled out), are re-made on every session id change regardless of config availability, and a buffer is never flushed without a decision when sampling is configured. Because the decision is a deterministic hash of the session id, re-deciding never flips the outcome for the same session. This also stops a stalefalsedecision from a previous session being inherited by a new session, which chronically under-recorded returning visitors. (2026-06-10) -
Updated dependencies []:
- @posthog/types@1.386.1
- @posthog/core@1.32.1
1.386.0
Minor Changes
-
#3634
612f97aThanks @lucasheriques! - feat(surveys): add opt-inappearance.allowGoBackfor multi-question surveys, and make button labels translatableRenders a "Back" button on web surveys after the first question. Default is off — existing surveys are unchanged. Uses a visited-index history stack so back-navigation respects branching paths (
response_based,specific_question), and abandoned-branch responses are pruned before submission so analytics aren't polluted. Returning to a question pre-fills the prior answer.appearance.backButtonTextoverrides the default label. The button uses the survey's text color so it stays readable on any background, and it also shows in survey previews.Also adds
submitButtonTextandbackButtonTextto survey-level translations, so both the submit and back button labels can be localized viaappearancetranslations (previously only the per-question button text was translatable). (2026-06-10)
Patch Changes
- Updated dependencies [
612f97a]:- @posthog/core@1.32.0
- @posthog/types@1.386.0
1.385.0
Minor Changes
- #3777
f601c49Thanks @dustinbyrne! - Promote external dependency script versioning to supportedstrict_script_versioningandasset_hostconfig options. (2026-06-10)
Patch Changes
-
#3753
c11794dThanks @dustinbyrne! - Reload feature flags by default when resetting person properties for flags. (2026-06-10) -
#3742
23b2af1Thanks @arnohillen! - record: capture resting scroll offset onscrollendwhen a reveal scroll clamps to 0 before its target is scrollable (e.g. Silk sheets). Deduped againstscrollso normal gestures don't double event volume. (2026-06-10) -
Updated dependencies [
c11794d,f601c49]:- @posthog/types@1.385.0
- @posthog/core@1.31.4
1.384.3
Patch Changes
- #3791
2d21adaThanks @marandaneto! - Deprecate__preview_disable_beaconin favor ofdisable_beaconand mark__preview_disable_xhr_credentialsas a no-op. (2026-06-10) - Updated dependencies [
2d21ada]:- @posthog/types@1.384.3
- @posthog/core@1.31.3
1.384.2
Patch Changes
- #3789
d9462b3Thanks @marandaneto! - Deprecate__preview_eager_load_replayas a no-op now that session replay lazy loading is the default. (2026-06-10) - Updated dependencies [
d9462b3]:- @posthog/types@1.384.2
- @posthog/core@1.31.2
1.384.1
Patch Changes
- #3787
0e22d77Thanks @TueHaulund! - replayer: stop corrupting recordings when events are added behind the playhead.addEvent()used to apply any event older than the playback baseline synchronously onto the current DOM — correct for live-mode catch-up, but wrong for on-demand playback where snapshot chunks can finish loading after the user has seeked ahead. Applying those past mutations onto a DOM at a different position made theirremovesfail mirror lookups, andapplyMutationthen deleted the failed entries from the event objects themselves, so every later seek rebuilt from corrupted data (DOM nodes accumulating, e.g. duplicated text) and exports serialized the stripped events. Past events are now only applied synchronously in live mode (otherwise they are just inserted for the next seek to pick up), andapplyMutationfilters removes into a local copy instead of mutating the event data. (2026-06-10) - Updated dependencies []:
- @posthog/types@1.384.1
- @posthog/core@1.31.1
1.384.0
Minor Changes
-
#3782
0c2acb9Thanks @pauldambra! - Detect the Google Search App (GSA) as its own$browservalue (Google Search App) via the cross-platformGSA/UA marker, instead of reporting the embedded webview as Mobile Safari (iOS) or Chrome (Android). Gated behind the newdetect_google_search_appconfig option, which the2026-05-30config defaults opt into automatically — left off otherwise to keep existing browser attribution backwards-compatible.Note:
$browser_versionforGoogle Search Appis not comparable across platforms — iOS yields a version like284.0(fromGSA/284.0.564099828) while Android yields a version like14.21(fromGSA/14.21.20.28.arm64), since Google maintains separate versioning schemes for the two apps. Avoid building cross-platform version dashboards on$browser_versionfor this browser. (2026-06-10)
Patch Changes
- Updated dependencies [
0c2acb9]:- @posthog/core@1.31.0
- @posthog/types@1.384.0
1.383.3
Patch Changes
- #3776
783ba46Thanks @marandaneto! - Deprecate the no-op__preview_flags_v2browser SDK config option. The SDK already uses the/flags/?v=2endpoint by default. (2026-06-09) - Updated dependencies [
783ba46]:- @posthog/types@1.383.3
- @posthog/core@1.30.14
1.383.2
Patch Changes
- #3748
7820929Thanks @marandaneto! - Reduce duplicate internal code found by dry4ts. (2026-06-09) - Updated dependencies []:
- @posthog/types@1.383.2
- @posthog/core@1.30.13
1.383.1
Patch Changes
- #3770
e481b0cThanks @dustinbyrne! - Respectcapture_pageview: falsewhen opting out in cookielesson_rejectmode. (2026-06-08) - Updated dependencies []:
- @posthog/types@1.383.1
- @posthog/core@1.30.12
1.383.0
Minor Changes
-
#3771
227c9b0Thanks @dustinbyrne! - feat(persistence): addsplit_storageconfig option to store the feature-flag config cluster in its own localStorage entry (<name>__flags) instead of the single main persistence blob. This payload is large and changes rarely, so keeping it out of the main blob stops it riding on every high-frequency main-blob write and broadcasting on cross-tabstorageevents. Reads are unchanged: on load the entry is merged back into the in-memory props, and the old main-blob location is read once and migrated forward so upgrades never miss a cached flag. The split only applies when persistence resolves tolocalStorage/localStorage+cookie(it is pointless formemory/sessionStorageand impossible forcookie), andreset()/ opt-out wipe every entry. Defaults tofalsefor backwards compatibility; the new2026-05-30config default opts in automatically. (2026-06-08) -
#3727
393f9e2Thanks @pauldambra! - feat(surveys): extendsplit_storageto also move the survey config ($surveys) out of the main persistence blob into its own<name>__surveyslocalStorage entry, on top of the feature-flag split. Surveys now stamp a$surveys_loaded_atfreshness timestamp on every/surveysload — the survey analogue of$feature_flag_evaluated_at— so a stale__surveysentry can no longer win over a fresher survey payload written back into the main blob by a gate-off / older-SDK tab. With no timestamp on either side (migration leftover) the group entry still wins, so the migration path is unchanged. Same backend andreset()/ opt-out semantics as the flag split. (2026-06-08)
Patch Changes
1.382.0
Minor Changes
-
#3749
9877710Thanks @pauldambra! - Stop classifying intentional repeated clicks as rageclicks. From the2026-05-30config defaults, rageclick detection now ignores:- text-editing surfaces (
textarea, text-likeinputs, andcontenteditableelements), where rapid clicks are double/triple-click text selection rather than rage (rageclick.ignore_text_selection) +/-stepper buttons, added to the defaultcontent_ignorelist
Symbol-only keywords in
content_ignorelist(e.g.+,-,>,<) now match the element's text exactly instead of as a substring, so labels likesign-up,5 > 3, orC++are no longer treated as repeatedly-clicked controls. The heatmaps rageclick marker now applies the same suppression as the$rageclickevent.A partial
rageclickconfig object is now merged with the date-gated defaults instead of replacing them, so e.g.rageclick: { threshold_px: 50 }keeps the defaultcontent_ignorelist/ignore_text_selection. Pass an explicit value (e.g.content_ignorelist: false) to override a specific default, or a boolean to opt out entirely.Behaviour change for existing
content_ignorelist: trueusers (available since2025-11-30): the default list already includes>and<. After this release, buttons whose text contains>or<but is not exactly that symbol (e.g.Learn more >,< Back,home > settings) will no longer be suppressed. Bare>and<buttons remain suppressed. This is the intended fix, but if you rely on the old substring behaviour for those keywords, replacecontent_ignorelist: truewith an explicit array listing the exact terms you want to suppress. (2026-06-06) - text-editing surfaces (
Patch Changes
- Updated dependencies []:
- @posthog/types@1.382.0
- @posthog/core@1.30.10
1.381.0
Minor Changes
- #3719
a7bd828Thanks @lricoy! - Add__preview_cookie_wins_on_conflictopt-in config to prefer cookie values over localStorage when merging persistence state inlocalStorage+cookiemode, fixing cross-subdomain identify and session disconnects. (2026-06-05)
Patch Changes
- Updated dependencies [
a7bd828]:- @posthog/types@1.381.0
- @posthog/core@1.30.9
1.380.1
Patch Changes
- #3743
ced0039Thanks @robbie-c! - fix(surveys): stop the survey CSS from using:has(.survey-question:empty), which crashes some WebKit builds during text-node style invalidation while a survey renders. The empty-header margin tweak now keys off a JS-setquestion-header--emptyclass and a sibling selector instead. (2026-06-05) - Updated dependencies []:
- @posthog/types@1.380.1
- @posthog/core@1.30.8
1.380.0
Minor Changes
- #3715
2387084Thanks @dustinbyrne! - Promote browser tracing header configuration to the publictracing_headersoption while keepingaddTracingHeadersand__add_tracing_headersas deprecated aliases. (2026-06-04)
Patch Changes
- #3715
2387084Thanks @dustinbyrne! - When using tracing headers,X-POSTHOG-DISTINCT-IDis read at request time instead of when fetch/XHR is patched, ensuring it reflects bootstrap, identify, reset, and other identity changes. (2026-06-04) - Updated dependencies [
2387084]:- @posthog/types@1.380.0
- @posthog/core@1.30.7
1.379.3
Patch Changes
1.379.2
Patch Changes
- #3736
374962aThanks @arnohillen! - replay: re-apply scroll positions after fast-forward/seek. Scrolls applied mid-catch-up could clamp to 0 when the target wasn't scrollable yet (e.g. scroll-revealed sheets/modals whose content sits below the fold), leaving the content scrolled out of view on replay. The last scroll per node is now re-applied in the flush stage once layout has settled.posthog-jsis bumped too so the rebuilt bundle containing the fix is published. (2026-06-03) - Updated dependencies []:
- @posthog/types@1.379.2
- @posthog/core@1.30.5
1.379.1
Patch Changes
-
#3570
4a27cedThanks @gruessi! - fix(record): release iframe documents and observers on iframe removal — same-origin iframes mounted and unmounted while session recording is active no longer leak theirDocument, every node serialized into the mirror, or oneMutationObserverper mount. Closes eight retainer chains: load-listener disposers, named pagehide handlers, therecordCrossOriginIframescleanup gate (now applied to same-origin too), capturedDocument/Windowsets that surviveiframe.srcswap-to-about:blankbefore removal, and the globalmutationBuffers[]/handlers[]arrays which previously accumulated forever. Validated end-to-end: a host page that mounts/unmounts 5 blob-URL iframes every 2s for 110s went from +118 MB / +390 leakedHTMLDocuments to ~0 MB / 0. (2026-06-03) -
#3717
1688b38Thanks @turnipdabeets! - Move the OpenTelemetry logs dependencies todevDependencies. They are only used to build the CDN-servedlogsextension chunk, which inlines them, so consumers no longer install the transitiveprotobufjs(whoseeval("require")trippedunsafe-evalContent Security Policies).If you imported
@opentelemetry/*directly while relying on it being hoisted fromposthog-js, add it to your own dependencies. (2026-06-03) -
Updated dependencies []:
- @posthog/types@1.379.1
- @posthog/core@1.30.4
1.379.0
Minor Changes
- #3722
c487070Thanks @marandaneto! - Add$sdk_dist_channelevent property for browser SDKnpmandcdndistribution channels. (2026-06-02)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.379.0
- @posthog/core@1.30.3
1.378.1
Patch Changes
- #3706
8fcf40dThanks @dustinbyrne! - fix(browser): avoid exposing internally-created Request bodies to downstream fetch wrappers in Safari. (2026-06-01) - Updated dependencies []:
- @posthog/types@1.378.1
- @posthog/core@1.30.2
1.378.0
Minor Changes
- #3688
8181354Thanks @pauldambra! - feat(persistence): addpersistence_save_debounce_msconfig option to coalesce rapid storage saves into a single write. Setting a positive value debounces writes to localStorage/cookie by that window; the in-memorypropsobject still updates synchronously so within-tab reads see the latest values immediately, and pending writes flush onbeforeunloadandpagehideso no state is lost on tab close. Cross-tabstorageevents are reduced proportionally to the debounce window. Defaults to0(no debouncing) for backwards compatibility. On pages that capture many events per second,250is a reasonable starting point. The new2026-05-30config default opts intopersistence_save_debounce_ms: 250automatically. (2026-06-01)
Patch Changes
- Updated dependencies [
8181354]:- @posthog/types@1.378.0
- @posthog/core@1.30.1
1.377.0
Minor Changes
-
#3708
3d4a76fThanks @pauldambra! - Detect Brave (desktop, Android, iOS), Vivaldi, Yandex, Naver Whale, DuckDuckGo, Pale Moon, and Waterfox so users on these browsers no longer get bucketed as Chrome or Firefox.detectBrowser/detectBrowserVersionnow accept an optional third argument,BrowserDetectionHints, with abraveflag (set whennavigator.braveexists). The browser SDK populates this automatically to catch desktop / Android Brave, which is Chromium-based and carries no UA marker. Brave on iOS is picked up purely from theBrave/UA marker — WebKit doesn't shipnavigator.brave. The original two-argument signature still works for non-DOM callers. (2026-06-01)
Patch Changes
- #3703
f3cc6faThanks @marandaneto! - Disable/no-op initialization paths instead of throwing or sending requests when PostHog project tokens are missing or blank. (2026-06-01) - Updated dependencies [
3d4a76f]:- @posthog/core@1.30.0
- @posthog/types@1.377.0
1.376.6
Patch Changes
- #3687
663e250Thanks @pauldambra! - fix(persistence): skip the storage write when the serialized props are unchanged. Callers spamsave()after every property change, and many of those changes leave the serialized payload identical (e.g. resetting a value to its current value). Writing identical bytes to localStorage still fires a cross-tabstorageevent in every same-origin tab, where Chrome allocates the payload buffer in mojo IPC even though no listener reacts. Nowsave()compares the serialized payload against the last successful write and bails out when nothing changed. (2026-05-31) - Updated dependencies []:
- @posthog/types@1.376.6
- @posthog/core@1.29.15
1.376.5
Patch Changes
- #3686
66cbc59Thanks @pauldambra! - fix(persistence): throttle session-activity timestamp writes to a 5s granularity. The in-memory value still moves at full resolution; only writes to localStorage/cookie are coalesced. Activity-timestamp-only updates within the granularity window are skipped, dropping localStorage write pressure and cross-tabstorageevent broadcasts on pages that capture many events per second. The pending in-memory value is flushed ondestroyandbeforeunloadso a tab close inside the window does not leave the persisted value up to 5s stale for sibling tabs. The flush re-reads storage first and bails out if a sibling tab has rotated the session, so the flush cannot clobber the new session with the old id/start. (2026-05-31) - Updated dependencies [
d9ad199]:- @posthog/core@1.29.14
- @posthog/types@1.376.5
1.376.4
Patch Changes
-
#3685
f59f35aThanks @ioannisj! - fix(cookieless): enable request queue when opting out inon_rejectmode. When usingcookieless_mode: "on_reject", callingopt_out_capturing()correctly switched the SDK into cookieless capturing but never enabled theRequestQueue— so batched events were enqueued but never flushed over the network. At init time the queue was not started because consent wasPENDINGandis_capturing()returnedfalse;opt_out_capturing()is the first moment capturing becomes active but was missing the_start_queue_if_opted_in()call thatopt_in_capturing()already had. (2026-05-28) -
#3692
f01cd93Thanks @ksvat! - fix(replay): take a fresh full snapshot after session ID rotates viaforcedIdleReset. Previously, when the session manager's idle enforcement timer rotated the session id, the recorder tore down rrweb and set_isIdle = 'unknown'before the new session id was observed. Neither restart path then fired (the_onSessionIdCallbackguard only restarted when_isIdle === true, and_updateWindowAndSessionIdscould not run with rrweb stopped), so the new session received only incremental mutations until a later snapshot — leaving the player stuck on "Buffering". The restart guard now also fires when rrweb isn't running. (2026-05-28) -
#3691
cc71f3fThanks @ksvat! - fix(replay): shipph-no-captureabsolute-position fix from #3678 toposthog-js. The original changeset only bumped@posthog/rrweband@posthog/rrweb-snapshot; becauseposthog-jsdepends on@posthog/rrwebviaworkspace:*, the cascade did not bumpposthog-js, so the rebuilt bundle containing the fix was not published. This changeset re-publishesposthog-jswith the fix. (2026-05-28) -
#3695
e1ff722Thanks @ksvat! - chore(replay): expose$sdk_debug_rrweb_attachedand$sdk_debug_rrweb_start_attempteddebug properties on captured events. Today the SDK already stamps several$sdk_debug_*properties (start reason, linked-flag trigger status, recording status) that report the SDK's intent to record — they all flip to "active" as soon as the state machine evaluates the configured triggers. None of them observe whether rrweb actually attached and is producing events. The new booleans close that gap:$sdk_debug_rrweb_start_attemptedis set when_startRecorder()is first entered, and$sdk_debug_rrweb_attachedreflects whether_stopRrwebis currently a non-falsy stop handle (i.e.rrwebRecord({...})returned successfully and the recorder has not been torn down). No behavior change — this only adds two booleans to the existingsdkDebugPropertieschannel, used to diagnose cases where a session reportstrigger_activated/recording_status: activebut no$snapshotdata is ever uploaded. (2026-05-28) -
Updated dependencies [
7b84b75]:- @posthog/core@1.29.13
- @posthog/types@1.376.4
1.376.3
Patch Changes
- #3649
9cac1f6Thanks @marandaneto! - Improve console log serialization performance for large objects. (2026-05-27) - Updated dependencies []:
- @posthog/types@1.376.3
- @posthog/core@1.29.12
1.376.2
Patch Changes
- #3667
cafa9ccThanks @pauldambra! - fix(replay): stop polling preload-as-style<link>elements forever. Session recorder treated<link rel="preload" as="style" href="*.css">as if it were a stylesheet and waited forlink.sheetto populate. Per spec preload links never instantiate aCSSStyleSheet, so the wait timed out, re-serialized the link, scheduled another wait, and leaked aloadlistener on every cycle — multiplying further on every realloadevent. Pages with Next.js-style CSS preloads accumulated thousands of active polling chains, saturating the main thread and freezing the tab on refocus (2026-05-26) - Updated dependencies []:
- @posthog/types@1.376.2
- @posthog/core@1.29.11
1.376.0
Minor Changes
- #3655
6e8d349Thanks @arnaudhillen! - Expose the in-repo@posthog/rrweb,@posthog/rrweb-types, and@posthog/rrweb-plugin-console-recordpackages as subpath entry points onposthog-js. Consumers can nowimport { Replayer } from 'posthog-js/rrweb',import type { eventWithTime } from 'posthog-js/rrweb-types', andimport { LogLevel } from 'posthog-js/rrweb-plugin-console-record'instead of installing the underlying rrweb packages directly. The rrweb worker sourcemap (image-bitmap-data-url-worker-*.js.map) is also shipped fromposthog-js/dist/so downstream bundlers no longer need to reach intonode_modules/@posthog/rrweb. (2026-05-22)
Patch Changes
- #3639
c806ccaThanks @marandaneto! - Use native async gzip compression for session recording events when CompressionStream is available. (2026-05-22) - Updated dependencies [
c806cca]:- @posthog/core@1.29.9
- @posthog/types@1.376.0
1.375.0
Minor Changes
- #3641
2e1d5f4Thanks @dustinbyrne! - Addflag_keysconfig to restrict browser feature flag remote evaluation to specific flag keys. (2026-05-21)
Patch Changes
- Updated dependencies [
2e1d5f4]:- @posthog/types@1.375.0
- @posthog/core@1.29.8
1.374.4
Patch Changes
-
#3638
87e2145Thanks @marandaneto! - Apply tracing headers to matching XMLHttpRequest requests (2026-05-21) -
#3646
4f87827Thanks @marandaneto! - Avoid throwing or initializing PostHogProvider when no API key or client is provided (2026-05-21) -
#3645
280832bThanks @TueHaulund! - Capture<link rel="stylesheet">URLs fromlink.sheet.hrefand trylink.sheetdirectly for inlining, so recordings survive SPAhistory.pushStatenavigations between routes of different path depths (wherelink.hrefre-resolves against a new baseURI butlink.sheet.hrefpreserves the URL the browser actually fetched).Ships the fix landed in #3635, which only bumped the internal
@posthog/rrweb-snapshotpackage — that package is bundled intoposthog-jsat build time but is not published to npm on its own, so aposthog-jsbump is needed to actually deliver the change. (2026-05-21) -
Updated dependencies []:
- @posthog/types@1.374.4
- @posthog/core@1.29.7
1.374.2
Patch Changes
-
#3550
df91995Thanks @TueHaulund! - Preserve session-recording remote config acrossposthog.reset().posthog.reset()was clearing the entire persistence store, which wiped$session_recording_remote_configalong with user state. On the next session rotation triggered by the reset,start('session_id_changed')would early-return because the remote config was missing — leaving rrweb torn down and the new session opening with no Meta + FullSnapshot until the next periodic 5-minute checkout.This affected any flow where an app calls
posthog.reset()mid-session (e.g. on sign-out / sign-in) and was particularly visible on Flutter Web recordings that depend on a fresh FullSnapshot to anchor the CanvasKit DOM. (2026-05-18) -
Updated dependencies []:
- @posthog/types@1.374.2
- @posthog/core@1.29.5
1.374.1
Patch Changes
- #3627
07a0f5fThanks @marandaneto! - Respect transport overrides passed to posthog.capture. (2026-05-18) - Updated dependencies []:
- @posthog/types@1.374.1
- @posthog/core@1.29.4
1.374.0
Minor Changes
- #3620
594ea11Thanks @pauldambra! - Dead clicks: add a.ph-no-deadclickCSS class (andcapture_dead_clicks.css_selector_ignorelistconfig option) to exclude specific elements from dead-click detection without affecting autocapture, session replay, or heatmaps. Mirrors the existing.ph-no-rageclickpattern. (2026-05-18)
Patch Changes
- #3621
3c0a09fThanks @pauldambra! - Dead clicks: a click on an<a>(or any element inside an<a>, including across shadow DOM) is no longer flagged as a dead click — the browser navigates / downloads / opens a new window and we can't observe that. Reuses autocapture's existing DOM walker for the ancestor walk. Direct clicks on<button>,<input>,<select>,<textarea>,<label>, and<form>(previously all skipped) are now eligible for dead-click detection: if their JS handler ran, the existing mutation / scroll / selection observers see the effect; if it didn't, dead-click correctly surfaces the bug. A broken<button>with no handler, or an<svg>icon inside one, will now flag — which is exactly the dead-click case we want to catch. (2026-05-18) - Updated dependencies [
594ea11]:- @posthog/types@1.374.0
- @posthog/core@1.29.3
1.373.5
Patch Changes
- #3613
221973eThanks @lucasheriques! - Surveys: submit open text questions with Cmd/Ctrl+Enter. The textarea still inserts a newline on plain Enter (native behaviour), matching the convention used by Slack, GitHub, Discord, and ChatGPT for multi-line inputs. Single-line "Other:" inputs continue to submit on plain Enter as before. (2026-05-15) - Updated dependencies []:
- @posthog/types@1.373.5
- @posthog/core@1.29.2
1.373.4
Patch Changes
- #3602
4b895bfThanks @marandaneto! - Validate gzip request bodies at the browser send boundary and fall back to JSON if the outgoing body is not gzip data. (2026-05-12) - Updated dependencies [
4b895bf]:- @posthog/core@1.29.1
- @posthog/types@1.373.4
1.373.2
Patch Changes
- #3568
223d925Thanks @marandaneto! - Validate native gzip output before sending requests and fall back when CompressionStream returns malformed data. (2026-05-11) - Updated dependencies [
223d925]:- @posthog/core@1.28.7
- @posthog/types@1.373.2
1.373.1
Patch Changes
- #3566
7d027bcThanks @dustinbyrne! - Prevent browser log capture from throwing when console arguments contain unreadable properties. (2026-05-11) - Updated dependencies []:
- @posthog/types@1.373.1
- @posthog/core@1.28.6
1.373.0
Minor Changes
- #3547
4c0c7d9Thanks @williamchong! -capture()now accepts an optionaluuidonCaptureOptions. (2026-05-11)
Patch Changes
-
#3561
3511848Thanks @marandaneto! - Handle invalid persisted session replay config JSON gracefully (2026-05-11) -
#3559
0a835faThanks @marandaneto! - Skip remote config background refreshes when no document is available. (2026-05-11) -
Updated dependencies [
4c0c7d9,0a835fa]:- @posthog/types@1.373.0
- @posthog/core@1.28.5
1.372.10
Patch Changes
-
#3544
d120042Thanks @ksvat! - fix: stop session recording before destroying sessionManager inopt_out_capturing()withcookieless_mode: "on_reject". Previously, queued/throttled rrweb events (e.g. mousemove) could fire after the sessionManager was set toundefinedand throw[SessionRecording] must be started with a valid sessionManager. Also adds a defensive early-return inonRRwebEmitso any remaining late events bail out instead of throwing. (2026-05-07) -
#3542
94a5ba0Thanks @TueHaulund! - Preserve<style>textContent when the browser's CSSOM serialization would emit empty longhands fromvar()inside a shorthand. When a stylesheet has e.g.padding: var(--p); padding-bottom: var(--pb);, browsers store the shorthand's longhands with empty token lists per the CSS Custom Properties spec, andCSSStyleRule.cssTextre-emits them aspadding-top: ; padding-right: ; padding-left: ;. The previous behavior replaced the<style>text with that corrupted output, silently dropping layout rules on replay. We now detect the empty-longhand pattern and keep the original textContent in that case. Affects users of any CSS-in-JS framework that combinesvar()with shorthands (Chakra UI v3, Panda CSS, Emotion, etc.). Same class of bug as rrweb-io/rrweb#1667. (2026-05-07) -
Updated dependencies []:
- @posthog/types@1.372.10
- @posthog/core@1.28.4
1.372.9
Patch Changes
- #3537
026e09dThanks @TueHaulund! - Pull in the canvas-manager fix from@posthog/rrweb0.0.61: skip canvas snapshots while the WebGL context is lost so transparent bitmaps don't poison the worker's fingerprint dedup map and silently kill canvas recording for the rest of the session. Also wrapsgetCanvas()in try/catch so DOM/shadow-root traversal errors can't cancel the rAF loop. See PR #3527 for context. (2026-05-05) - Updated dependencies []:
- @posthog/types@1.372.9
- @posthog/core@1.28.3
1.372.8
Patch Changes
- #3515
255b273Thanks @marandaneto! - Gate survey translation logs behind SDK debug logging to avoid production console spam. (2026-05-04) - Updated dependencies [
220cd61,255b273]:- @posthog/core@1.28.2
- @posthog/types@1.372.8
1.372.6
Patch Changes
- #3492
cf56753Thanks @lucasheriques! - Add translated survey rendering support in React Native and share survey translation logic through@posthog/core. (2026-05-01) - Updated dependencies [
cf56753,04db756]:- @posthog/core@1.28.0
- @posthog/types@1.372.6
1.372.3
Patch Changes
- #3488
5b8efc3Thanks @lucasheriques! - Add browser survey translation rendering and language tracking. (2026-04-27) - Updated dependencies []:
- @posthog/types@1.372.3
- @posthog/core@1.27.7
1.372.2
Patch Changes
- #3484
cba2570Thanks @veryayskiy! - Fix autofocus (2026-04-27) - Updated dependencies []:
- @posthog/types@1.372.2
- @posthog/core@1.27.6
1.372.1
Patch Changes
- #3464
70508dfThanks @dustinbyrne! - Avoid usingBlob.stream()for native async gzip compression to prevent SafariNotReadableErrorstream failures. (2026-04-24) - Updated dependencies [
70508df]:- @posthog/core@1.27.5
- @posthog/types@1.372.1
1.372.0
Minor Changes
- #3470
eaa1322Thanks @veryayskiy! - You cannot write to a resolve ticket. Start a new one. (2026-04-24)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.372.0
- @posthog/core@1.27.4
1.371.3
Patch Changes
- #3445
61cf83eThanks @dustinbyrne! - Fix session recording in the full no-external browser bundles (2026-04-24) - Updated dependencies [
daf028d]:- @posthog/core@1.27.2
- @posthog/types@1.371.3
1.371.2
Patch Changes
- #3453
96f19b7Thanks @turnipdabeets! - Lift OTLP log serialization helpers from posthog-js into @posthog/core so the upcoming React Native logs feature consumes the same builders. Browser gains two fixes as a side effect: NaN and ±Infinity attribute values no longer get silently dropped during JSON encoding, and the scope.version OTLP field is now populated with the SDK version (changes the server's instrumentation_scope column from "posthog-js@" to "posthog-js@"). (2026-04-23) - Updated dependencies [
96f19b7]:- @posthog/types@1.371.2
- @posthog/core@1.27.1
1.371.1
Patch Changes
- #3425
2da17e8Thanks @marandaneto! - Classify SDK-owned persistence keys with an explicit event exposure policy so new internal persistence state must be intentionally marked as event-visible, hidden, or derived. (2026-04-23) - Updated dependencies []:
- @posthog/types@1.371.1
1.371.0
Patch Changes
-
#3432
1a8b727Thanks @richardsolomou! - refactor: rename__add_tracing_headerstoaddTracingHeaders. The__prefix signalled an internal/experimental option, but the config is a public API (documented for linking LLM traces to session replays).__add_tracing_headerscontinues to work as a deprecated alias on the browser SDK.Also exposes
patchFetchForTracingHeadersfrom@posthog/coreso non-browser SDKs can reuse the implementation. (2026-04-23) -
Updated dependencies [
1a8b727]:- @posthog/core@1.27.0
- @posthog/types@1.371.0
1.370.1
Patch Changes
- #3442
6f19ce8Thanks @marandaneto! - fix(surveys): guard survey seen localStorage access (2026-04-22) - Updated dependencies []:
- @posthog/types@1.370.1
1.370.0
Minor Changes
- #3389
922a1c1Thanks @hpouillot! - Add exception steps to error tracking (aka breadcrumbs) (2026-04-22)
Patch Changes
- Updated dependencies [
922a1c1]:- @posthog/types@1.370.0
- @posthog/core@1.26.0
1.369.4
Patch Changes
- #3362
d61bce1Thanks @sampennington! - fix(cookieless): start in cookieless mode when opt_out_capturing_by_default is set (2026-04-21) - Updated dependencies []:
- @posthog/types@1.369.4
1.369.2
Patch Changes
- #3386
4a65604Thanks @dustinbyrne! - Add a preview flag for versioned browser lazy bundle asset paths. (2026-04-16) - Updated dependencies [
4a65604]:- @posthog/types@1.369.2
1.369.1
Patch Changes
-
#3393
85ae4d9Thanks @haacked! - Exclude active feature flag payloads from event properties (2026-04-16) -
#3392
00cd1ceThanks @haacked! - Fix unnecessary persisted config and activation properties (including product tours, surveys, and session recording config) added to captured events (2026-04-16) -
Updated dependencies []:
- @posthog/types@1.369.1
1.368.2
Patch Changes
- #3378
f1bea33Thanks @marandaneto! - Disable native gzip compression after a NotReadableError in the browser SDK (2026-04-14) - Updated dependencies []:
- @posthog/types@1.368.2
1.368.1
Patch Changes
- #3379
d7c71b1Thanks @dmarticus! - Fix bootstrapped feature flags being overwritten by partial /flags response whenadvanced_only_evaluate_survey_feature_flagsis enabled (2026-04-14) - Updated dependencies []:
- @posthog/types@1.368.1
1.367.0
Minor Changes
- #3242
353be9aThanks @dustinbyrne! - feat: Add support for pre-loaded remote-config (2026-04-09)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.367.0
1.366.2
Patch Changes
- #3364
575e354Thanks @lucasheriques! - Add a hover state to numeric survey rating options so they provide clearer pointer feedback before selection. (2026-04-09) - Updated dependencies []:
- @posthog/types@1.366.2
1.366.1
Patch Changes
- #3360
802bf39Thanks @jabahamondes! - Re-evaluate consent persistent store when config changes to support cross-subdomain consent sharing (2026-04-09) - Updated dependencies []:
- @posthog/types@1.366.1
1.366.0
Minor Changes
- #3305
b599672Thanks @veryayskiy! - Add customer side identification (2026-04-09)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.366.0
1.365.4
Patch Changes
- #3353
3939856Thanks @lucasheriques! - Expose the current question index on.survey-boxvia adata-question-indexattribute. This gives consumers rendering surveys via the API a reliable way to know which question is currently displayed without parsing input ids or class names — works for every question type, including link questions which render no input or rating element. (2026-04-08) - Updated dependencies []:
- @posthog/types@1.365.4
1.365.3
Patch Changes
- #3357
dbdddcaThanks @pauldambra! - Bump @posthog/rrweb packages to 0.0.56, which includes:- PostHog/posthog-rrweb#157: fix: clear mutation buffer on iframe pagehide to prevent recording corruption
- PostHog/posthog-rrweb#158: fix: skip unchanged setAttribute calls to prevent replay flicker
- PostHog/posthog-rrweb#159: fix: prevent iframe leak in untainted prototype and avoid unnecessary iframe creation
- PostHog/posthog-rrweb#163: fix: handle SecurityError in IframeManager destroy and removeIframeById
- PostHog/posthog-rrweb#166: fix: remove postcss from @posthog/rrweb-record bundle (420KB → 170KB) (2026-04-08)
- Updated dependencies []:
- @posthog/types@1.365.3
1.365.2
Patch Changes
- #3323
c387f6dThanks @pauldambra! - perf(replay): reduce memory and CPU cost of event compression by caching gzipped empty arrays and eliminating redundant JSON.stringify for size estimation (2026-04-08) - Updated dependencies [
c387f6d]:- @posthog/types@1.365.2
1.365.0
Minor Changes
- #3302
fc5589fThanks @dmarticus! - preserve $set_once semantics in local flag evaluation cache (2026-04-07)
Patch Changes
- Updated dependencies [
fc5589f]:- @posthog/core@1.25.0
- @posthog/types@1.365.0
1.364.7
Patch Changes
- #3319
b25b689Thanks @dustinbyrne! - fix: send $groupidentify for new groups even when no properties are provided (2026-04-03) - Updated dependencies []:
- @posthog/types@1.364.7
1.364.6
Patch Changes
- #3316
68cd4e5Thanks @dustinbyrne! - Fix slim bundle + extension bundles crash caused by inconsistent property mangling (2026-04-02) - Updated dependencies [
a01a3d5]:- @posthog/core@1.24.6
- @posthog/types@1.364.6
1.364.5
Patch Changes
-
#3309
197eedaThanks @marandaneto! - Extract CLI and sourcemap utilities from @posthog/core into @posthog/plugin-utils to remove cross-spawn from React Native dependencies (2026-04-01) -
#3312
c5feb5cThanks @TueHaulund! - Bump @posthog/rrweb-* to 0.0.52 — adds error recovery to the canvas FPS snapshot pipeline, preventing canvas recording from permanently stopping when createImageBitmap or the worker encounters an error (2026-04-01) -
#3315
7b944fcThanks @TueHaulund! - Bump @posthog/rrweb-* to 0.0.53 — fixes infinite recursion crash ("Maximum call stack size exceeded") when calling posthog.reset() or restarting the recorder on pages with shadow DOM elements (e.g. CometChat) (2026-04-01) -
Updated dependencies [
197eeda]:- @posthog/core@1.24.5
- @posthog/types@1.364.5
1.364.4
Patch Changes
- #3298
2365df5Thanks @TueHaulund! - fix: skip deep copy for snapshot/exception events to prevent stack overflow on deeply nested DOM trees (2026-03-31) - Updated dependencies []:
- @posthog/types@1.364.4
1.364.3
Patch Changes
- #3300
bab5f3aThanks @dustinbyrne! - Strip workspace:* references from lib/package.json after build (2026-03-31) - Updated dependencies []:
- @posthog/types@1.364.3
1.364.2
Patch Changes
- #3297
341caafThanks @marandaneto! - fix: wrap sendBeacon body in Blob to ensure Content-Type header is set (2026-03-30) - Updated dependencies [
a863914]:- @posthog/core@1.24.4
- @posthog/types@1.364.2
1.364.0
Minor Changes
- #3285
00a5079Thanks @pauldambra! - Reject the strings "undefined" and "null" in posthog.identify(). All invalid distinct IDs now log a critical console error (always visible, not debug-only). (2026-03-27)
Patch Changes
- #3286
8d34289Thanks @marandaneto! - Use async native CompressionStream for gzip compression to avoid blocking the main thread (2026-03-27) - Updated dependencies [
8d34289]:- @posthog/core@1.24.2
- @posthog/types@1.364.0
1.363.6
Patch Changes
- #3279
32edaadThanks @pauldambra! - Bump @posthog/rrweb packages to 0.0.51, which includes:- PostHog/posthog-rrweb#145: fix: handle cross-origin iframe errors during stop handler cleanup
- PostHog/posthog-rrweb#148: fix: mask textarea innerText mutations
- PostHog/posthog-rrweb#150: fix: guard WebGLRenderingContext access for iOS compatibility
- PostHog/posthog-rrweb#151: refactor: extract slimDOMDefaults into shared function
- PostHog/posthog-rrweb#152: fix: improve nested CSS rule handling
- PostHog/posthog-rrweb#153: fix: allow clearing adopted stylesheets with empty strings
- PostHog/posthog-rrweb#154: fix: prevent object reference mutation breaking remote CSS replay
- PostHog/posthog-rrweb#156: fix: catch all SecurityError variants in stop handler cleanup (2026-03-26)
- Updated dependencies []:
- @posthog/types@1.363.6
1.363.5
Patch Changes
-
#3278
c59dc90Thanks @dustinbyrne! - Add tree-shakeable ESM extension-bundles entry point for slim builds (2026-03-25) -
#3274
ba08262Thanks @pauldambra! - fix: document visibility change shoudln't capture dead click (2026-03-25) -
Updated dependencies [
ba08262]:- @posthog/types@1.363.5
1.363.3
Patch Changes
- #3253
42fbd41Thanks @marandaneto! - Reduce browser SDK bundle size by ~6.6 KB (-3.7%) through code modernization, build config tuning, string deduplication, enum-to-const conversions, and property access shorthand getters. (2026-03-23) - Updated dependencies []:
- @posthog/types@1.363.3
1.363.0
Minor Changes
- #3247
7efa558Thanks @dmarticus! - prevent silent identity switch during bootstrap and auto-identify anonymous users (2026-03-20)
Patch Changes
- #3245
1acd6fdThanks @dmarticus! - handle plain array and object forms in overrideFeatureFlags (2026-03-20) - Updated dependencies [
1acd6fd]:- @posthog/types@1.363.0
1.362.0
Minor Changes
- #3244
ff8a93eThanks @sampennington! - Fixed $set_once initial person properties (e.g. $initial_current_url) not being included with $identify calls when they had already been sent with a prior event. This ensures initial properties are reliably set when identifying users across subdomains, even if an anonymous event was captured first. (2026-03-18)
Patch Changes
- Updated dependencies [
9cd2313]:- @posthog/core@1.24.0
- @posthog/types@1.362.0
1.361.1
Patch Changes
- #3249
c265d62Thanks @marandaneto! - fix: preserve_overrideSDKInfofrom terser mangling so wrapper SDKs can call it (2026-03-18) - Updated dependencies []:
- @posthog/types@1.361.1
1.361.0
Minor Changes
-
#3201
552c018Thanks @frankh! - Add a serviceName config option to logs config (2026-03-18) -
#3240
e4a58d0Thanks @marandaneto! - Add internal_overrideSDKInfomethod to allow wrapper SDKs to override$liband$lib_versionevent properties (2026-03-18) -
#3241
fe1fd7bThanks @dustinbyrne! - feat: addadvanced_feature_flags_dedup_per_sessionconfig option to scope$feature_flag_calleddeduplication to the current session (2026-03-18)
Patch Changes
-
#3239
bf4f078Thanks @jonathanlab! - fix: debug mode not persisting across page navigations (2026-03-18) -
#3228
8773fdfThanks @TueHaulund! - fix: restart session recorder when session rotates externally while idle, preventing "Recording not found" for sessions where analytics events triggered session rotation (2026-03-18) -
Updated dependencies [
552c018,fe1fd7b]:- @posthog/types@1.361.0
1.360.2
Patch Changes
- #3236
bc30c2dThanks @dustinbyrne! - fix: Calling reset() now automatically reloads feature flags (2026-03-13) - Updated dependencies [
bc30c2d,bc30c2d]:- @posthog/core@1.23.4
- @posthog/types@1.360.2
1.360.0
Patch Changes
-
#3213
db089fdThanks @TueHaulund! - fix(replay): treat legacy configs without cache_timestamp as freshConfigs persisted by older SDK versions never include a cache_timestamp. Defaulting to 0 treats them as always stale, causing the persisted config to be cleared before start() runs — so recording never starts for customers on older core SDK versions paired with the latest CDN recorder. (2026-03-09)
-
#3207
c5a37cbThanks @dustinbyrne! - fix: PostHogFeatureFlags uses a TreeShakeabletype (2026-03-09) -
Updated dependencies [
c5a37cb]:- @posthog/types@1.360.0
1.359.1
Patch Changes
- #3204
2b0cd52Thanks @marandaneto! - chore: upgrade dompurify to 3.3.2 (2026-03-06) - Updated dependencies []:
- @posthog/types@1.359.1
1.359.0
Minor Changes
- #3166
9180726Thanks @dustinbyrne! - feat: Tree-shake feature flags (2026-03-05)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.359.0
1.358.1
Patch Changes
-
#3191
9f41d26Thanks @TueHaulund! - fix(replay): fall back to persisted config when remote config fetch failsWhen the remote config fetch failed (network error, ad blocker, CDN outage), the SDK received an empty
{}response with nosessionRecordingkey. TheonRemoteConfighandler returned early without ever setting_receivedFlags = true, leaving the recording permanently stuck inpending_configstatus for the entire page session.This removes the
_receivedFlagsgate entirely. The 1-hour TTL on persisted config (added in #3051, increased from 5 minutes) and the stale-config retry in_onScriptLoaded(added in #3093) already prevent recording from starting with outdated config. The additional gate was redundant and created a deadlock when the config fetch failed.Now when the config fetch fails,
startIfEnabledOrStop()is called and falls back to persisted config from a previous page load. If no persisted config exists (first-ever visit), recording is correctly disabled rather than silently stuck. (2026-03-04) -
#3198
9d0df0eThanks @TueHaulund! - Reduce session replay memory pressure by tracking per-event sizes in SnapshotBuffer, eliminating redundant JSON.stringify calls during buffer operations. Also bumps @posthog/rrweb to 0.0.46 which uses FNV-1a hash-based canvas frame deduplication instead of storing full base64 strings. (2026-03-04) -
Updated dependencies []:
- @posthog/types@1.358.1
1.358.0
Minor Changes
- #3165
0e08337Thanks @dustinbyrne! - feat: Tree-shake surveys, toolbar, exceptions, conversations, logs, experiments (2026-03-03)
Patch Changes
- #3164
20c1ff2Thanks @dustinbyrne! - Add Extension interface for tree-shakable extensions (2026-03-03) - Updated dependencies []:
- @posthog/types@1.358.0
1.357.0
Minor Changes
- #3169
4f885c0Thanks @marandaneto! - feat: add local sampleRate config for session recording (2026-03-02)
Patch Changes
- #3179
0dce119Thanks @TueHaulund! - Bump @posthog/rrweb-* to 0.0.45 — reuses a single OffscreenCanvas in the canvas recording worker instead of allocating a new one per frame, fixing a memory leak in Safari where GPU-backed canvas resources were not being garbage collected promptly (2026-03-02) - Updated dependencies [
4f885c0]:- @posthog/types@1.357.0
1.356.2
Patch Changes
-
#3174
e9127d8Thanks @TueHaulund! - Detect and report when rrweb fails to initialize. rrweb'srecord()silently swallows startup errors and returnsundefined, which previously left the SDK reporting an active recording status while capturing zero data. The SDK now checks the return value and reports a newrrweb_errorstatus, making the failure visible in debug properties. (2026-03-02) -
#3175
6ee5f12Thanks @TueHaulund! - Fix memory leak in canvas recording on Safari < 16.4 where ImageBitmaps were never closed when OffscreenCanvas was unavailable in the web worker. (2026-03-02) -
#3178
186871aThanks @TueHaulund! - Skip canvas FPS recording entirely on browsers without OffscreenCanvas support (Safari < 16.4) instead of running a wasteful requestAnimationFrame loop that can never produce data. Also includes displayWidth/displayHeight in canvas mutation data for correct replay sizing. (2026-03-02) -
#3176
87bae20Thanks @dustinbyrne! - fix: Drop explicit exports (2026-03-02) -
#3172
2e46959Thanks @dustinbyrne! - fix: Compressed requests use ArrayBuffer (2026-03-02) -
Updated dependencies []:
- @posthog/types@1.356.2
1.356.0
Minor Changes
- #3142
ec54fd8Thanks @dmarticus! - Add feature_flag_cache_ttl_ms config to prevent stale flag values (2026-02-26)
Patch Changes
-
#3154
a47179cThanks @slshults! - fix: Improve tablet device type detection when Chrome sends desktop-like UA stringsChrome on Android tablets defaults to "request desktop site" mode, sending a UA string indistinguishable from desktop Linux. This uses the Client Hints API (navigator.userAgentData.platform) and touch capability (navigator.maxTouchPoints) to correctly classify these devices as Tablet or Mobile when UA-based detection falls through to the Desktop default. (2026-02-26)
-
#3145
d741668Thanks @dmarticus! - Adds a remote_config_refresh_interval_ms config option to control how often feature flags are automatically refreshed in long-running sessions. (2026-02-26) -
Updated dependencies [
ec54fd8,d741668]:- @posthog/types@1.356.0
1.354.2
Patch Changes
- #3153
67cf41eThanks @dustinbyrne! - fix: Add additional legacy exports for fully qualified dist and lib exports (2026-02-25) - Updated dependencies []:
- @posthog/types@1.354.2
1.354.1
Patch Changes
- #3148
9ae20e7Thanks @dustinbyrne! - fix: Expose all export paths (2026-02-25) - Updated dependencies []:
- @posthog/types@1.354.1
1.354.0
Minor Changes
- #3080
4d0c783Thanks @dustinbyrne! - feat: Introduce internal config to improve tree-shaking (2026-02-25)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.354.0
1.353.0
Minor Changes
- #3135
fba7e5bThanks @dustinbyrne! - feat: Persist $user_state to cookie for server-side access (2026-02-23)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.353.0
1.352.1
Patch Changes
-
#3129
6bfa003Thanks @pauldambra! - fix: no need to put rrweb and friends directly on window in posthog-recorder (2026-02-23) -
#3131
ad26474Thanks @veryayskiy! - Fix issue with toolbar interferring distinct id in conversations (2026-02-23) -
Updated dependencies []:
- @posthog/types@1.352.1
1.352.0
Minor Changes
- #3121
c3c9780Thanks @veryayskiy! - Ability to retrieve previous conversations (2026-02-20)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.352.0
1.351.4
Patch Changes
- #3119
2649a9aThanks @dmarticus! - Adds a fresh option to getFeatureFlag(), getFeatureFlagResult(), and isFeatureEnabled() that only returns values loaded from the server, not cached localStorage values. (2026-02-19) - Updated dependencies [
2649a9a]:- @posthog/types@1.351.4
1.351.0
Minor Changes
- #3115
8655261Thanks @veryayskiy! - Strip markdown in tickets list (2026-02-18)
Patch Changes
- #3107
9dbc05eThanks @ablaszkiewicz! - warning on manual capture('$exception') (2026-02-18) - Updated dependencies [
9dbc05e]:- @posthog/types@1.351.0
- @posthog/core@1.23.1
1.350.0
Minor Changes
- #2895
1b47203Thanks @benjackwhite! - RemoteConfig (config.js) has been loaded for ages and is in use by us in production. This PR makes it the sole config loading mechanism for posthog-js, removing the legacy /flags/?v=2&config=true path and the __preview_remote_config gate. (2026-02-17)
Patch Changes
- Updated dependencies [
1b47203]:- @posthog/types@1.350.0
1.348.0
Minor Changes
- #3108
c4ca045Thanks @veryayskiy! - Support multiple tickets (2026-02-17)
Patch Changes
1.347.2
Patch Changes
-
#3094
0d30218Thanks @TueHaulund! - feat(replay): add $snapshot_max_depth_exceeded debug property and bump rrweb to 0.0.42 with DOM depth limit (2026-02-13) -
#3093
f19b7f2Thanks @TueHaulund! - fix(replay): retry session recording start when persisted remote config is stale (2026-02-13) -
Updated dependencies []:
- @posthog/types@1.347.2
1.345.5
Patch Changes
- #3060
7437982Thanks @pauldambra! - Add missingfeatureFlagsproperty andOverrideFeatureFlagsOptionstype toPostHoginterface, restoreset_configto the loaded callback type, and addfeatureFlagsReloadingtoon()event types (2026-02-11) - Updated dependencies [
7437982]:- @posthog/types@1.345.5
1.345.4
Patch Changes
- #3074
4e7fda9Thanks @marandaneto! - fix: session replay respects the network_timing remote config (2026-02-11) - Updated dependencies []:
- @posthog/types@1.345.4
1.345.3
Patch Changes
- #3064
50ebdfbThanks @jordanm-posthog! - Fixed an issue where Dead Clicks could continue being captured after being disabled via remote config. (2026-02-10) - Updated dependencies [
0acf16f]:- @posthog/core@1.22.0
- @posthog/types@1.345.3
1.345.0
Minor Changes
- #2919
fe8090cThanks @dustinbyrne! - Add$feature_flag_errorproperty to$feature_flag_calledevents (2026-02-09)
Patch Changes
- #3066
90db5d4Thanks @pauldambra! - fix: remote config cache invalidation was too aggressive (2026-02-09) - Updated dependencies [
fe8090c]:- @posthog/types@1.345.0
1.343.1
Patch Changes
- #3051
aa712a3Thanks @pauldambra! - fix: replay remote config cache should be invalidated periodically (2026-02-09) - Updated dependencies []:
- @posthog/types@1.343.1
1.343.0
Minor Changes
- #3048
dd3328fThanks @veryayskiy! - Do not show identification form if user is identified (2026-02-09)
Patch Changes
- #3049
8d9bb16Thanks @pauldambra! - fix: sampled: true in persistence if legacy and should be ignored (2026-02-09) - Updated dependencies []:
- @posthog/types@1.343.0
1.342.1
Patch Changes
- #3039
8f75daeThanks @hpouillot! - fix(err): fix console error capturing (2026-02-06) - Updated dependencies [
8f75dae]:- @posthog/core@1.20.1
- @posthog/types@1.342.1
1.342.0
Minor Changes
- #3032
19d59eaThanks @dmarticus! - add featureFlagsReloading event for tracking flag reload state (2026-02-05)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.342.0
1.340.0
Minor Changes
- #3024
2b2725eThanks @veryayskiy! - Support widget position (2026-02-04)
Patch Changes
- Updated dependencies [
bb62809]:- @posthog/core@1.20.0
- @posthog/types@1.340.0
1.338.0
Minor Changes
- #3020
5ccf27eThanks @veryayskiy! - Fix issue with contrast colors in support widget (2026-02-03)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.338.0
1.337.0
Minor Changes
-
#2996
7768010Thanks @matheus-vb! - Filter out flags marked as failed before merging with cached values, preventing transient backend errors from overwriting previously evaluated flag states (2026-02-03) -
#3000
4a1af3bThanks @veryayskiy! - Render markdown in support product (2026-02-03)
Patch Changes
1.336.2
Patch Changes
-
#2985
2ed9623Thanks @adboio! - support custom banner container for product tours (2026-01-29) -
#2991
2b32a60Thanks @lricoy! - treat undefined and null the same when receiving config (2026-01-29) -
#2973
c1aa45cThanks @lricoy! - make attribution opt-in by default to reduce memory usage (2026-01-29) -
Updated dependencies []:
- @posthog/types@1.336.2
1.336.0
Minor Changes
- #2954
228930aThanks @dustinbyrne! - feat: AddgetFeatureFlagResultmethod (2026-01-28)
Patch Changes
- Updated dependencies [
228930a]:- @posthog/types@1.336.0
1.334.0
Minor Changes
- #2802
f8c17bcThanks @pauldambra! - feat: add external_scripts_inject_target config to control script injection location (2026-01-22)
Patch Changes
-
#2950
8543f0fThanks @fuziontech! - fix(web-vitals): reduce memory leak in SPAs- Upgrade web-vitals from v4.2.4 to v5.1.0 (includes internal memory fixes from v5.0.3)
- Remove duplicate observer creation on URL change
Note: web-vitals has inherent memory accumulation in SPAs due to internal state. The v5 upgrade reduces this but doesn't fully eliminate it since web-vitals doesn't provide cleanup functions (Issue #629 was closed as "not planned"). (2026-01-22)
-
Updated dependencies []:
- @posthog/types@1.334.0
1.333.0
Minor Changes
- #2942
994206dThanks @veryayskiy! - Send context on sendMessage (2026-01-21)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.333.0
1.331.2
Patch Changes
- #2939
6442f5dThanks @dustinbyrne! - fix: Rate limiting configuration changes are respected (2026-01-20) - Updated dependencies []:
- @posthog/types@1.331.2
1.331.0
Minor Changes
-
#2900
23770e9Thanks @dmarticus! - RenamedevaluationEnvironmentstoevaluationContextsfor clearer semantics. The term "contexts" better reflects that this feature is for specifying evaluation contexts (e.g., "web", "mobile", "checkout") rather than deployment environments (e.g., "staging", "production").Deprecated
posthog.initoptionevaluationEnvironmentsis now deprecated in favor ofevaluationContexts. The old property will continue to work and will log a deprecation warning. It will be removed in a future major version.
Migration Guide
// Before posthog.init('<ph_project_api_key>', { evaluationEnvironments: ['production', 'web', 'checkout'], }) // After posthog.init('<ph_project_api_key>', { evaluationContexts: ['production', 'web', 'checkout'], }) ``` (2026-01-19)
Patch Changes
- Updated dependencies [
23770e9]:- @posthog/core@1.11.0
- @posthog/types@1.331.0
1.330.0
Minor Changes
- #2929
6695383Thanks @veryayskiy! - Add more context to a ticket when created (2026-01-19)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.330.0
1.329.0
Minor Changes
- #2927
da78b8cThanks @veryayskiy! - Remove loading state in support product (2026-01-19)
Patch Changes
- #2926
3676972Thanks @pawel-cebula! - Fix TypeError when logging objects with null/undefined property values in flattenObject (2026-01-19) - Updated dependencies []:
- @posthog/types@1.329.0
1.328.0
Minor Changes
- #2925
ce4566dThanks @TueHaulund! - Restore fetch wrappers to most recent working version (2026-01-17)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.328.0
1.327.0
Minor Changes
- #2923
b8b7f90Thanks @TueHaulund! - Fixed issue with fetch wrappers reconsuming request bodies and generating mismatched FormData boundaries (2026-01-17)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.327.0
1.325.0
Minor Changes
- #2913
262cb4bThanks @TueHaulund! - Ensure we always pass RequestInit object to wrapped fetch (2026-01-16)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.325.0
1.323.0
Minor Changes
- #2902
584657aThanks @TueHaulund! - Ensure wrapped fetch() passes duplex option when required (2026-01-15)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.323.0
1.322.0
Minor Changes
- #2904
b9fb2e2Thanks @veryayskiy! - Fix the issue with _currentTicketId (2026-01-15)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.322.0
1.320.0
Minor Changes
- #2875
7662025Thanks @lucasheriques! - chore(deps): bump preact from 10.19.3 to 10.28.0 to fix security vulnerability (2026-01-13)
Patch Changes
- Updated dependencies []:
- @posthog/types@1.320.0
1.319.2
Patch Changes
- #2864
f64ebefThanks @rafaeelaudibert! - We were missing some public definitions inside@posthog/typesso let's fix them here. We've also fixed the typing inside theloadedcallback (2026-01-13) - Updated dependencies [
f64ebef]:- @posthog/types@1.319.2
1.319.0
Minor Changes
Patch Changes
- #2873
ec5b64bThanks @pauldambra! - fix: use property based testing to expose another edge case bug in checkAndGetSessionAndWindowId (2026-01-12) - Updated dependencies []:
- @posthog/types@1.319.0
1.318.2
Patch Changes
- #2871
4f73495Thanks @pauldambra! - fix: detecting activity timestamp should not compare null to numbers (2026-01-12) - Updated dependencies []:
- @posthog/types@1.318.2
1.316.1
Patch Changes
-
#2846
5ce7252Thanks @ordehi! - Fix survey URL prefill to respect branching/skip logicWhen using URL parameters to prefill survey responses (e.g.,
?q0=9), the SDK now correctly respects the survey's branching configuration. Previously, prefilled answers would always advance to the next sequential question, ignoring any skip logic. (2026-01-09) -
Updated dependencies []:
- @posthog/types@1.316.1
1.316.0
Minor Changes
- #2851
d4bf005Thanks @veryayskiy! - Expose Conversations API Methods for Custom UI (2026-01-08)
Patch Changes
- #2856
c1ed63bThanks @marandaneto! - chore: expose default stack parser creator (2026-01-08) - Updated dependencies [
fba9fb2,c1ed63b]:- @posthog/core@1.9.1
- @posthog/types@1.316.0
1.315.0
Minor Changes
-
#2849
8ddf472Thanks @veryayskiy! - separate enable conversation with enable conversations widget (2026-01-06) -
#2839
83b03feThanks @rafaeelaudibert! - Release new @posthog/types library to make it easy for those using the script version ofposthog-jsto properly typewindow.posthog(2026-01-06)
Patch Changes
- Updated dependencies [
83b03fe]:- @posthog/types@1.315.0
1.313.0
Minor Changes
- #2832
f050f6cThanks @rafaeelaudibert! - Introduce custom cookie properties for localStorage+cookie persistence using the newcookie_persisted_propertiesproperty. This allows people to opt-in to store properties in cookies even inlocalstorage+cookiesmode (2026-01-01)
1.312.0
Minor Changes
-
#2834
548b466Thanks @ordehi! - fix: ClearPageViewManagerstate on session rotation to prevent cross-session duration pollutionWhen a browser tab is backgrounded and the session rotates (30 min idle or 24 hour max),
PageViewManagernow clears its state. This prevents$prev_pageview_durationfrom spanning session boundaries, which was causing impossibly large values (94+ hours observed) in web analytics "Average Time on Page" metrics.Users who implemented workarounds for inflated
$prev_pageview_durationvalues (e.g., capping at 30 minutes) may want to review those after upgrading, as the root cause is now fixed. (2025-12-31)
1.311.0
Minor Changes
-
#2813
4b7443cThanks @ordehi! - feat(flags): add updateFlags() method for injecting flags without network requestAdds
posthog.updateFlags(flags, payloads?, options?)to inject feature flag values from an external source (e.g., server-side evaluation, edge middleware) without making a network request. Supports{ merge: true }option to merge with existing flags instead of replacing. (2025-12-29)
1.310.2
Patch Changes
-
#2812
ad42eaeThanks @lucasheriques! - fix(surveys): queue callbacks when fetch is in progress instead of returning error (2025-12-29) -
#2814
3da6a4cThanks @jurajmajerik! - Persist $device_id to cookies so it survives localStorage clears (2025-12-29)
1.310.0
Minor Changes
-
#2770
6851061Thanks @daibhin! - feat: allow exception autocapture to be programatically enabled / disabled (2025-12-22) -
#2792
f7372c8Thanks @adboio! - add event/action triggers for product tours (2025-12-22) -
#2790
96f42beThanks @adboio! - fix: hosted survey auto-submit behavior only submits skipped questions (2025-12-22) -
#2786
2c54d15Thanks @adboio! - emit new "survey abandoned" event on pageleave (2025-12-22) -
#2787
b676b4dThanks @lucasheriques! - feat: allow customizing text colors on web and react native (2025-12-22)
Patch Changes
- Updated dependencies [
b676b4d]:- @posthog/core@1.9.0
1.306.2
Patch Changes
- #2730
79184bdThanks @ablaszkiewicz! - include synthetic exception in console.error capture (2025-12-15)
1.301.2
Patch Changes
-
#2690
e9c00fdThanks @robbie-c! - Related to https://www.wiz.io/blog/critical-vulnerability-in-react-cve-2025-55182We didn't include any of the vulnerable deps in any of our packages, however we did have them as dev / test / example project dependencies.
There was no way that any of these vulnerable packages were included in any of our published packages.
We've now patched out those dependencies.
Out of an abundance of caution, let's create a new release of all of our packages. (2025-12-04)
-
Updated dependencies [
e9c00fd]:- @posthog/core@1.7.1
1.301.1
Patch Changes
- #2666
2004d36Thanks @pauldambra! - fix: session id rotation relied on in-memory cache which would be stale after log idle periods - particularly with multiple windows in play (2025-12-04)
1.300.0
Minor Changes
- #2603
e1617d9Thanks @dmarticus! - add $feature_flag_evaluated_at properties to $feature_flag_called events (2025-12-03)
Patch Changes
-
#2670
4487d6bThanks @pauldambra! - A click while holding a modifier key (CTRL, ALT, CMD, Windows) shouldn't ever count as a dead click - so that we don't pick up e.g. open in a new tab as a dead click (2025-12-03) -
#2677
0e67750Thanks @lucasheriques! - chore: allow customizing text input and background for surveys (2025-12-03) -
Updated dependencies [
e1617d9]:- @posthog/core@1.7.0
1.299.0
Minor Changes
-
#2641
f9c4dbaThanks @adboio! - add survey cancellation events (2025-12-01) -
#2642
37e4f76Thanks @rafaeelaudibert! - Add newpayloadentry to theEarlyAccessFeaturetype (2025-12-01) -
#2661
aaad806Thanks @adboio! - add support for surveys triggered by actions with event property filters (2025-12-01)
Patch Changes
- #2582
21365ffThanks @pauldambra! - fix: properly cleanup in network plugin (2025-12-01)
1.298.1
Patch Changes
- #2592
7782dd9Thanks @marandaneto! - fix: session replay on react native web (2025-11-24)
1.298.0
Minor Changes
- #2619
86dab38Thanks @hpouillot! - package deprecation (2025-11-24)
Patch Changes
- Updated dependencies [
86dab38]:- @posthog/core@1.6.0
1.297.0
Minor Changes
- #2578
91f41eeThanks @rafaeelaudibert! - Output confirmation log message to the user when overriding feature flags to improve user feedback on whether the action actually did something or not (2025-11-19)
Patch Changes
- #2575
8acd88fThanks @hpouillot! - fix frame platform property for $exception events (2025-11-19) - Updated dependencies [
8acd88f]:- @posthog/core@1.5.3
1.296.1
Patch Changes
- #2590
ab85422Thanks @pauldambra! - fix: don't rely on order of method calls to gate calling url
1.293.0
Minor Changes
- #2565
f2426dbThanks @pauldambra! - feat: ignore rageclicks by content.
Patch Changes
- #2570
de80a41Thanks @pauldambra! - fix: rageclick detection should use event timestamp not current time
1.292.0
Minor Changes
- #2519
7c16ff7Thanks @rodrigomarcolin! - Made rageclick detection fully parametrizable with configurable threshold_px, timeout_ms, and click_count, while preserving previous default behavior.
1.291.0
Minor Changes
- #2557
c8c7de2Thanks @pauldambra! - feat: support strict minimum duration (more accurate on full page load)
1.290.0
Minor Changes
- #2553
8a2b790Thanks @pauldambra! - feat: yield to the main thread during posthog init
1.289.0
Minor Changes
- #2551
10be1b0Thanks @dmarticus! - Support bootstrapping feature flags during SSR in ReactJS
1.286.0
Minor Changes
- #2547
cd8bcd7Thanks @TueHaulund! - Fixed a bug where configuration overrides for session recording would not be applied if the recorder module was still loading
1.285.1
Patch Changes
- #2545
c26a12cThanks @pauldambra! - fix: allow session ending payload when recording is idle
1.285.0
Minor Changes
- #2503
e95a9d5Thanks @pauldambra! - feat: store previous and next session id in session recording
1.284.0
Minor Changes
-
#2529
882d823Thanks @MattBro! - feat(surveys): add URL prefill and auto-submit supportSurveys can now be prefilled and automatically submitted via URL parameters.
New configuration options:
posthog.init('token', { surveys: { prefillFromUrl: true, autoSubmitIfComplete: true, autoSubmitDelay: 800, }, })URL format:
?q0=1&q1=8&auto_submit=trueq{N}= question index (0-based)- Value = choice index or rating value
auto_submit=trueenables auto-submission
Supported question types:
- Single choice (choice index)
- Multiple choice (multiple q{N} params)
- Rating (numeric value, validated against scale)
Use cases:
- Pre-filled NPS surveys from email campaigns
- One-click survey responses from notifications
- SMS surveys with embedded feedback
- QR code surveys at events
1.282.0
Minor Changes
- #2517
46e3ca6Thanks @pauldambra! - feat: add a component that will wrap your components and capture an event when they are in view in the browser
Patch Changes
- #2517
46e3ca6Thanks @pauldambra! - fix: complete react sdk featureflag component refactor
1.281.0
Minor Changes
- #2502
751b440Thanks @pauldambra! - fix: bucketed rate limiter can calculate tokens without a timer
Patch Changes
-
#2500
71ae0d2Thanks @pauldambra! - fix: don't poll surveys while the page is hidden -
Updated dependencies [
751b440]:- @posthog/core@1.4.0
1.280.1
Patch Changes
-
#2492
2b13291Thanks @pauldambra! - fix: extendUrlParams should always replace unless the caller says otherwise -
#2491
130c9e0Thanks @pauldambra! - fix: correctly update the retry count URL parameter -
#2485
d7dced1Thanks @pauldambra! - fix: stop polling when the retry queue is empty
1.279.3
Patch Changes
1.279.1
Patch Changes
- #2469
b161bb3Thanks @pauldambra! - fix: stop heatmap buffer interval when hidden
1.279.0
Minor Changes
- #2463
3075888Thanks @pauldambra! - fix: remove rrweb types as a peer dependency
1.276.0
Minor Changes
- #2444
d50899eThanks @pauldambra! - chore: bump posthog rrweb version - not generally used yet
1.275.2
Patch Changes
-
#2431
7d45a7aThanks @marandaneto! - fix: remove deprecated attribute $exception_personURL from exception events -
Updated dependencies [
daf919b,7d45a7a]:- @posthog/core@1.3.0
1.275.1
Patch Changes
- #2422
4e15fdaThanks @pauldambra! - fix: possible memory leak in session id replacement in cookieless mode
1.275.0
Minor Changes
- #2426
ae941c2Thanks @thmsobrmlr! - Apply $current_url masking in web vitals and heatmaps extensions.
1.274.3
Patch Changes
- #2423
2d4eac4Thanks @pauldambra! - fix: another small potential memory leak in the recorder wrapping code"
1.274.2
Patch Changes
- #2421
43b8029Thanks @pauldambra! - fix: potential source of memory leak in recorder mutation throttler
1.274.0
Minor Changes
- #2404
39ace01Thanks @pauldambra! - feat: remove eager loaded replay and reduce bundle size by 14.8%
Patch Changes
- Updated dependencies [
e19a384]:- @posthog/core@1.2.3
1.273.1
Patch Changes
- #2412
25a8846Thanks @pauldambra! - fix: rely on 'state' less when reporting replay status
1.273.0
Minor Changes
- #2408
66b12f8Thanks @thmsobrmlr! - Fixes an issue where the event queue was not started until a page reload after callingopt_in_capturing()
1.272.1
Patch Changes
- #2395
4a39a10Thanks @pauldambra! - fix: increase max depth for app state diffing
1.272.0
Minor Changes
- #2405
cdfbd6dThanks @pauldambra! - fix: session recording config can be false, correct the types
1.271.0
Minor Changes
- #2385
7373238Thanks @pauldambra! - feat: switch replay to lazy loaded by default"
1.270.1
Patch Changes
- #2390
244b3adThanks @hpouillot! - fix react sourcemaps - revert: #2390 to fix persistence bug with surveys
1.270.0
Minor Changes
- #2355
9eccbabThanks @lucasheriques! - fix: use persistence for surveys if localStorage usage is enabled
Patch Changes
- #2396
13c6667Thanks @pauldambra! - fix: no need to estimate the size of all rrweb events before compressing some of them
1.269.1
Patch Changes
- #2393
a3b64e6Thanks @pauldambra! - chore: variable rename so i can trigger a releas
1.269.0
Minor Changes
- #2369
2a6ea65Thanks @dmarticus! - This PR implements support for evaluation environments in the posthog-js SDK, allowing users to specify which environment tags their SDK instance should use when evaluating feature flags.
1.268.9
Patch Changes
-
#2378
b920bacThanks @pauldambra! - fix: don't mangle to $ in no external or es5 builds -
#2376
b5eb605Thanks @pauldambra! - fix: rotating buffer while trigger pending
1.268.6
Patch Changes
- #2368
2102ee4Thanks @pauldambra! - fix: recorder behaviour when idle session is force terminated then restarted
1.268.5
Patch Changes
- #2362
8b570b8Thanks @pauldambra! - fix: over eager rename left a couple of old versions trying to call onRemoteConfig that doesn't exist
1.268.1
Patch Changes
- #2315
fd2c51dThanks @pauldambra! - fix: lazy loaded replay relies on remote config having been persisted in storage to avoid race with config on restart
1.268.0
Minor Changes
- #2345
4f37e77Thanks @lucasheriques! - feat: surveys matching on event properties
1.267.0
Minor Changes
- #2347
5d13bedThanks @pauldambra! - feat: allow ignoring rageclicks on elements by css selector
1.266.1
Patch Changes
-
#2330
da07e41Thanks @hpouillot! - use error tracking processing from core -
Updated dependencies [
da07e41]:- @posthog/core@1.1.0
1.266.0
Minor Changes
- #2321
b81e152Thanks @pauldambra! - feat: expose rrweb custom events on the public interface of the recorder. not intended for arbitrary public use but useful for internal purposes
1.265.0
Minor Changes
- #2032
822d8dfThanks @lucasheriques! - feat: allow display surveys popups on demand
1.263.0
Minor Changes
- #2294
5137440Thanks @pauldambra! - feat: add a redux logging middleware to posthog-js
1.262.1
Patch Changes
- #2309
28223c1Thanks @pauldambra! - fix: default to eager loading replay while investigating trigger bug reports
1.262.0
Minor Changes
- #2296
f9fe3baThanks @pauldambra! - feat: switch replay default to lazy loading
1.261.8
Patch Changes
- #2276
97961e4Thanks @dustinbyrne! -isFeatureEnablednow returnsundefined(instead offalse) for missing or disabled feature flags, aligning with the documentation. Previously,undefinedwas returned only before flags had loaded, and missing/disabled flags returnedfalse. This change clarifies the difference between flags that exist but don't match (false) and flags that don’t exist or are disabled (undefined).
1.261.7
Patch Changes
- #2284
bdfe450Thanks @pauldambra! - fix: order of operations when replay does pageview fallback
1.261.5
Patch Changes
- #2270
980f5c4Thanks @lucasheriques! - fix: hosted surveys should ignore any delays
1.261.4
Patch Changes
- #2268
999c63fThanks @pauldambra! - fix: session recorder wrapper had private field that should be public"
1.261.3
Patch Changes
- #2267
f2ac956Thanks @pauldambra! - feat: allow testing of the new lazy loaded session recorder
1.261.2
Patch Changes
-
#2266
9470d97Thanks @pauldambra! - fix: don't mangle variables to `# posthog-js -
#2265
2487d12Thanks @pauldambra! - chore: update to latest rollup and terser
1.261.1
Patch Changes
- #2263
41d3890Thanks @pauldambra! - chore: add unused lazy loaded session recorder to prime CDN
1.260.2
Patch Changes
- #2236
f3269f3Thanks @lucasheriques! - fix: set survey person properties on SDK <1.249.2
1.260.1
Patch Changes
- #2215
1e95d47Thanks @lucasheriques! - fix: always set surveySeen on local storage for old posthog-js versions
1.258.5
Patch Changes
- #2178
db569faThanks @lucasheriques! - - Fix surveys loading with advanced_enable_surveys config
1.258.4
Patch Changes
- #2172
ac254d9Thanks @lucasheriques! - Adds a new config,advanced_enable_surveys, to always enable surveys funcionality in the SDK
1.258.3
Patch Changes
-
#2171
14adc01Thanks @lucasheriques! - Fix early access features accumulation in persistence -
#2170
262cc5cThanks @lucasheriques! - Removes the_renderExternalSurveymethod which is not needed anymore
1.258.2
Patch Changes
- #2111
7114593Thanks @pauldambra! - checks for session activity in other windows when timing out in any particular window, avoids a race condition when proactively marking a session as idle
1.258.1
Patch Changes
- #2120
c7b03cdThanks @lucasheriques! - Updates the renderSurvey and getActiveMatchingSurveys methods to not take any external surveys into consideration