Your First In-App Messaging Experiment

1. Introduction

Goals

In this codelab, you'll instrument an in-app messaging experiment for a multi-platform mobile restaurant recommendation app powered by Flutter and Cloud Firestore.

Once finished, you will be able to design and implement in-app messaging experiments to effectively increase user engagement for any iOS or Android app while writing a minimal amount of code.

b284c40acc99b994.png

What you'll learn

  • How to use Firebase In-App Messaging (FIAM) in a Flutter app
  • How to customize the appearance of your in-app messages
  • How to design an in-app messaging experiment and implement it in your app
  • How to interpret the results of an in-app messaging experiment

What would you like to learn from this codelab?

I'm new to the topic, and I want a good overview. I know something about this topic, but I want a refresher. I'm looking for example code to use in my project. I'm looking for an explanation of something specific.

Firebase In-App Messaging

Firebase In-App Messaging (FIAM) helps you engage users who are actively using your app by sending them targeted and contextual messages that nudge them to complete key in-app actions - like beating a game level, buying an item, or subscribing to content.

Firebase A/B Testing

Powered by Google Optimize, Firebase A/B Testing (ABT) helps you optimize your app experience by making it easy to run, analyze, and scale product and marketing experiments. It gives you the power to test changes to your app's UI, features, or engagement campaigns to see if they actually move the needle on your key metrics (like revenue and retention) before you roll them out widely.

What you need

If you're not very familiar with Flutter or Firestore, first complete the Firebase for Flutter codelab:

You can run this codelab using any of the following devices:

  • A physical device (Android or iOS) connected to your computer and set to developer mode.
  • The iOS simulator. (Requires installing Xcode tools).
  • The Android emulator. (Requires setup in Android Studio).

In addition to the above, you'll also need:

  • A browser of your choice, such as Chrome.
  • An IDE or text editor of your choice, such as Android Studio or VS Code configured with the Dart and Flutter plugins. VS Code is recommended for use with Flutter.
  • The latest stable version of Flutter (or beta if you enjoy living on the edge).
  • A Google account, like a Gmail account, for creating and managing your Firebase project.
  • The codelab's sample code. See the next step for how to get the code.

2. Get set up

Get the code

Clone the GitHub repository from the command line:

git clone https://github.com/FirebaseExtended/codelab-friendlyeats-flutter.git friendlyeats-flutter

The sample code will be cloned into the friendlyeats-flutter directory. From now on, make sure you run commands from this directory:

cd friendlyeats-flutter

Then change into the codelab directory and check out the fiam-abt branch:

git checkout fiam-abt

This branch contains all the code necessary for this codelab, including a completed version in the done folder. The other branches in this repository contain code for building the FriendlyEats app, as shown in the Multi-platform Firestore Flutter codelab. For the purposes of this codelab, we've removed the web integration in this branch.

Import the starter app

Open or import the codelab-fiam-abt directory into your preferred IDE. This directory contains the starting code for the codelab which consists of a restaurant recommendation app. Through this codelab, you will instrument an in-app messaging experiment for this app's users.

Create a Firebase project

  1. In the Firebase console, click Add project, and then name the Firebase project FriendlyEats. Remember the project ID for your Firebase project (or click the Edit icon to set your preferred project ID).
  2. Make sure Google Analytics is enabled for the project, then click Continue.
  3. Click Create project.

Congratulations! You just created your first Firebase project. Now, you can click on the project name to enter the console.

Next, you walk through configuring and enabling the necessary services using the Firebase console.

Enable Anonymous Auth

Although authentication isn't the focus of this codelab, it's important to have some form of authentication in your app. You'll use Anonymous login—meaning that the user is silently signed in without being prompted.

To enable Anonymous login:

  1. In the Firebase console, locate Authentication in the left navigation bar.
  2. Click Authentication, and then click Get started and select the Sign-in method tab (or go directly to the Firebase console).
  3. Enable the Anonymous Sign-in Provider, and click Save.

fee6c3ebdf904459.png

Enabling Anonymous login allows the application to silently sign in your users when they access the app. To learn more, see the anonymous authentication documentation for Android and iOS.

