Skip to content

fix(analytics): fall back to server-evaluated feature flags when posthog-js is blocked#3131

Merged
tofikwest merged 2 commits into
mainfrom
tofik/fix-timeline-flag-server-fallback
Jun 12, 2026
Merged

fix(analytics): fall back to server-evaluated feature flags when posthog-js is blocked#3131
tofikwest merged 2 commits into
mainfrom
tofik/fix-timeline-flag-server-fallback

Conversation

@tofikwest

@tofikwest tofikwest commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Problem

Customer report: the is-timeline-enabled PostHog flag was toggled on for org_69cc72ba1ff5244c2f492f7b, but the customer never saw the Timeline tab on the Overview page — while impersonating staff saw it fine. Cache clears, cookies, hard reset, and incognito all failed.

Root cause

The Timeline tab is the only flag-gated UI that depends on the client-side posthog-js flags request (/ingest/flags). When that request is blocked — ad blocker, privacy browser, AdGuard, corporate proxy (all survive incognito and cache clears) — useFeatureFlagEnabled stays undefined forever, so useFeatureFlag returns false and the tab never renders. PostHog documents that the flags endpoint is routinely blocked and that generic proxy paths like /ingest are on public blocklists.

Impersonation proves the server-side flag state is correct: better-auth impersonation uses the customer's own user ID and the same org group, so the flag inputs are identical — the only difference is the staff member's unblocked browser.

The org layout already evaluates three other nav flags server-side via posthog-node (blocker-immune); the timeline flag was the odd one out.

Fix

  • packages/analytics: new ServerFeatureFlagsProvider context + useFeatureFlag now treats a flag as enabled when either the live posthog-js value or the server-evaluated value says so. The OR matters: a blocked client can also serve a stale false persisted from an old session, and only the fresher server value can override it.
  • apps/app [orgId]/layout.tsx: the flag map the layout already fetches server-side (getFeatureFlags(userId, { groups: { organization } })) is now passed into the provider.
  • Zero changes needed at the three call sites (OverviewTabs, FrameworkDetailContent, FrameworkTimeline), and any future useFeatureFlag usage under the org layout is covered automatically.

Behavior notes:

  • For blocked clients, flag toggles now take effect on the next full page load (same staleness model as the existing server-evaluated nav flags).
  • Apps that don't render the provider (portal, trust) keep the exact previous behavior — the context fallback is additive.

Testing

  • 9 new tests in OverviewTabs.test.tsx: hook fallback semantics (no provider / server-true / multivariate string / both-false / stale-live-false-vs-server-true / live-only) + tab rendering through the real component in the blocked-client scenario.
  • @trycompai/analytics typecheck green; app typecheck has zero errors in touched files (remaining failures reproduce identically on main without this change).

🤖 Generated with Claude Code


Summary by cubic

Fallback to server-evaluated PostHog flags when the browser blocks posthog-js, so Timeline and other flag-gated UI render correctly. Handles ad blockers and proxies that previously hid Timeline even when enabled.

  • Bug Fixes
    • Added ServerFeatureFlagsProvider in @trycompai/analytics; useFeatureFlag now enables a flag when the live posthog-js value OR the server-evaluated value is on (true or a non-empty variant).
    • [orgId]/layout.tsx evaluates flags with posthog-node, derives existing nav booleans, and wraps the app shell with ServerFeatureFlagsProvider to pass the full map; existing consumers need no changes.
    • Added tests for hook fallback and Timeline visibility; blocked clients pick up toggles on the next full page load.

Written for commit 022f2b9. Summary will update on new commits.

Review in cubic

…hog-js is blocked

The Timeline tab (is-timeline-enabled) is gated by useFeatureFlag, which
relied solely on the browser's posthog-js /flags request. Ad blockers,
privacy browsers, and corporate proxies block that request (the /ingest
proxy path is on public blocklists), so the flag never resolved and the
tab never rendered for affected customers — while impersonating staff on
unblocked machines saw it fine.

The org layout already evaluates all flags server-side (posthog-node with
the organization group) for nav gating. Provide that map to the client via
a new ServerFeatureFlagsProvider and let useFeatureFlag treat the flag as
enabled when either the live client value or the server-evaluated value
says so. No changes needed at the flag call sites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jun 12, 2026 7:43pm
comp-framework-editor Ready Ready Preview, Comment Jun 12, 2026 7:43pm
portal Ready Ready Preview, Comment Jun 12, 2026 7:43pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@tofikwest tofikwest merged commit 11d41cd into main Jun 12, 2026
11 checks passed
@tofikwest tofikwest deleted the tofik/fix-timeline-flag-server-fallback branch June 12, 2026 20:12
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.82.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants