From 7e084794219fbaffce15461477348859ee38f4a8 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 17:11:22 +0000 Subject: [PATCH] fix(flags): surface that preloadFeatureFlags is ignored on Flutter web posthog-js is initialized by the host app on web, so PostHogConfig.preloadFeatureFlags never reaches it. Setting it to false was a silent no-op. - Warn in debug builds during web setup when preloadFeatureFlags is false (pointing at advanced_disable_feature_flags_on_first_load) or when bootstrap is set. - Document the web gap on preloadFeatureFlags, mirroring the note bootstrap already carries. - Document that identify() and group() reload feature flags regardless of preloadFeatureFlags. Generated-By: PostHog Code Task-Id: b8ef6da1-fe3d-47ac-9901-7406d300f36a --- .changeset/quiet-lions-warn.md | 5 ++ posthog_flutter/lib/posthog_flutter_web.dart | 16 ++++++ posthog_flutter/lib/src/posthog.dart | 6 +++ posthog_flutter/lib/src/posthog_config.dart | 13 ++++- .../test/posthog_flutter_web_setup_test.dart | 53 +++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 .changeset/quiet-lions-warn.md create mode 100644 posthog_flutter/test/posthog_flutter_web_setup_test.dart diff --git a/.changeset/quiet-lions-warn.md b/.changeset/quiet-lions-warn.md new file mode 100644 index 00000000..f8d1d8fd --- /dev/null +++ b/.changeset/quiet-lions-warn.md @@ -0,0 +1,5 @@ +--- +'posthog_flutter': patch +--- + +Warn in debug builds when `preloadFeatureFlags` or `bootstrap` are set on Flutter web, where they are not applied, and document that `identify`/`group` reload feature flags diff --git a/posthog_flutter/lib/posthog_flutter_web.dart b/posthog_flutter/lib/posthog_flutter_web.dart index 33cc43d9..fd5e88c1 100644 --- a/posthog_flutter/lib/posthog_flutter_web.dart +++ b/posthog_flutter/lib/posthog_flutter_web.dart @@ -69,6 +69,22 @@ class PosthogFlutterWeb extends PosthogFlutterPlatformInterface { final ph = posthog; _config = config; + // posthog-js is initialized by the host app, so a few config options never + // reach it. Warn instead of silently ignoring them. + if (!config.preloadFeatureFlags) { + printIfDebug( + 'Warning: PostHogConfig.preloadFeatureFlags is not applied on Flutter web. ' + 'posthog-js is initialized by your app, so set ' + 'advanced_disable_feature_flags_on_first_load in your posthog.init({...}) call instead.', + ); + } + if (config.bootstrap != null) { + printIfDebug( + 'Warning: PostHogConfig.bootstrap is not applied on Flutter web. ' + 'Configure bootstrap in your posthog.init({...}) call instead.', + ); + } + WebCanvasMaskProvider(config).register(); if (config.onFeatureFlags != null && ph != null) { diff --git a/posthog_flutter/lib/src/posthog.dart b/posthog_flutter/lib/src/posthog.dart index b38368e9..ee8157b9 100644 --- a/posthog_flutter/lib/src/posthog.dart +++ b/posthog_flutter/lib/src/posthog.dart @@ -117,6 +117,9 @@ class Posthog { /// /// Returns a [Future] that completes when the identify call has been queued. /// + /// Note that identifying a user reloads feature flags, which issues a + /// `/flags` request even when [PostHogConfig.preloadFeatureFlags] is `false`. + /// /// **Example:** /// ```dart /// await Posthog().identify( @@ -544,6 +547,9 @@ class Posthog { /// /// Returns a [Future] that completes when the group call has been queued. /// + /// Note that setting a group reloads feature flags, which issues a `/flags` + /// request even when [PostHogConfig.preloadFeatureFlags] is `false`. + /// /// **Example:** /// ```dart /// await Posthog().group( diff --git a/posthog_flutter/lib/src/posthog_config.dart b/posthog_flutter/lib/src/posthog_config.dart index 260740ab..2e53065f 100644 --- a/posthog_flutter/lib/src/posthog_config.dart +++ b/posthog_flutter/lib/src/posthog_config.dart @@ -115,7 +115,18 @@ class PostHogConfig { /// Whether feature flags are loaded when the SDK starts. /// - /// Defaults to `true`. + /// Defaults to `true`, which means every SDK start issues a `/flags` request. + /// Set it to `false` if you evaluate flags lazily (via + /// `Posthog().reloadFeatureFlags()`) and want to avoid that request. + /// + /// Note that `Posthog().identify()`, `Posthog().group()` and the + /// `set*PropertiesForFlags` helpers reload feature flags as well, so turning + /// preloading off only removes the request made at startup. + /// + /// **Flutter web:** not applied. The web SDK hooks onto an already-initialized + /// posthog-js instance, so set + /// [`advanced_disable_feature_flags_on_first_load`](https://posthog.com/docs/libraries/js/config) + /// in your `posthog.init({...})` call instead. var preloadFeatureFlags = true; /// Whether the SDK captures application lifecycle events automatically. diff --git a/posthog_flutter/test/posthog_flutter_web_setup_test.dart b/posthog_flutter/test/posthog_flutter_web_setup_test.dart new file mode 100644 index 00000000..ec28b787 --- /dev/null +++ b/posthog_flutter/test/posthog_flutter_web_setup_test.dart @@ -0,0 +1,53 @@ +@TestOn('browser') +library; + +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:posthog_flutter/posthog_flutter.dart'; +import 'package:posthog_flutter/posthog_flutter_web.dart'; + +/// posthog-js is initialized by the host app on web, so options the plugin +/// cannot forward must warn instead of silently doing nothing. +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + Future> setupCapturingLogs(PostHogConfig config) async { + final logs = []; + await runZoned( + () => PosthogFlutterWeb().setup(config), + zoneSpecification: ZoneSpecification( + print: (_, __, ___, line) => logs.add(line), + ), + ); + return logs; + } + + test('warns that preloadFeatureFlags is not applied on web', () async { + final config = PostHogConfig('test_project_token'); + config.preloadFeatureFlags = false; + + final logs = await setupCapturingLogs(config); + + final warnings = + logs.where((line) => line.contains('preloadFeatureFlags')).toList(); + expect(warnings, hasLength(1)); + expect(warnings.single, + contains('advanced_disable_feature_flags_on_first_load')); + }); + + test('does not warn when preloadFeatureFlags keeps its default', () async { + final logs = await setupCapturingLogs(PostHogConfig('test_project_token')); + + expect(logs.where((line) => line.contains('preloadFeatureFlags')), isEmpty); + }); + + test('warns that bootstrap is not applied on web', () async { + final config = PostHogConfig('test_project_token'); + config.bootstrap = PostHogBootstrapConfig(distinctId: 'user-1'); + + final logs = await setupCapturingLogs(config); + + expect(logs.where((line) => line.contains('bootstrap')), hasLength(1)); + }); +}