Set up Cloud Firestore

The app uses Cloud Firestore to save and receive restaurant information and ratings.

Here's how to set up Cloud Firestore in your Firebase project:

  1. In the left-panel of the Firebase console, expand Build and then select Firestore database.
  2. Click Create database.
  3. Leave the Database ID set to (default).
  4. Select a location for your database, then click Next.
    For a real app, you want to choose a location that's close to your users.
  5. Click Start in test mode. Read the disclaimer about the security rules.
    Later in this codelab, you'll add Security Rules to secure your data. Do not distribute or expose an app publicly without adding Security Rules for your database.
  6. Click Create.

3. Mobile-specific Firebase configuration

Most of the code changes required to enable Firebase support are already checked into the project that you're working on. However, in order to add support for mobile platforms, you need to:

  • Register the desired platform on the Firebase project
  • Download the platform-specific configuration file, and add it to the code.

In the top-level directory of your Flutter app, there are subdirectories called ios and android. These directories hold the platform-specific configuration files for iOS and Android, respectively.

a35458e5c0dd0acf.png Configure iOS

In the Firebase console, select Project Settings in the top of the left navigation bar, and click the iOS button under Your apps in the General page.

You should see the following dialog:

c42139f18fb9a2ee.png

  1. The important value to provide is the iOS bundle ID. You get the bundle ID by performing the next three steps.
  1. In the command-line tool, go to the top-level directory of your Flutter app.
  2. Run the command open ios/Runner.xcworkspace to open Xcode.
  1. In Xcode, click the top-level Runner in the left pane, to show the General tab in the right pane, as shown. Copy the Bundle Identifier value.

9733e26be329f329.png

  1. Go back to the Firebase dialog, paste the copied Bundle Identifier into the iOS bundle ID field, and click Register App.
  1. Continuing in Firebase, follow the instructions to download the configuration file GoogleService-Info.plist.
  2. Go back to Xcode. Notice that Runner has a subfolder also called Runner (shown in the preceding image).
  3. Drag the GoogleService-Info.plist file (that you just downloaded) into that Runner subfolder.
  4. In the dialog that appears in Xcode, click Finish.
  5. Go back to the Firebase console. In the setup step, click Next, skip the remaining steps, and go back to the main page of the Firebase console.

You're done configuring your Flutter app for iOS!

84e0b3199bef6d8a.pngConfigure Android

  1. In the Firebase Console, select Project Settings in the top of the left navigation bar, and click the Android button under Your apps in the General page.

You'll should see the following dialog : 8254fc299e82f528.png

  1. The important value to provide is the Android package name. You get the package name when you perform the following two steps:
  1. In your Flutter app directory, open the file android/app/src/main/AndroidManifest.xml.
  2. In the manifest element, find the string value of the package attribute. This value is the Android package name (something like com.yourcompany.yourproject). Copy this value.
  3. In the Firebase dialog, paste the copied package name into the Android package name field.
  4. You don't need the Debug signing certificate SHA-1 for this codelab. Leave this blank.
  5. Click Register App.
  6. Continuing in Firebase, follow the instructions to download the configuration file google-services.json.
  7. Go to your Flutter app directory, and move the google-services.json file (that you just downloaded) into the android/app directory.
  8. Back in the Firebase console, skip the remaining steps, and go back to the main page of the Firebase console.
  9. All the Gradle configuration is already checked in. If your app is still running, then close and rebuild it, to allow gradle to install dependencies.

You're done configuring your Flutter app for Android!

4. Run your app locally

You're ready to actually start work on your app! First, run the app locally. You can now run the app in any platform that you configured (and for which you have a device and emulator available).

Discover which devices are available with the following command:

flutter devices

Depending on which devices are available, the output of the preceding command looks something like this:

7d44d7c0837b3e8e.png

Now, run the app locally with the following command:

flutter run

Now, you should see your copy of FriendlyEats, connected to your Firebase project.

The app automatically connects to your Firebase project and silently signs you in as an anonymous user.

5. Create and test your first message

Integrate Firebase In-App Messaging into your app

