Fixes bug where App Router pages (docs, www/blog) only tracked the
initial page load but not subsequent navigations.
The issue was introduced in PR #35384 which inverted the logic for
App Router telemetry tracking. The condition used a boolean flag
that prevented tracking after the initial page view.
The root cause: useEffect with [appPathname] dependency fires both
on initial mount AND on pathname changes. The flag-based approach
couldn't differentiate between these two cases.
Solution: Track the previous pathname to detect actual changes.
- Initial mount: previousAppPathnameRef is null, skip (initial effect handles it)
- Navigation: previousAppPathnameRef !== appPathname, send telemetry
Before: Only first page view tracked
After: All page navigations tracked (like Pages Router)
Affects: docs app, www app (blog pages)
- Add reset() method to PostHogClient class to clear user identification
- Call posthogClient.reset() before clearLocalStorage() in signout flow
- Include proper error handling and memory leak prevention
- Clear all pending state (identification, groups, events)
Resolves GROWTH-535
Remove backend API calls for page view and page leave tracking,
keeping only client-side PostHog tracking. Generic events and
identify calls remain server-side for now.
- Remove /platform/telemetry/page API call from handlePageTelemetry
- Remove /platform/telemetry/page-leave API call from handlePageLeaveTelemetry
- Both functions now return Promise.resolve() for compatibility
- Client-side PostHog tracking remains fully functional
- Keep sendTelemetryEvent and sendTelemetryIdentify unchanged
* fix: resolve 50% session tracking discrepancy on root route
- Fixes race condition causing ~50% discrepancy in session tracking between client and server on root route
- Implements event queuing to capture telemetry events before PostHog initializes
- Adds session ID correlation to enable unified tracking analysis between client and server events
- Uses sendBeacon API for both pageview and pageleave events to ensure reliable capture even during navigation
- Adds production safeguards with try/catch blocks and memory caps to prevent API errors from breaking tracking
* refactor(posthog-client): reduce max pending events and improve event handling
- Decreased the maximum number of queued events from 200 to 20
- Added the use of the sendBeacon API for pending events to survive page unload
- Added comments to clarify the handling of pending properties and events during posthog initialization
Adds client-side PostHog tracking to run in parallel with server-side telemetry across studio, docs, and www. This enables session replays and resolves a race condition where page views arrive before group assignments resulting in attribution errors.
Changes:
- Created PostHog client wrapper with consent-aware initialization in common package
- Integrated PostHog client calls into existing telemetry functions to send events to both PostHog (client) and backend (server)
- Updated CSP to allow connections to PostHog endpoints
- Added environment variable support for all apps
- PostHog client accepts consent as a parameter and respects user preferences
- Events can be distinguished in PostHog by $lib property (posthog-js vs posthog-node)
- PostHog URL configured based on environment (staging/local uses ph.supabase.green)
- Maintains full backward compatibility with existing telemetry system
Resolves GROWTH-438
Resolves GROWTH-271
* Add third-parties dependency for GTM. Reexport the GTM from the common package.
* Add the TelemetryTagManager to four of the production apps.
* Add the GOOGLE_TAG_MANAGER_ID env var as a turbo dependency to the 4 apps.
* Skip rendering the tag manager if the env var is not set or not running on the platform.
* Fix the prop type to be extracted from the component.
* Add default values for consent to GTM.
* Another try to mimic gtag function.
* Fix a link in www.
* Try another approach.
* try.
* Remove the data-redaction flag.
* Remove extra code.
* Send a sign-up event if GTM is enabled.
* Send only the email to GTM.
* Minor fixes.
* Remove third-parties from pnpm lockfile.
* Lets try to make studio work again.
* Add CSP rules for img loading for GTM.
* Add event for testing.
* Add www.googletagmanager.com to the CSP rules.
* Add Stape to CSP rules.
* Fix stape CSP.
* Clean up the code.
* Remove extra console.log.
* Fix the stape urls for CORS.
* Fix the wrong category for Stape URL.
* Add google ads urls.
* Bump the timeout.
* Add google.com to the img-src for google ads.
* update csp
* remove comment
* update to use google analytics without signals
* add stape to default-src in csp
* move csp to middleware
* add google ads support and fix middleware base path
* remove google tag manager / google ads references from csp. load via stape proxy instead
* add double click url to image src
* add Google Tag Manager URL to CSP configuration
* add ga4 urls to csp
* remove google urls from CSP
---------
Co-authored-by: Alaister Young <a@alaisteryoung.com>
* chore: add usercentrics for consent management
* client component to make next.js happy
* address feedback
* move consent state to common
* fix import
* ensure page events are sent correctly
* add feature flag provider to ui library site
* fix ui lib 500 error
* skip in test env
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Jordi Enric <jordi.err@gmail.com>
There were two bugs when trying to run the integrations page locally
with NEXT_PUBLIC_IS_PLATFORM=false:
1. The IS_PLATFORM check imported from common was not evaluating
correctly to a boolean. This is because I slapped a 'use client' on the
entire common package last year -_-""" which caused all its imports to
be evaluated to functions when used in server components. I have now
moved the 'use client's down to the submodules that actually need it.
2. When the integrations submenu is empty, the navigation menu errors
out because it expects all navigation items to either have children or
have links. Have updated this to gracefully hide empty headers.