🪄 Powering up your app with Firebase

Felipe Sales
suamusicatech
Published in
17 min readApr 17, 2024

and the possibilities to boost your business.

Who I Am

I am Felipe Sales, a developer who has been actively engaged in the Flutter market for a more than 2 years. I also have experience creating courses for developers - with courses on Udemy and contents on Rocketseat.

Actually, I am a software engineer at Sua Música, the largest platform for Brazilian music content; directly involved in the application - with 10M+ downloads on the Play Store.

Addictionally, I share programming related content on my social medias, see here.

🤔 What is Firebase?

Firebase is Google's cloud-based app development platform for building applications, providing resources to create better apps, enhance quality, and strengthen your growth.

And this suite of tools adds value at every stage of your development journey. Build, release and engagement; three key points for a successful project.

Those are the three general points.

And principal consequence of this is the scalability that this can bring to your app. Scalability that results in a high degree of flexibility for your project, capable of make it 100% customizable and with multiple testing possibilities.

🤔 Pros and Cons

✅ Pros

01. Setup and quick integration.

Easy to integrate into the application, as it has materials and most documentations that explain how to do it - from Firebase itself and externals.

02. Resources and funcionalities.

Provide a serie of services with easy integration, configuration and with each scope (from Authentication to A/B Testings [keep this concept in mind, we will talk more about it]).

03. Scalability and integration.

When well optimized and used intelligently, Firebase is a great friendly for project scalability and integration of the entire ecosystem.

04. Community, engagement and suport.

Because it is widely used and has a large community, if you have a problem, a bug, or have a question about some functionality it provides, this doubt has certainly already been answered in some issue of GitHub, StackOverFlow topic, open communities, or others devs can help you.

05. Versatile solution.

Can be used in various projects and contexts, both for personal objectives and for companies with million of users. This versatility provides flexible and adapts solutions for business requirements.

❌ Cons

01 | Prices and plans.

When not optimized and/or used excessively it's possible that costs be will be high compared to others services (even more so if consider exchange rate and usage).

02 | Support in specific cases.

It's possible that you have a very specific case where support may not provide a considerable and helpful answer that helps you. I already needed it and did not have a good experience - but it was a very specific case.

03 | Changes and failures in SDKs.

Due to internal integrations that are made, it is possible that errors may come from your SDK - some may be minor, and others may even be fatal (automatically closing the application).

04 | Vendor Lock-in.

It's very probably to happen when using - but this is not exclusive to Firebase (however it is ideal be aware that a possible migration will be more work).

05 | Documentation.

You may encounter issues in the documentation or even that it is not as clear as you would like - due to the specifies of each case. A tip is to always look for examples and/or ask in the communities.

It is important here to understand your needs and whether Firebase is suitable for them, in most of the cases that we will show below it is more than sufficient and serves very well.

🔎 Concept of Feature-Flag / Feature-Toggle

An increasingly common practice in market is adoption of feature-flag / feature-toggle. This concept allows flexibility regarding the control of features without need for changes in code and/or new deployment.

For example: controlling what will be displayed, the behaviour of a feature, layout arrangements, display of messages and notifications etc.

This image show a little in practice what the behaviour of a feature-flag might can be.

And this is where the concept of A/B Testing comes in, where Firebase has integration between services that can be used for this:

📈 Behaviour in the practice

See the image below and consider that:

  1. This is the same application;
  2. The same things are being showed in differents ways - in other words, it's in an A/B Testing to identify which of this formats is the best and which will be used from now on.

After consider this, let's move on to the keys points of an A/B Test.

🟰 Point 1. Distribution

An A/B test can have different distributions. You can select whichever one you want.

Let's take an example, consider that:

  • You have 100.000 users in the base;
  • 20% of users (20.000) are selected for the experiment mentioned above;
  • In practice, the value distributed within this 20% was:
    — 10.000 users with type A (50% of the 20%);
    — 10.000 users with type B (50% of the 20%);