The In-App Messaging basic integration is totally codeless, all you need to do is add the dependency and you're ready to go! Add the following dependency to your pubspec.yaml file

dependencies:
  # ...
  firebase_in_app_messaging: ^0.4.0
  # ...

Compose a message in the Firebase Console

Now that you've added FIAM to your app, lets compose a message that will trigger when your app is first opened.

To compose your first message:

  1. In the Firebase console's Engage section, click In-App Messaging.
  2. Click Create your first campaign in the In-App Messaging pane.

4fec02395f89f2a8.png

Lets compose a basic Modal message to make sure the integration is working. Feel free to customize the message in any way you'd like – you can add images, buttons, or change colors.

59845004afc26847.png

Be sure to target the app you want to test with, depending on what integration path you're following you might have iOS, Android, or both.

3f1eb7a327a50265.png

We want to make sure to have the message trigger when the app opens, so the default scheduling configuration will work here.

8dc5cea0a4c79008.png

Once the scheduling is done we can publish the message. Click "review" and you should see something like the following

5bbc987bf63d1f48.png

View the message in your app

Now, uninstall and reinstall your app, and you should see the message you created display upon opening. Congrats, you just sent your first in-app message! In the next step, you will learn how to add an analytics event, in order to trigger an in-app message based on actions your users take in the app.

6. Integrate Firebase Analytics for advanced message triggering

Integrate Firebase Analytics into your app

In order to understand how users are interacting with our app, and trigger an in-app message based on their actions, we will now add an Analytics event for when a user clicks on a restaurant.

  1. Add the Firebase Analytics dependency to Flutter in pubspec.yaml
dependencies:
  # ...
  firebase_analytics: ^1.0.1
  # ...
  1. Import analytics in home_page.dart
import 'package:firebase_analytics/firebase_analytics.dart';
  1. Add an instance of Firebase Analytics to the HomePage class in home_page.dart
class HomePage extends StatefulWidget {
  static const route = '/';
  static FirebaseAnalytics analytics = FirebaseAnalytics();
  HomePage({Key key}) : super(key: key);
  @override
  _HomePageState createState() => _HomePageState();
}
  1. Fire an analytics event when the user clicks on a restaurant card in home_page.dart
onRestaurantPressed: (id) async {
  await HomePage.analytics.logEvent(name: 'click_restaurant');
  Navigator.pushNamed(context,
                      RestaurantPage.route,
                      arguments: RestaurantPageArguments(id: id));
})

Edit your message to trigger on the analytics event

Now that we have an event "click_restaurant" let's trigger our in-app message based on that rather than when the user opens the app.

In the Firebase Console go back to In-App Message and edit your existing campaign

d1fdc539dfcc6375.png

Now change the scheduling section to trigger the message from the new event

8e12d8f1f8f166dd.png

From there we can publish our changes by clicking the "review" button

4f7d6bd2960b3ef7.png

Test out your trigger in the app

At this point you should be able to run you app with

flutter run

And when you click a restaurant you should see your In-App Message

a11febda5526263.png

7. Create a FIAM+ABT Campaign

Start with a goal

Our Friendlyeats app is already looking great, but for it to be useful we need to have some reviews. These will be sourced from Friendlyeats users, so let's find some way to encourage users to leave reviews.

First let's define our conversion event

Since we want to see if users are reviewing restaurants lets add an analytics event to measure this behavior.

  1. Import Firebase Analytics just like before and add an instance of Analytics to RestaurantPage in restaurant_page.dart
class RestaurantPage extends StatefulWidget {
  static const route = '/restaurant';
  static FirebaseAnalytics analytics = FirebaseAnalytics();
  final String _restaurantId;
  RestaurantPage({Key key, @required String restaurantId})
      : _restaurantId = restaurantId,
        super(key: key);
  @override
  _RestaurantPageState createState() =>
      _RestaurantPageState(restaurantId: _restaurantId);
}
  1. Now lets trigger an event in _onCreateReviewPressed when we save a review in restaurant_page.dart
 if (newReview != null) {
   // Log successful review
   await RestaurantPage.analytics.logEvent(name: 'review_success');
   // Save the review
   return data.addReview(restaurantId: _restaurant.id, review: newReview);
 }

