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)); + }); +}