eppo 1.2.0
Eppo is a composable next-generation feature flagging and experimentation platform focused on tightly integrating with your existing tech stack.
Eppo Feature Flagging SDK Example
This example demonstrates how to use the Eppo SDK for feature flagging and experimentation in a Dart application, showcasing both the traditional singleton API and the new multi-instance API.
What This Example Shows
- Singleton API: Traditional single-user SDK usage
- Multi-Instance API: Managing multiple user contexts (anonymous vs. logged-in users)
- User State Transitions: Handling anonymous → logged-in user flows
- API Coexistence: How both APIs work together seamlessly
- Instance Management: Creating, using, and cleaning up user instances
- Different User Types: Anonymous users, free users, premium users with different attributes
- Feature Flag Types: String, boolean, integer, numeric, JSON flags
- Bandit Actions: Personalized recommendations and content selection
- Custom Assignment Logger: Tracking flag assignments for analytics
Running the Example
To run this example, you'll need a valid Eppo SDK key. You can get one by signing up at geteppo.com.
# From the root of the eppo package
dart run example/main.dart <your-sdk-key> [optional-subject-key]
If you don't provide a subject key, the example will use 'user-123' as the default.
Key Concepts and Code Snippets
Custom Assignment Logger
Create a custom logger to track flag assignments:
import 'package:eppo/eppo.dart';
class MyAssignmentLogger extends AssignmentLogger {
@override
void logAssignment(AssignmentEvent event) {
print('logAssignment: ${event.featureFlag} ${event.variation} ${event.timestamp}');
}
}
Creating a Subject
Create a subject with attributes for targeted flag assignments:
final subject = Subject(
subjectKey: 'user-123',
subjectAttributes: ContextAttributes(
categoricalAttributes: {'country': 'US', 'device': 'mobile'},
numericAttributes: {'age': 30, 'visits': 5},
),
);
final subjectEvaluation = SubjectEvaluation(subject: subject);
Providing Bandit Actions
When using bandit algorithms, you must provide actions during initialization:
// Create a subject evaluation with bandit actions
final subjectEvaluation = SubjectEvaluation(
subject: Subject(
subjectKey: 'user-identifier',
subjectAttributes: ContextAttributes(
categoricalAttributes: {'country': 'usa'},
numericAttributes: {'age': 30},
),
),
banditActions: {
'nike': {
'brand_affinity': 0.4,
'from': 'usa',
}
},
);
SDK Initialization
Initialize the SDK with your key and configuration:
final clientConfiguration = ClientConfiguration(
sdkPlatform: SdkPlatform.dart,
assignmentLogger: MyAssignmentLogger(),
);
await Eppo.initialize(
'your-sdk-key',
subjectEvaluation,
clientConfiguration
);
Evaluating Feature Flags
String Flag
final stringValue = Eppo.getStringAssignment('dart-test-flag-string', 'default-string');
print('string-flag: $stringValue');
Boolean Flag
final boolValue = Eppo.getBooleanAssignment('dart-test-flag-boolean', false);
print('boolean-flag: $boolValue');
Integer Flag
final intValue = Eppo.getIntegerAssignment('dart-test-flag-integer', 0);
print('integer-flag: $intValue');
Numeric Flag
final numValue = Eppo.getNumericAssignment('dart-test-flag-numeric', 0.0);
print('numeric-flag: $numValue');
JSON Flag
final jsonValue = Eppo.getJSONAssignment('dart-test-flag-json', {});
print('json-flag: $jsonValue');
Bandit Action
final banditValue = Eppo.getBanditAction('update-highlights-bandit', 'default-bandit');
print('bandit-flag: action=${banditValue.action} variation=${banditValue.variation}');
Example Output Structure
When run successfully, you'll see a comprehensive demonstration:
Eppo SDK Multi-Instance Example
=================================
1️⃣ Singleton API
----------------
✅ Initialized SDK for logged-in user: user-123
Premium feature enabled: true
2️⃣ Multi-Instance API
---------------------
✅ Created anonymous user instance
✅ Created second user instance
3️⃣ Flag Evaluations Per User
----------------------------
Anonymous user flags:
Premium feature: false
Show signup banner: false
Second user flags:
Premium feature: false
Show signup banner: false
API Coexistence:
----------------
Singleton API result: true
Multi-instance API (same subject): true
✅ Results match: true
Instance Management:
-------------------
Active subjects: [user-123, anonymous-session-abc123, user-456]
Total instances: 3
Cleaning up anonymous user...
Active subjects after cleanup: [user-123, user-456]
User State Transition:
---------------------
Simulating anonymous → logged-in user transition...
Before login - signup banner: false
After login - premium feature: true
✅ Example completed successfully!
Final active subjects: [user-123, user-456, user-789]
Key API Additions
Multi-Instance Usage
// Create instances for different users
final anonymousUser = await Eppo.forSubject(
SubjectEvaluation(
subject: Subject(
subjectKey: 'anonymous-session-123',
subjectAttributes: ContextAttributes(
categoricalAttributes: {'user_type': 'anonymous'},
numericAttributes: {'session_count': 1},
),
),
),
);
final loggedInUser = await Eppo.forSubject(
SubjectEvaluation(
subject: Subject(
subjectKey: 'user-456',
subjectAttributes: ContextAttributes(
categoricalAttributes: {'user_type': 'authenticated', 'plan': 'premium'},
numericAttributes: {'age': 30, 'account_age_days': 180},
),
),
),
);
// Use per-user flag evaluations
bool showSignup = anonymousUser.getBooleanAssignment('signup-banner', false);
bool premiumFeature = loggedInUser.getBooleanAssignment('premium-feature', false);
Instance Management
// Check active instances
List<String> activeUsers = Eppo.activeSubjects;
// Clean up when user logs out
Eppo.removeSubject('anonymous-session-123');
// Reset all instances
Eppo.reset();
Further Reading
For more advanced usage and configuration options, see the full documentation.