How to set up Flutter remote config
Jan 27, 2025
Remote config enables you to update your Flutter app's settings and behavior instantly without deploying new code or waiting for app store approval. This makes it perfect for controlling features on the fly and disabling problematic features if needed.
This tutorial shows you how to set up remote config in your Flutter app using PostHog. We'll create a basic Flutter app that displays a company logo and message, both of which we'll control using remote config.
1. Create a new Flutter app
First, ensure the Flutter extension for VS Code is installed and then create a new app by opening the VS Code command palette (Ctrl/Cmd + Shift + P
), typing flutter
and selecting Flutter: New Project
.
Select Empty Application
and name your app flutter_remote_config
. Once created, replace your code in lib/main.dart
with the following:
import 'package:flutter/material.dart';void main() {runApp(const MyApp());}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return const MaterialApp(title: 'Flutter PostHog remote config demo',home: MainScreen(),);}}class MainScreen extends StatelessWidget {const MainScreen({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('PostHog remote config demo'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Image.network('https://picsum.photos/200', // We'll update this with remote configwidth: 200,height: 200,),const SizedBox(height: 20),const Text('Welcome message goes here', // We'll update this with remote configstyle: TextStyle(fontSize: 20),),],),),);}}
To test this works, we check for the emulation devices available with flutter devices
and run the app for one of them. We'll use the web version and launch it like this:
flutter run -d chrome
2. Add PostHog to your app
With our app set up, it's time to install and set up PostHog. If you don't have a PostHog instance, you can sign up for free.
To start, install PostHog's Flutter SDK by adding posthog_flutter
to your pubspec.yaml
:
dependencies:flutter:sdk: flutterposthog_flutter: ^4.0.1
Next, we configure PostHog in each platform using our project API key and instance address which you can find in your project settings.
Android setup
For Android, add your PostHog configuration to your AndroidManifest.xml
file located in android/app/src/main
folder:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><application><!-- ... other configuration ... --><meta-data android:name="com.posthog.posthog.API_KEY" android:value="<ph_project_api_key>" /><meta-data android:name="com.posthog.posthog.POSTHOG_HOST" android:value="https://us.i.posthog.com" /><meta-data android:name="com.posthog.posthog.TRACK_APPLICATION_LIFECYCLE_EVENTS" android:value="true" /><meta-data android:name="com.posthog.posthog.DEBUG" android:value="true" /></application></manifest>
You'll also need to update the minimum Android SDK version to 21
in android/app/build.gradle
:
defaultConfig {minSdkVersion 21// rest of your config}
iOS setup
For iOS, you need to have Cocoapods installed and then add your PostHog configuration to the Info.plist
file located in the ios/Runner
directory:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><!-- rest of your configuration --><key>com.posthog.posthog.API_KEY</key><string><ph_project_api_key></string><key>com.posthog.posthog.POSTHOG_HOST</key><string>https://us.i.posthog.com</string> <!-- <https://us.i.posthog.com> or <https://eu.i.posthog.com> --><key>com.posthog.posthog.CAPTURE_APPLICATION_LIFECYCLE_EVENTS</key><true/><key>com.posthog.posthog.DEBUG</key><true/></dict></plist>
Then set the minimum platform version to iOS 13.0 in your iOS Podfile:
platform :ios, '13.0'# ... rest of your config
Web setup
For web, add your the PostHog web snippet (which you can find in your project settings) in the <head>
of your web/index.html
file:
<!DOCTYPE html><html><head><!-- ... other head elements ... --><script>!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);posthog.init('<ph_project_api_key>',{api_host:'https://us.i.posthog.com',})</script></head><!-- ... other elements ... --></html>
3. Create remote config flags in PostHog
With PostHog set up, let's create two remote config flags to control our app's configuration:
- Go to the feature flags tab in PostHog and click New feature flag
- Enter
company-logo-url
as the key - Under Served value, select Remote config (single payload)
- Set the payload to a string of an image. We'll use PostHog's logo at
"/brand/posthog-logo@2x.png"
- Click Save
After this, repeat steps 1-5 to create another flag with key welcome-message
and payload of "Welcome to our awesome app!"
4. Implement remote config in Flutter
Finally, we'll update our app to use these remote config values. To do this, we start by creating a new file in lib
named config_provider.dart
. In this file we create a ConfigProvider
to manage our remote config state.
import 'package:flutter/material.dart';import 'package:posthog_flutter/posthog_flutter.dart';class ConfigProvider extends ChangeNotifier {String _logoUrl = 'https://picsum.photos/200'; // Default valueString _welcomeMessage = 'Welcome message goes here'; // Default valueString get logoUrl => _logoUrl;String get welcomeMessage => _welcomeMessage;Future<void> loadConfig() async {try {final logoPayload = await Posthog().getFeatureFlagPayload('company-logo-url');final messagePayload = await Posthog().getFeatureFlagPayload('welcome-message');if (logoPayload != null) {_logoUrl = logoPayload.toString();}if (messagePayload != null) {_welcomeMessage = messagePayload.toString();}notifyListeners();} catch (e) {debugPrint('Error loading remote config: $e');}}}
Second, update your main.dart
file to use the ConfigProvider
and actually modify what users see in your app:
import 'package:flutter/material.dart';import 'package:provider/provider.dart';import 'config_provider.dart';void main() {runApp(ChangeNotifierProvider(create: (_) => ConfigProvider(),child: const MyApp(),),);}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return const MaterialApp(title: 'Flutter PostHog remote config demo',home: MainScreen(),);}}class MainScreen extends StatefulWidget {const MainScreen({super.key});State<MainScreen> createState() => _MainScreenState();}class _MainScreenState extends State<MainScreen> {void initState() {super.initState();// Load remote config when the screen initializesProvider.of<ConfigProvider>(context, listen: false).loadConfig();}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('PostHog remote config demo'),actions: [IconButton(icon: const Icon(Icons.refresh),onPressed: () {// Reload remote config when refresh button is pressedProvider.of<ConfigProvider>(context, listen: false).loadConfig();},),],),body: Consumer<ConfigProvider>(builder: (context, config, child) {return Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Image.network(config.logoUrl,width: 200,height: 200,),const SizedBox(height: 20),Text(config.welcomeMessage,style: const TextStyle(fontSize: 20),),],),);},),);}}
Finally, add the provider
package to your pubspec.yaml
:
dependencies:flutter:sdk: flutterposthog_flutter: ^4.0.1provider: ^6.1.1
Now, when we run our app, it fetches and displays the remote config values from PostHog. You either press r
in the terminal or run your emulation device like flutter run -d chrome
again to show this in action:
Further reading
- Feature flags vs configuration: Which should you choose?
- How to set up analytics in Flutter
- How to set up A/B tests in Flutter
Questions? Ask Max AI.
It's easier than reading through 575 docs articles.