💡 It's worth remembering that this is the default distribution, 50/50; but it's also possible to have different distributions and Firebase handles the distribution and expected calculations.

📊 Point 2. Statistic

After experiment is done, there is the value of Conversion Rate. In this same test, the conversion rate for A was 40% and B was 54%.

Considering that A was the old layout and B was the new one, we see that the new one converts much more and it is acceptable for change to apply to all users, that is, 100% of 100.000.

With this, we can undertand and predict in a certain way which would have the greatest impact taking into account the statistics of this.

💡 The possibilities

Have you ever imagined that everything can be controlled through strings, numbers and booleans?

In practice, we see that:

  • The total control of components can be 100% configurable;
    — Positioning, the animation, order of elements as a whole.
  • Activation or deactivation of specific features can be controlled;
  • Target audiende segmentation;
  • Dynamic change of behaviours and dynamic values based in your preference;
  • In addiction to colors, texts, fonts, spacements, sizes and much more.

The possibilities are infinites; and the best of all is know that your have the datas and statistics for your decisions.

💰 Another common example - ADs Case

Is very common for today applications to have some type of adversiting, and it's common for the Product team search to seek the best way to take advantage of them.

With this, remote configuration also flourishes, because you can experiment with different formats, frequencies and placements for them to appear.

🏆 The developer and the pillar of success.

Everything depends on the goal that you want to achieve and test.

And how the developer prepares their components to be flexible enough for the tests.

And that's where the importance of ensuring that one option is superior to another; based on reliable analysis and statistics arises.

Ignoring the instinct and supositions that may not yield results for users - and consequently for the product, which can bring losses.

Take advantage of the data-driven world and make these powers that are within your reach an essential part of the validation and implementation proccess.

💸 The cost of it all.

Stop for a few seconds and guess a value that you imagine be for the use of this service…

Forget about it! It's fully free. You won't have any cost to implement this, regardless of whether there 1 user or 1 million.

🎵 A/B Testing at Sua Música

Sua Música is the largest streaming platform in Brazil, where artists can release their music to millions of people for free. Besides providing an entire ecosystem for user interaction, through apps, website and social media channels - such as Instagram.

With an app that has over than 10 millions downloads at PlayStore and 1M DAU (Daily Active Users), it's crucial that it's be remotely configurable.

In other works, being able to remotely define the behaviour of a feature, the positioning of a component, their order, as well as color, size and other details that can make a difference.

Here, we use this strategy and conduct many A/B tests to validate the formats that will retain users the most and use these statistics to make best decision (based on real data).

Since the beginning, when Firebase was starting to bring these features, we have experimented and put them into practice. The gains are notable because we can adapt the user experience based on the feedback that we receive, giving an interaction more customizable and efficient interactions.

Though data analysis, we can justify the implementation or not. And thus, we can measure the success of any feature based on data and not on assumptions.

🌟 The showcase

To exemplify a showcase, I develop an application from scratch to demonstrate how this can be made.

If you want to test it, you will have this repository:

In it, we want to conduct tests to verify if new formats and orders could make the user more engaged.

So, the Product Team suggested some variants based on current base; that is, A, B and C.

If we stop to observe, each of this orders have a reason to be implemented, but not necessarily will be one in specific which put directly results for an business.

In other words, these 4 formats will be tested to identify the best format to follow in practice.

But we need to think the challenges that this will have, which are:

  1. How will I order these components in differents ways and distribute this?
  2. How will I know which one was the best in the test?

For both challenges, Firebase has the solutions, the Remote Config and Google Analytics (as mentioned previously).

  1. Answer: Firebase Remote Config has support for string, number, boolean and json - formats that open up an infinite range of possibilities.
  2. Answer: Though sending unique events to Google Analytics, which will give to you numbers and statistics of engagement and actions performed (which we call as convertion).

🛠️ Firebase Setup

Since it's not the main focus, we let's start from the point where you have performed the Firebase setup (which you can find how to do via Firebase documentation or by searching like: "[your tecnology] firebase setup”.

Due didatic finally and to turn it a bit clear, I will show how my setup and all the configuration steps were done using Flutter - so you can adapt the concepts and strategies to tecnology that you use.

⚙️ 1 Step: Remote Config.

From a technical standpoint, the challenge is to make a static screen become remote, so we have the HomePage built in this way:

class HomePage extends StatelessWidget {
const HomePage({super.key});

@override
Widget build(BuildContext context) {
return const SingleChildScrollView(
child: Column(
children: [
HomeHeaderWidget(),
MyAccount(),
ServiceWidget(),
OffersWidget(),
MyCards(),
CreditCard(),
LoanWidget(),
FollowWidget(),
DiscoverOffersWidget(),
AppDivider(),
],
),
);
}
}

So ok! Now let's to start turning this 100% remote.

  1. In your main(), add the setup of Firebase; so that its inicialization will be done:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await AppFirebaseService().setUpInitialization(); /// setup

runApp(
const App(),
);
}

2. Now, for this class, add the following:

import 'dart:developer' as developer;

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:remote/firebase_options.dart';
import 'package:remote/src/data/services/firebase/firebase.dart';

class AppFirebaseService {
/// Initializes Firebase and Remote Config.
Future<void> setUpInitialization() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await setUpRemoteConfig();
}

/// Sets up Remote Config, sets defaults, and fetches and activates the config.
Future<void> setUpRemoteConfig() async {
try {
final remoteConfig = FirebaseRemoteConfig.instance;
await remoteConfig.setDefaults(AppFirebaseDefaults.getRemoteConfigKeys);
await remoteConfig.setConfigSettings(AppFirebaseSettings().config);
await remoteConfig.fetchAndActivate();
} catch (e, s) {
developer.log(
'setUpRemoteConfig',
name: 'AppFirebaseService',
error: e,
stackTrace: s,
);
}
}
}

/// Settings for Firebase Remote Config, such as fetch timeout and minimum fetch interval.
class AppFirebaseSettings {
final config = RemoteConfigSettings(
fetchTimeout: const Duration(hours: 1),
minimumFetchInterval: const Duration(hours: 1),
);
}

/// [AppFirebaseRemoteKeys] contains the remote keys for the remote config.
class AppFirebaseRemoteKeys {
static const homeRemoteOrder = 'home_remote_order';
}

/// Default values for Remote Config.
class AppFirebaseDefaults {
static get getRemoteConfigKeys => {
AppFirebaseRemoteKeys.homeRemoteOrder:
'account,services,myCards,offers,divider,creditCard,divider,loans,divider,follow,divider,searchOffers',
};
}
}

/// Get Remote Config values.
class AppFirebaseRemoteGet {
static String get homeRemoteOrder => FirebaseRemoteConfig.instance
.getString(AppFirebaseRemoteKeys.homeRemoteOrder);
}

And now, do this in your HomePage - and the coolest thing about it is using the powers of Dart 3.0.0 with the new switch):

class HomePage extends StatelessWidget {
const HomePage({super.key});

@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
const HomeHeaderWidget(),
/// This is the part of the code that was changed to use the remote order
/// instead of the default order.
/// The remote order is fetched via the AppFirebaseRemoteGet class,
/// that gets the remote order from the Firebase Remote Config.
for (final item
in AppFirebaseRemoteGet.homeRemoteOrder.trim().split(','))
switch (item.trim()) {
HomeABKeys.account => const MyAccount(),
HomeABKeys.services => const ServiceWidget(),
HomeABKeys.servicesGrid => const ServiceGridWidget(),
HomeABKeys.myCards => const MyCards(),
HomeABKeys.offers => const OffersWidget(),
HomeABKeys.creditCard => const CreditCard(),
HomeABKeys.loans => const LoanWidget(),
HomeABKeys.follow => const FollowWidget(),
HomeABKeys.searchOffers => const DiscoverOffersWidget(),
HomeABKeys.divider => const AppDivider(),
/// If want to add space remotely between widgets
_ when double.tryParse(item) != null =>
SizedBox(height: double.parse(item)),
_ => const SizedBox(),
},
],
),
);
}
}