Configure A/B Test in the Firebase Console

Now that we know how to create in-app messaging campaigns, it's time to consider what kind behavior we'd like to encourage in our app through these campaigns. For FriendlyEats, we'd like more people to leave reviews, which would make the app more useful! There's a few ways we could encourage this using in-app messages. One is through a simple in-app message that just tells the user they should give the restaurant a review to help improve the FriendlyEats app. Another way is to use an in-app message to offer some type of incentive for providing a review, like a coupon or discount code to a given restaurant.

Both approaches could increase how often users provide reviews for restaurants on FriendlyEats, and it seems like providing a coupon could have an even stronger impact in this case. But, how much more likely would providing this coupon make users to write a review? Is it worth the cost of the coupon in the first place? To determine this, we will run an in-app messaging experiment! We can use Firebase A/B Testing to randomly display one of our in-app messages to users, and measure the effect this has on user behavior, kind of like a clinical trial. Best of all, this can be done completely through the Firebase console, with no code needed!

To compose your first in-app messaging experiment:

  1. In the Firebase console's Engage section, click A/B Testing.
  2. Click Create experiment, and select that you want to experiment with In-App Messaging. This will bring you to the experiment composer shown below.

a792dfd4f82fee9c.png

Give your experiment a name and an optional description.

  1. The next step is where you will compose the different in-app messages you will send to users in your experiment. The first in-app message we will compose is the "baseline", or the control of our experiment. We can make this our simple "please make a review" message:

50e3eb946c56501a.png

  1. Now that we have a baseline, we will now compose a variant, the in-app message that offers users a coupon code to encourage them to leave a review. This isn't fully visible in the preview below, but the Message title is "Take a coupon, leave a review!", and the message body is "Next time you're at the Burrito Cafe, use coupon code FRIENDLYEATS-15 at checkout for 15% off your order. And remember to leave a review after!". This will hopefully inspire some users to check out the Burrito Cafe!

bed9182080bebb41.png

In the next step, we will target our app and set the Exposure. This is the percentage of eligible users (those satisfying the targeting/triggering conditions) who will see one of the messages in the experiment. We can just set this to 100% for this example, as we'd like all users to see either the baseline or our coupon variant. If you want to have a control group which is shown no in-app message at all, you can reduce this exposure percentage.

bd96bf5798d227f1.png

  1. Next, you will define some goals for the experiment. This is the outcome of the experiment we'd like to measure. We'll set this as the review_success analytics event we defined in the previous section, as we'd like to see the impact our different in-app messages have on users leaving restaurant reviews. eb89d3b9f89ab43b.png
  2. For scheduling, we'll let the campaign begin immediately, and set click_restaurant as the triggering condition, so that users see one of the two in-app messages when they click on a restaurant.

c57be430d41bfcad.png

  1. Now, all that is left is to review our experiment, and hit Start experiment. Then we can sit back and wait for the data from our experiment to come in!

566af8bace30c67.png

Check out the data collection in real time

Now that we've started our experiment, FriendlyEats users will randomly see one of the two in-app messages we composed when they click on a restaurant, either the baseline message or the variant message. This will divide our users into two groups, based on which message they saw. We can then look in the Firebase console (again under the A/B Testing section) to compare live analytics data from both groups. It will take some time for data to come in, as we need to wait for users to actually see the in-app messages and act accordingly. Here's what your results could look like after enough data:

8fa8a0edcd8a8ad4.png

In this case, the variant improved upon the baseline significantly, so we could choose to select Roll out variant, which would then roll out the in-app message with the coupon to all users.

8. Congratulations

Congratulations, you've successfully created and run your first in-app messaging experiment. Now you can run an experiment in your own app, and use the results to make your in-app messaging campaigns more effective.

What's next?

Check out some of these codelabs...

Further reading

We've just scratched the surface of what can be done with Firebase In-App Messaging and Firebase A/B Testing. Check these out if you'd like to learn more...

Reference docs