GrowthBook Flutter SDK
๐ฏ Feature flags โข ๐งช A/B testing โข ๐ Analytics integration
Quick Start โข Features โข Documentation โข Examples โข Resources
Overview
GrowthBook is an open source feature flagging and experimentation platform. This Flutter SDK allows you to use GrowthBook with your Flutter based mobile application.
Platform Support:
- ๐ฑ Android 21+ โข iOS 12+
- ๐บ tvOS 13+ โข โ watchOS 7+
- ๐ฅ๏ธ macOS โข Windows โข Linux
- ๐ Web (Flutter Web)
โจ Features
- Lightweight - Minimal performance impact
- Type Safe - Full Dart/Flutter type safety
- Caching - Smart caching with TTL and stale-while-revalidate
- Cross-platform - Works on Android, iOS, Web, Desktop
๐๏ธ Core Capabilities
- Feature Flags - Toggle features on/off without code deployments
- A/B Testing - Run experiments with statistical significance
- Targeting - Advanced user segmentation, variation weights and targeting rules
- Tracking - Use your existing event tracking (GA, Segment, Mixpanel, custom)
- Real-time Updates - Features update instantly via streaming
๐ฏ Advanced Features
- Sticky Bucketing - Consistent user experiences across sessions
- Remote Evaluation - Server-side evaluation for enhanced security
- Multi-variate Testing - Test multiple variations simultaneously
- Rollout Management - Gradual feature rollouts with traffic control
๐ Supported Features
Feature | Support | Since Version |
---|---|---|
โ Feature Flags | Full Support | All versions |
โ A/B Testing | Full Support | All versions |
โ Sticky Bucketing | Full Support | โฅ v3.8.0 |
โ Remote Evaluation | Full Support | โฅ v3.7.0 |
โ Streaming Updates | Full Support | โฅ v3.4.0 |
โ Prerequisites | Full Support | โฅ v3.2.0 |
โ Encrypted Features | Full Support | โฅ v3.1.0 |
โ v2 Hashing | Full Support | โฅ v3.1.0 |
โ SemVer Targeting | Full Support | โฅ v3.1.0 |
โ TTL Caching | Full Support | โฅ v3.9.10 |
๐ Quick Start
1. Installation
Add to your pubspec.yaml
:
dependencies:
growthbook_sdk_flutter: ^3.9.10
2. Basic Setup
import 'package:growthbook_sdk_flutter/growthbook_sdk_flutter.dart';
// Initialize the SDK
final sdk = await GBSDKBuilderApp(
apiKey: "sdk_your_api_key",
hostURL: "https://growthbook.io",
attributes: {
'id': 'user_123',
'email': 'user@example.com',
'country': 'US',
},
growthBookTrackingCallBack: (experiment, result) {
// Track experiment exposures
print('Experiment: ${experiment.key}, Variation: ${result.variationID}');
},
).initialize();
// Use feature flags
final welcomeMessage = sdk.feature('welcome_message');
if (welcomeMessage.on) {
print('Feature is enabled: ${welcomeMessage.value}');
}
// Run A/B tests
final buttonExperiment = GBExperiment(key: 'button_color_test');
final result = sdk.run(buttonExperiment);
final buttonColor = result.value ?? 'blue'; // Default color
3. Widget Integration
class MyHomePage extends StatelessWidget {
final GrowthBookSDK sdk;
@override
Widget build(BuildContext context) {
final newDesign = sdk.feature('new_homepage_design');
return Scaffold(
body: newDesign.on
? NewHomepageWidget()
: ClassicHomepageWidget(),
);
}
}
Analytics
final sdk = await GBSDKBuilderApp(
apiKey: "your_api_key",
growthBookTrackingCallBack: (experiment, result) {
// Google Analytics
FirebaseAnalytics.instance.logEvent(
name: 'experiment_viewed',
parameters: {
'experiment_id': experiment.key,
'variation_id': result.variationID,
'variation_name': result.key,
},
);
// Mixpanel
Mixpanel.track('Experiment Viewed', {
'Experiment ID': experiment.key,
'Variation ID': result.variationID,
});
// Custom analytics
YourAnalytics.trackExperiment(experiment, result);
},
).initialize();
๐ Documentation
Configuration Options
final sdk = await GBSDKBuilderApp(
// Required
apiKey: "sdk_your_api_key",
hostURL: "https://growthbook.io",
// User Context
attributes: {
'id': 'user_123',
'email': 'user@example.com',
'plan': 'premium',
'country': 'US',
},
// Performance & Caching
ttlSeconds: 300, // Cache TTL (default: 60s)
backgroundSync: true, // Real-time updates
// Testing & QA
qaMode: false, // Disable randomization for QA
forcedVariations: { // Force specific variations
'button_test': 1,
},
// Analytics Integration
growthBookTrackingCallBack: (experiment, result) {
// Send to your analytics platform
analytics.track('Experiment Viewed', {
'experiment_id': experiment.key,
'variation_id': result.variationID,
'variation_name': result.key,
});
},
// Advanced Features
remoteEval: false, // Server-side evaluation
encryptionKey: "...", // For encrypted features
).initialize();
Feature Flag Usage
// Boolean flags
final isEnabled = sdk.feature('new_feature').on;
// String values
final welcomeText = sdk.feature('welcome_message').value ?? 'Welcome!';
// Number values
final maxItems = sdk.feature('max_items').value ?? 10;
// JSON objects
final config = sdk.feature('app_config').value ?? {
'theme': 'light',
'animations': true,
};
// Check feature source
final feature = sdk.feature('premium_feature');
switch (feature.source) {
case GBFeatureSource.experiment:
print('Value from A/B test');
break;
case GBFeatureSource.force:
print('Forced value');
break;
case GBFeatureSource.defaultValue:
print('Default value');
break;
}
Experiments - A/B Testing
// Define experiment
final experiment = GBExperiment(
key: 'checkout_button_test',
variations: ['๐ Buy Now', '๐ณ Purchase', 'โจ Get It Now'],
weights: [0.33, 0.33, 0.34], // Traffic distribution
);
// Run experiment
final result = sdk.run(experiment);
// Use result
Widget buildButton() {
final buttonText = result.value ?? '๐ Buy Now';
return ElevatedButton(
onPressed: () => handlePurchase(),
child: Text(buttonText),
);
}
// Track conversion
if (purchaseCompleted) {
// Your analytics will receive this via trackingCallBack
}
User Attributes & Targeting
// Update user attributes dynamically
sdk.setAttributes({
'plan': 'enterprise',
'feature_flags_enabled': true,
'last_login': DateTime.now().toIso8601String(),
});
// Target users with conditions
// Example: Show feature only to premium users in US
// This is configured in GrowthBook dashboard, not in code
๐ง Advanced Features
Smart Caching Strategy
The SDK implements an intelligent caching system for optimal performance:
final sdk = await GBSDKBuilderApp(
apiKey: "your_api_key",
ttlSeconds: 300, // Cache TTL: 5 minutes
backgroundSync: true, // Enable background refresh
).initialize();
How it works:
- ๐ Instant Response - Serve cached features immediately
- ๐ Background Refresh - Fetch updates in the background
- โก Stale-While-Revalidate - Show cached data while updating
- ๐ Smart Invalidation - Refresh only when needed
Benefits:
- โ Zero loading delays for feature flags
- โ Always up-to-date with background sync
- โ Reduced API calls with intelligent caching
- โ Offline resilience with cached fallbacks
Sticky Bucketing
Ensure consistent user experiences across sessions:
class MyAppStickyBucketService extends GBStickyBucketService {
@override
Future<Map<String, String>?> getAllAssignments(
Map<String, dynamic> attributes,
) async {
// Retrieve from local storage
final prefs = await SharedPreferences.getInstance();
final json = prefs.getString('gb_sticky_assignments');
return json != null ? jsonDecode(json) : null;
}
@override
Future<void> saveAssignments(
Map<String, dynamic> attributes,
Map<String, String> assignments,
) async {
// Save to local storage
final prefs = await SharedPreferences.getInstance();
await prefs.setString('gb_sticky_assignments', jsonEncode(assignments));
}
}
// Use with SDK
final sdk = await GBSDKBuilderApp(
apiKey: "your_api_key",
stickyBucketService: MyAppStickyBucketService(),
).initialize();
Remote Evaluation
For enhanced security and server-side evaluation:
final sdk = await GBSDKBuilderApp(
apiKey: "your_api_key",
remoteEval: true, // Enable remote evaluation
attributes: userAttributes,
).initialize();
// Features are evaluated server-side
// Sensitive targeting rules never reach the client
Real-time Updates
final sdk = await GBSDKBuilderApp(
apiKey: "your_api_key",
backgroundSync: true, // Enable streaming updates
).initialize();
// Features automatically update when changed in GrowthBook
// No need to restart the app or refresh manually
๐ก Examples
E-commerce App
class ProductPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final sdk = context.read<GrowthBookSDK>();
// Feature flags
final showReviews = sdk.feature('show_product_reviews').on;
final freeShipping = sdk.feature('free_shipping_threshold').value ?? 50.0;
// A/B test for pricing display
final pricingExperiment = GBExperiment(key: 'pricing_display_test');
final pricingResult = sdk.run(pricingExperiment);
return Scaffold(
body: Column(
children: [
ProductImage(),
ProductTitle(),
// Dynamic pricing display based on A/B test
if (pricingResult.value == 'with_discount')
PricingWithDiscount()
else
StandardPricing(),
// Conditional features
if (showReviews) ProductReviews(),
if (freeShipping > 0) FreeShippingBanner(threshold: freeShipping),
AddToCartButton(),
],
),
);
}
}
Gradual Feature Rollout
class NewFeatureService {
final GrowthBookSDK sdk;
NewFeatureService(this.sdk);
bool get isNewDashboardEnabled {
final feature = sdk.feature('new_dashboard_v2');
// Feature is rolled out gradually:
// 0% โ 5% โ 25% โ 50% โ 100%
// Configured in GrowthBook dashboard
return feature.on;
}
Widget buildDashboard() {
return isNewDashboardEnabled
? NewDashboardWidget()
: LegacyDashboardWidget();
}
}
๐ ๏ธ Development
Local Development Setup
1. Clone and Setup
# Clone the repository
git clone https://github.com/growthbook/growthbook-flutter.git
cd growthbook-flutter
# Install dependencies
flutter pub get
# Generate code (for json_serializable)
dart run build_runner build --delete-conflicting-outputs
2. Run Tests
# Run all tests
flutter test
# Run tests with coverage
flutter test --coverage
# Run specific test file
flutter test test/features/feature_test.dart
3. Code Generation
The SDK uses json_serializable
for JSON parsing. When you modify model classes with @JsonSerializable()
, run:
# Watch for changes and auto-generate
dart run build_runner watch
# One-time generation
dart run build_runner build --delete-conflicting-outputs
4. Linting and Formatting
# Check linting
dart analyze
# Format code
dart format .
# Fix auto-fixable issues
dart fix --apply
5. Building Examples
cd example
flutter pub get
flutter run
Testing
// Mock SDK for testing
class MockGrowthBookSDK implements GrowthBookSDK {
final Map<String, dynamic> mockFeatures;
MockGrowthBookSDK({required this.mockFeatures});
@override
GBFeatureResult feature(String key) {
final value = mockFeatures[key];
return GBFeatureResult(
value: value,
on: value == true,
source: GBFeatureSource.force,
);
}
}
// Use in tests
void main() {
testWidgets('shows new feature when enabled', (tester) async {
final mockSDK = MockGrowthBookSDK(
mockFeatures: {'new_feature': true},
);
await tester.pumpWidget(MyApp(sdk: mockSDK));
expect(find.text('New Feature'), findsOneWidget);
});
}
Build Integration
// Different configurations for different environments
final sdk = await GBSDKBuilderApp(
apiKey: kDebugMode
? "sdk_dev_your_dev_key"
: "sdk_prod_your_prod_key",
hostURL: kDebugMode
? "https://growthbook-dev.yourcompany.com"
: "https://growthbook.yourcompany.com",
qaMode: kDebugMode, // Disable randomization in debug
).initialize();
Contributing
We welcome contributions! Here's how to get started:
- Fork the repository and create a feature branch
- Make your changes following our coding conventions
- Add tests for any new functionality
- Ensure all tests pass:
flutter test
- Format code:
dart format .
- Submit a pull request with a clear description
Pull Request Guidelines:
- โ Include tests for new features
- โ Update documentation if needed
- โ Follow existing code style
- โ Keep commits atomic and well-described
- โ Reference any related issues
Release Process:
- Uses automated releases via release-please
- Follow conventional commits:
feat:
,fix:
,docs:
, etc. - Automatic version bumping and changelog generation
๐ Resources
- ๐ Official Documentation
- ๐ฏ GrowthBook Dashboard
- ๐ฌ Community Slack
- ๐ Report Issues
- ๐ฆ pub.dev Package
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
Originally contributed by the team at Alippo. The core GrowthBook platform remains open-source and free forever.
Made with โค๏ธ by the GrowthBook community