Now, let's add the key home_remote_order in our Remote Config:

  1. Go to Engage > Remote Config > Create Configuration and click;

2. Create your first parameter and add value to it, in this case, we will put: account,services,myCards,offers,divider,creditCard,divider,loans,divider,follow,divider,searchOffers;

3. After saving, publish your changes;

4. After publication, this will already be available to be used in your app, and the changes you make here already be reflected in your project.

  • Tip: Leave fetchTimeout and minimumFetchInterval in your code low values - to always keep them updated -, such as 1 second. Add do the hot-restart so that your setup is done again (or reload the application).

And that's it! Your ordering is now remote, and you are already using the powers of Remote Config in your app.

🔍 2 Step: Google Analytics.

You will need to track events for each component in question - and this is personal and specific for each test case. Here's a generic strategy that will help in most cases:

/// The Firebase Analytics helper class, that log events to Firebase Analytics.
class AppFirebaseAnalytics {
/// Logs an event with the given [name].
static void logEvent(String name) {
final event = name.replaceAll(' ', '');
try {
FirebaseAnalytics.instance
.logEvent(name: event)
.then((value) => debugPrint('Analytics - logEvent: $event'));
} catch (e) {
debugPrint('Analytics - logEvent: $event, error: $e');
}
}

/// Logs events with the given [names].
static void logEvents(List<String> names) {
for (var name in names) {
logEvent(name);
}
}

/// Logs a [HomeTap] event with the given [names].
static void logHomeEvent(List<String> names) =>
logEvents(['HomeTap', for (var name in names) name]);
}

And in your component, you can use on clicks, for example:

onTap: () {
/// This logs HomeTap and Finance events.
AppFirebaseAnalytics.logHomeEvent('Finance');
}

Observations:

  1. 💡 Here comes the importance of creating reusable components, where you leave an event by default and pass differents event names defined by parameters; and with this covering 100% of your app with events. This allows you to understand user behaviour.
  2. 💡 Remember that each event should be unique. That is, it should uniquely cover a flow, a functionality and/or a component. This will ensure that your events are evenly distributed in the test and allow for precise analysis of the results.

Check more about this strategy in through this commit:

And done! You have covered your app with the 2 main points before creating your A/B test; now let's move on to the most important part.👇

🧪 How to create an A/B Test | In practice

1. Access Firebase Console and select your project;

2. Go to Engage > A/B Testing > Create Experiment;

3. After that, you will see that there are 3 options for test: Notifications, Remote Config and In-App Messaging; we will focus on Remote Config.

Now let's start the creation!

4. [BASICS] (1): Give the name and description of your experiment.

5. [TARGETING] (2): The moment to choose specifics of your test.

6. [TARGETING] (2): Choose the desired platform - iOS / Android / Web...
(it is likely that you create another test to apply to all users - Firebase starts from this on the Operating System target, you can see there are 3 in my example).

7. [TARGETING] (2): Note that you already have the numbers of users who will be in the experiment, and you can choose the desired percentage though Exposure.
(in our case, we will make it for 100% of users)

8. [TARGETING] (2): You probably want to specify your test a little more and see more available options before publishing anything.
In this way, click on and:

9. [TARGETING] (2): Now click on the dropdown so that the segmentation options appear:

10. [TARGETING] (2): There are several segmentations you can choose from, it's multiple (I recommend you explore and do the desired segmentation).

11. [TARGETING] (2): See this example, we selected that:

  • We want that the language to be in portuguese;
  • The build number is 10 (choose what you want to segment appropriately considering the release when the feature was launched); - it may also be interesting to add the Version.
  • That audience is customers;
  • And that the entry was after the chosen date in a specific timezone.

12. [TARGETING] (2): It's also possible to add an activation event; this is like a starting point / condition for the user to participate in the experiment.

  • That is, a click, a purchase, entering in specific screen… whatever you want as a start point for the test to begin.

I have to repeat, this is very complete!

13. [Goals] (3): Now the goals - where you will select the main metrics to determine which variant of these tests will be lead. By default, these are the metrics that Firebase itself puts.

14. [Goals] (3): To add different goals, click here:

15. [Goals] (3): Here are more options, you can also add or search for events (considering that you can have N (multiples) events).

16. [Goals] (3): When you already have recent events saved, they will also appear in the list. If they don't appear, you can create them manually and Firebase should increment and use it.

17. [Goals] (3): Select all the events you want to use as metric for A/B test. The maximum is 5 (additional) + 1 (the main metric).

⚠️ IMPORTANT OBSERVATION:

  • Each event must be unique for this analysis to be given only to the scope of the test.
  • If the event be used in another scope and/or not well distributed (in other words, it is in one variant and not in another), this tests may be invalid - because Firebase will add it to the in test.
  • For example: suppose that an "PURCHASE” event is used as a metric for an A/B test on the new purchase screen, but it is also used in others parts of the application that are not related to the test. This would cause Firebase to count all occurrences of the event, not just those related to A/B test.

18. [Variants] (4): Now is the time to choose the variants that will go into your test. Here, you will add the parameters (keys) and their respective values that will be used in each variation.

  • Here, it's important to note that you can have multiple variations and keys in each variation, meaning you have infinite possibilities and test cases.
  • As this is about remote ordering, the following orders were placed in each variation, respectively:
  • account,services,myCards,offers,divider,creditCard,divider,loans,divider,follow,divider,searchOffers
  • account,services,offers,myCards,divider,creditCard,divider,loans,divider,follow,divider,searchOffers
  • account,myCards,offers,services,divider,creditCard,divider,loans,divider,follow,divider,searchOffers
  • account,servicesGrid,myCards,offers,divider,creditCard,divider,loans,divider,follow,divider,searchOffers

19. [Variants] (4): If you want, you can perform a customized distribution for each one - by default, the distribution wil be equal.

20. [Review] (5): Upon clicking in review, you will have the draft of your test.

21. [Review] (5): You will have a preview to finalize last details, review and even share the experiment link with others before launching it to all users. You can click here to get more details about your test.

22. [Review] (5): You will have all the details about your experiment, where you can edit, view more details in the menu icon (where you can add test devices) etc. After all this, you can start the experiment.

23. [Review] (5): Confirm the release of the experiment.

24. [Experiment] (6): Done! Now your test is available for the selected users; wait a few hours and the first data will be shown.

25. [Experiment] (6): Your test will also appear on Firebase dashboard:

26. [Experiment] (7): After a period, you can already see the first datas.

  • Since this is a simple app for didatic purposes, the results are statistically insignificat; but certainly in a real application, this would yield more meaningful results.
  • Based on our defined metrics, whether it's increasing users, improving retention and/or engagement, we can decide with data-driven rather than relying on assumptions, the best alternative for the application.
An example of results from an AB test using Remote Config.

🚀 Remote Config and Scalability

The main idea behind all of this is to make you understand the powers that Firebase can bring to your project.

Besides, primarily, it makes you confident in the decision to be made regarding the best formats to be used. This progressively provides scalability for configuring and managing the application without the need for a new deployment.

With all this power, you make decisions effectively, due to the grounding and analysis that have been done.

💬 Q&A

If you have any questions I'm available to help and collaborate in this aspect.

My social networks are:

📝 Finals Considerations

What did you think about this article? Undoubtedly, it should be one of the most comprehensive on this topic in the community; in addiction, to being comprehensive for any area and professionals interested; from developers to product teams, this will certainly add a lot of value.

Due this, consider giving some 👏 here, to help reach more people, strenghten these contents and support this initiative.

Thanks and lets go, aiming for the next level! 🏆

If you want to see and access the complete example, see the link below:

--

--

Felipe Sales
suamusicatech

🏆 | I love programming and always seek the next level! | @SuaMusica