10 tips to make ad monetization
10 Tips to make Ad Monetization Smarter with Firebase
1. Introduction
Ads are a crucial part of your app's overall user experience. Good ad implementations can contribute efficiently to UX and even improve user retention and engagement. For example, Rewarded Video Ads enable you to reward users with in-app currency or items for watching video ads, so that users can reach new heights where otherwise they may get stuck and would have churned.
However, an excellent ad implementation involves a lot of considerations: How often should you show these ads? Where and when should you show them? What should the award be? And so on. Unfortunately, the answer differs from app to app, and from placement to placement. There is no one-size-fits-all answer.
With Google Analytics for Firebase and AdMob, alongside several powerful yet easy-to-use tools Firebase offers, fine tuning your app in a data driven way has become much easier and more streamlined.
What are you going to be building?
In this codelab, you're going to collect analytics signals with Google Analytics for Firebase, set up Remote Config parameters and A/B testing, and send push notifications to users who are predicted to churn. We will also share with you tips about what metrics to collect and look at, and how to turn them into actions.
What you'll learn
- How to enable Google Analytics for Firebase for your app
- What analytics data to collect for monetization
- How to setup Remote Config parameters and A/B tests to fine-tune Ad behavior
- How to use Predictions together with Remote Config and Cloud Messaging
What you'll need
- Android Studio version 3.1+
- A Google account
- A test device with Android 4.1+ with a USB cable to connect your device, or Android Emulator running AVD(Android Virtual Device) with a system image that supports Play Store/Google APIs
2. Download and import the starter app
Download the code
Click the following button to download all the code for this codelab:
Unpack the downloaded zip file. This will unpack a root folder firebase-monetization-tips-master
. Rename the root folder to firebase-monetization-tips
.
...or clone the GitHub repository from the command line.
$ git clone https://github.com/googlecodelabs/firebase-monetization-tips
It contains two directories as follows:
- starter—Starting code that you will build in this codelab.
- final—Completed code for the finished sample app.
Import the starter app
Launch Android Studio, choose "Import project" on the welcome screen and select the starter directory from the sample code download.
You should now have the project open in Android Studio.
3. Setup Firebase Project
Create Firebase Console Project
- Go to the Firebase console.
- Select Add Project, and name your project "Awesome Drawing Quiz".
Connect your Android app
- From the overview screen of your new project, click Add Firebase to your Android app.
- Enter the codelab's package name: com.google.firebase.codelab.awesomedrawingquiz
- Set a nickname for your app: Awesome Drawing Quiz
- Leave the SHA-1 field blank since SHA-1 is not required for this project.
- Select Register App to register your app.
Add google-services.json file to your app
Next, you will be prompted a screen where you can download a configuration file that contains all the necessary Firebase metadata for your app. Click Download google-service.json and copy the file into the app directory in your project.
Add google-services plugin to your app
The google-services plugin uses the google-services.json
file to configure your application to use Firebase.
First, add google-services to buildscript level dependency in the build.gradle
file located at project root directory.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
...
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
// Add the following line
classpath 'com.google.gms:google-services:3.3.0'
}
}
...
Then, apply the google-services plugin by adding a line in app/build.gradle
file as follows:
apply plugin: 'com.android.application'
android {
...
}
dependencies {
...
}
// Add the following line at the bottom of your gradle file
apply plugin: 'com.google.gms.google-services'
Sync your project with gradle files
To be sure that all dependencies are available to your app, you should sync your project with gradle files at this point. Select File > Sync Project with Gradle Files menu to sync your project with gradle files.
4. Setup Rewarded Video Ad Unit (Optional)
The starter app already includes a dedicated Rewarded Video Ad Unit for your convenience. You are entirely free to skip this step if you don't want to create a new one under your AdMob account.
To create a new AdMob app in your account, please follow the instructions as follows:
- Go to the AdMob frontend.
- From Apps menu, click "Add App," answer "NO." when asked "Have you published your app on Google Play or the App Store," then name the app "Awesome Drawing Quiz," choose "Android" as the Platform and click "Add".
Once you created an AdMob app in your account, follow the steps as described in the below to create a new Rewarded Video Ad Unit.
- Click Apps menu in AdMob frontend, then select "Awesome Drawing Quiz" from the app list.
- Click Ad units menu, then click ADD AD UNIT to create a new Rewarded Video ad unit.
- Select Rewarded for the Ad format.
- Provide the name of the ad unit as you prefer. Then, set reward amount to 1, and reward item to "hint" (these are the reward the app current gives to users). And click CREATE AD UNIT to create a new Rewarded Video ad unit.
- When successfully created, you will see the instructions like the following.
- Go back to your Android project, and update the AdMob app id and ad unit id constants to the ones that you have created in the previous step.
AwesomeDrawingQuiz.java
// Update the value with your AdMob app id
private static final String ADMOB_APP_ID = "<YOUR_ADMOB_APP_ID>";
GameActivity.java
// Update the value with your Rewarded Video ad unit id
private static final String AD_UNIT_ID = "<YOUR_AD_UNIT_ID>";
5. Compile and Run the game
In this section, we'll quickly walk-through Awesome Drawing Quiz game. Once you compile and run the project, you'll see the following screen when the app starts.
Once you click ‘START A GAME,' you'll see a drawing on the screen. Your mission is to guess the name of the drawing by using the hint displayed on the top, from which you can infer the first letter and the length of the drawing's name.
If you don't have any idea what the name of the drawing is, you can click ‘SKIP' to skip the level. However, instead of skipping the level, you may want a clue that helps you guess the right answer. You can get an extra clue by clicking 'HINT' button and watching a Rewarded Video ad. After you complete watching the ad, one extra letter will be disclosed in the hint as a reward.
6. Understand What Analytics data to Collect (Tip 1)
Rewarded Video is a highly user-centric format. It's initiated by the user choosing to watch an ad, and it gives them some kind of reward that will impact user engagement in a variety of ways (in this Awesome Drawing Quiz, a hint).
In Awesome Drawing Quiz, there are four main steps when a user watches a rewarded ad and consumes the hint.
Ad prompt | Ad impression | Ad reward | Level success |
- Ad prompt: Where you show the user an option to watch a rewarded ad.
- Ad impression: Where your user actually watches the ad.
- Ad reward: A user who finished watching the ad receives a hint as a reward.
- Level success: Where a user clears a level
These four parts are your "rewarded funnel."
The opt-in rate lets you know how many of your users choose to watch a rewarded ad for a hint. It will help you answer: "Do users perceive a hint as a useful reward?"
The level clear rate helps you answer: "Users are watching the ads, but are they clearing the levels?"
Add Google Analytics for Firebase to your game
To understand the user journey in our game, you will add Google Analytics for Firebase to your game. Add the dependency for Google Analytics for Firebase to the dependencies block of your app/build.gradle
file:
implementation 'com.google.firebase:firebase-core:16.0.0'
Once you integrate Google Analytics for Firebase SDK to your app, it will automatically capture a number of events and user properties. It also allows you to define your own custom events.
Define custom events
To understand the user journey in the game, you will define a few custom events that track user behaviors.
Event name | Triggered... | Parameters |
stage_start | when a user starts a stage | none |
level_start | when a user starts a new level (a new drawing quiz) within a stage. (there are 6 levels in one stage) | level_name |
level_wrong_answer | when a user submits a wrong answer | level_name |
ad_prompt | when a user taps on the hint button, and is prompted to watch a Rewarded Video | ad_unit_id |
level_success | when a user submits a correct answer (clears a level) | elapsed_time_sec, hint_used, level_name, number_of_attempts |
level_fail | when a user skips a level | elapsed_time_sec, hint_used, level_name, number_of_attempts |
stage_end | when a user finishes a stage | number_of_correct_answers |
7. Log Custom Events (Tip 2)
Create a helper class for logging custom events
To make logging easier, you will create a helper class to manage custom events.
Create a new Java class and name it QuizAnalytics
under com.google.firebase.codelab.awesomedrawingquiz.ui.game
package. Create fields that define the name of your custom events and their parameters.
QuizAnalytics.java
public final class QuizAnalytics {
private static final String EVENT_AD_PROMPT = "ad_prompt";
private static final String EVENT_LEVEL_FAIL = "level_fail";
private static final String EVENT_LEVEL_SUCCESS = "level_success";
private static final String EVENT_LEVEL_WRONG_ANSWER = "level_wrong_answer";
private static final String EVENT_STAGE_START = "stage_start";
private static final String EVENT_STAGE_END = "stage_end";
private static final String PARAM_AD_UNIT_ID = "ad_unit_id";
private static final String PARAM_ELAPSED_TIME_SEC = "elapsed_time_sec";
private static final String PARAM_HINT_USED = "hint_used";
private static final String PARAM_NUMBER_OF_ATTEMPTS = "number_of_attempts";
private static final String PARAM_NUMBER_OF_CORRECT_ANSWERS = "number_of_correct_answers";
}
Next, add methods that help you log custom events in your game. Note that most of the custom events include parameters so you have more context of each event. Also note that a couple of event names and parameters (LEVEL_NAME
and LEVEL_START
) are already defined by Analytics, so we're going to use those.
public final class QuizAnalytics {
...
public static void logStageStart(@NonNull FirebaseAnalytics instance) {
instance.logEvent(EVENT_STAGE_START, null);
}
public static void logLevelStart(
@NonNull FirebaseAnalytics instance, @NonNull String levelName) {
Bundle param = new Bundle();
param.putString(FirebaseAnalytics.Param.LEVEL_NAME, levelName);
instance.logEvent(FirebaseAnalytics.Event.LEVEL_START, param);
}
public static void logLevelWrongAnswer(
@NonNull FirebaseAnalytics instance, @NonNull String levelName) {
Bundle param = new Bundle();
param.putString(FirebaseAnalytics.Param.LEVEL_NAME, levelName);
instance.logEvent(EVENT_LEVEL_WRONG_ANSWER, param);
}
public static void logAdPrompt(
@NonNull FirebaseAnalytics instance, @NonNull String adUnitId) {
Bundle param = new Bundle();
param.putString(PARAM_AD_UNIT_ID, adUnitId);
instance.logEvent(EVENT_AD_PROMPT, param);
}
public static void logLevelSuccess(
@NonNull FirebaseAnalytics instance, @NonNull String levelName,
int numberOfAttempts, int elapsedTimeSec, boolean hintUsed) {
Bundle param = new Bundle();
param.putString(FirebaseAnalytics.Param.LEVEL_NAME, levelName);
param.putInt(PARAM_NUMBER_OF_ATTEMPTS, numberOfAttempts);
param.putInt(PARAM_ELAPSED_TIME_SEC, elapsedTimeSec);
param.putLong(PARAM_HINT_USED, hintUsed ? 1 : 0);
instance.logEvent(EVENT_LEVEL_SUCCESS, param);
}
public static void logLevelFail(
@NonNull FirebaseAnalytics instance, @NonNull String levelName,
int numberOfAttempts, int elapsedTimeSec, boolean hintUsed) {
Bundle param = new Bundle();
param.putString(FirebaseAnalytics.Param.LEVEL_NAME, levelName);
param.putInt(PARAM_NUMBER_OF_ATTEMPTS, numberOfAttempts);
param.putInt(PARAM_ELAPSED_TIME_SEC, elapsedTimeSec);
param.putLong(PARAM_HINT_USED, hintUsed ? 1 : 0);
instance.logEvent(EVENT_LEVEL_FAIL, param);
}
public static void logStageEnd(
@NonNull FirebaseAnalytics instance, int numberOfCorrectAnswers) {
Bundle param = new Bundle();
param.putInt(PARAM_NUMBER_OF_CORRECT_ANSWERS, numberOfCorrectAnswers);
instance.logEvent(EVENT_STAGE_END, param);
}
}
Log custom events in our game
In GameActivity
, create a reference to FirebaseAnalytics
and initialize it as follows:
GameActivity.java
public class GameActivity extends AppCompatActivity implements RewardedVideoAdListener {
...
// Define a field for FirebaseAnalytics
FirebaseAnalytics firebaseAnalytics;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
// Obtain a FirebaseAnalytics instance
firebaseAnalytics = FirebaseAnalytics.getInstance(this);
...
}
...
}
Next, in onCreate()
method, call logStageStart()
to indicate a stage has started.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
if (!viewModel.isStarted()) {
showStageStartFullScreenDialog();
// Add the following line
QuizAnalytics.logStageStart(firebaseAnalytics);
}
...
}
Next, in setupViewModel()
method, add calls to log custom events as the following.
private void setupViewModel() {
viewModel.registerGameEventListener(ev -> {
if (ev instanceof GameLevelEvent) {
GameLevelEvent round = (GameLevelEvent) ev;
Log.d(TAG, "Round loaded: " + ev);
// Add this line
QuizAnalytics.logLevelStart(firebaseAnalytics, round.drawing().getWord());
...
} else if (ev instanceof GameLevelClueUpdateEvent) {
...
} else if (ev instanceof GameWrongAnswerEvent) {
GameWrongAnswerEvent event = (GameWrongAnswerEvent) ev;
Log.d(TAG, "Wrong Answer received: " + event);
// Add this line
QuizAnalytics.logLevelWrongAnswer(firebaseAnalytics, event.drawing().getWord());
...
} else if (ev instanceof GameLevelClearEvent) {
GameLevelClearEvent event = (GameLevelClearEvent) ev;
Log.d(TAG, "Round cleared: " + event);
// Add this line
QuizAnalytics.logLevelSuccess(firebaseAnalytics, event.drawing().getWord(),
event.numAttempts(), event.elapsedTimeInSeconds(), event.isHintUsed());
...
} else if (ev instanceof GameLevelSkipEvent) {
GameLevelSkipEvent event = (GameLevelSkipEvent) ev;
Log.d(TAG, "Round skipped: " + event);
// Add this line
QuizAnalytics.logLevelFail(firebaseAnalytics, event.drawing().getWord(),
event.numAttempts(), event.elapsedTimeInSeconds(), event.isHintUsed());
} else if (ev instanceof GameStageClearEvent) {
GameStageClearEvent event = (GameStageClearEvent) ev;
Log.d(TAG, "Stage cleared: " + event);
// Add this line
QuizAnalytics.logStageEnd(firebaseAnalytics, event.numCorrectAnswers());
...
}
});
}
Finally, add a call to logAdPrompt()
in showHintConfirmDialog()
method.
private void showHintConfirmDialog() {
// Add this line
QuizAnalytics.logAdPrompt(firebaseAnalytics, AD_UNIT_ID);
new AlertDialog.Builder(this)
.setTitle(R.string.need_a_hint)
.setMessage(R.string.need_a_hint_description)
.setPositiveButton(android.R.string.ok, (dlg, which) -> {
showRewardedVideoAd();
})
.setNegativeButton(android.R.string.no, null)
.show();
}
8. Debug Analytics Events
You can use DebugView to verify events being correctly logged. DebugView enables you to see the raw event data logged by your app on development devices in near real-time.
This is very useful for validation purposes during the instrumentation phase of development and can help you discover errors and mistakes in your analytics implementation.
Enable debug mode
Generally, events logged in your app are batched together over a period of approximately one hour and uploaded together. To validate your analytics implementation on the fly, you need to enable Debug mode on your development device to upload events with minimal delays.
First, open Terminal tool in Android Studio. It is located in the bottom toolbar.
Then execute the following command (make sure test Android device is connected to your computer or Android Emulator is running):
adb shell setprop debug.firebase.analytics.app com.google.firebase.codelab.awesomedrawingquiz
This behavior persists until you explicitly disable Debug mode by executing the following command:
adb shell setprop debug.firebase.analytics.app .none.
Debug Analytics events with DebugView
Once you have enabled Debug mode on your test device, go to the Firebase console and select DebugView from the menu. Then, on your test device, play your game to see events being logged and shown on the DebugView report.
You can access detailed information about each event by clicking the event name. As an example, the following screenshot shows parameter details associated with the level_start
event.
Please refer to DebugView help center article for more details.
9. Segment users with Audiences (Tip 3)
Audiences in Analytics
Audiences let you segment your users in ways that are meaningful to your app and your business. You can segment users by event or by user property, or combine events, parameters, and properties to include practically any subset of users.
In this step, you will create an audience that contains users who are highly engaged and perform very well in your game. You will include users who cleared more than 50 stages as "Expert users".
Create an Audience
Go to Firebase console then select Audiences menu under the ANALYTICS section. Then click the NEW AUDIENCE button to create a new audience.
Next, enter a name and a description of your new Audience as follows:
- Name: Expert users
- Description: Players who have cleared more than 50 stages with all correct answers
Choose "stage_end" in the conditions field. Since this event is triggered when a user finishes the stage, you should pick this event to define Expert Users audience.
Then, click Count > 0 condition to change the value. Modify the value to 50 as shown below.
Next, click ADD A PARAMETER button to add a parameter as an additional condition.
Remember in each stage there are 6 levels, you want to count stage_end events with all 6 quizzes answered correctly. To do so, choose "number_of_correct_answers" parameter, and set the condition to "equal to," "6," as follows:
You will see the following screen after you finish audience configuration for Expert users. Click CREATE to complete audience creation.
View Audience details
You can see a detailed report for an audience by clicking the audience name from the list as shown in the following screenshot. Remember, your graph will probably look much emptier than this example.
Metrics available from Audience report are as follows:
- User activity graph
- % of users
- ARPU(Average Revenue Per User)
- App version distribution
- Interests
- Location
- Demographics
0. Get Insights to Read Analytics Reports (Tip 4)
Enable custom parameter reporting
Google Analytics for Firebase will collect total number of event counts by default, but reporting for custom parameters needs to be turned on explicitly for each event parameter you're interested in. Once this is enabled, Google Analytics for Firebase will display additional cards to show the stats for custom parameters.
To register custom parameters for an event:
- Go to the Firebase console and select the Awesome Drawing Quiz project you created earlier. Then click Events from the navigation menu.
- In the row for the event you want to modify, click > Edit Parameter reporting.
- In the Enter parameter name field, enter the name of the parameter you'd like to register. If no match is found, just enter the parameter name then click ADD.
- Refer to the table below, and set the Type field to Text or Number accordingly. For numeric parameters, make sure you set the Unit of Measurement field as well.
- Click SAVE button to finish the setup.
Enable parameter reporting on each event listed below.
Event name | Parameter name | Parameter type | Unit of Measurement |
level_start | level_name | Text | N/A |
level_wrong_answer | level_name | Text | N/A |
ad_prompt | ad_unit_id | Text | N/A |
level_success | elapsed_time_sec | Number | Seconds |
hint_used | Number | Standard | |
level_name | Text | N/A | |
number_of_attempts | Number | Standard | |
level_fail | elapsed_time_sec | Number | Seconds |
hint_used | Number | Standard | |
level_name | Text | N/A | |
number_of_attempts | Number | Standard | |
stage_end | number_of_correct_answers | Number | Standard |
The following screenshot shows custom parameter reporting setup for level_success
event:
Find insights on Rewarded Video from Event reports
Rewarded Video is a highly user-centric format. It's initiated by a user choosing to watch an ad, and it gives the user a reward that impact a user engagement in a variety of ways, (in your Awesome Drawing Quiz game, a hint.)
Recall there are four parts to a Rewarded Ad in Awesome Drawing Quiz.
Ad prompt | Ad impression | Ad reward | Level success |
Go to the Firebase console and Select the Awesome Drawing Quiz project you created earlier. Click Events menu under ANALYTICS, to see our list of custom events.
Suppose that for level_success, we want to find out how many times a player used a hint to clear the levelOn the event list screen, click on level_success.
In the level_success detailed event report, find the hint_used card, and click SUM to see the total number of hints that were used. Note that earlier in your code, when a level is cleared using a hint, the event parameter hint_used was set to 1.
11. Change Ad Behavior on the fly (Tip 5)
Suppose you're curious if the showing one additional letter is a valuable enough hint for your users, and you're interested in experimenting with the number of letters your hint gives away.
To achieve this, you will change your project code so that the app retrieves the reward amount from the cloud using Firebase Remote Config. You will then create a value on the Firebase console to adjust this value without having to re-publish your app.
Add Firebase Remote Config to our game
First, add the dependency for Firebase Remote Config to app/build.gradle
file:
implementation 'com.google.firebase:firebase-config:16.0.0'
Next, create remote_config_defaults.xml
file under src/main/res/xml
directory. Then define a default value for reward_amount
parameter as shown in the following.
remote_config_defaults.xml
<?xml version="1.0" encoding="utf-8"?>
<defaultsMap>
<entry>
<key>reward_amount</key>
<value>1</value>
</entry>
</defaultsMap>
Now let's change your game's code a little bit to make room for Remote Config. in AwesomeDrawingQuiz.java
, add provideRemoteConfig()
method as follows:
AwesomeDrawingQuiz.java
public class AwesomeDrawingQuiz extends Application {
...
// Add provideRemoteConfig() method
private FirebaseRemoteConfig provideRemoteConfig() {
FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings settings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(BuildConfig.DEBUG)
.build();
remoteConfig.setConfigSettings(settings);
remoteConfig.setDefaults(R.xml.remote_config_defaults);
Task<Void> fetchTask;
if (BuildConfig.DEBUG) {
fetchTask = remoteConfig.fetch(0L);
} else {
fetchTask = remoteConfig.fetch();
}
fetchTask.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Log.d("AwesomeDrawingQuiz", "Remote config value fetched");
remoteConfig.activateFetched();
}
});
return remoteConfig;
}
}
Please note that you have enabled developer mode on debug build by calling setDeveloperModeEnabled()
.
In onCreate()
method, pass FirebaseRemoteConfig
object generated by provideRemoteConfig()
method as a parameter of AwesomeDrawingQuizViewModelFactory
's constructor.
public class AwesomeDrawingQuiz extends Application {
...
@Override
public void onCreate() {
...
// Pass FirebaseRemoteConfig as a parameter
viewModelFactory = new AwesomeDrawingQuizViewModelFactory(this, provideRemoteConfig());
}
private FirebaseRemoteConfig provideRemoteConfig() {
...
}
}
Next, modify AwesomeDrawingQuizViewFactory
's implementation to include FirebaseRemoteConfig
object as shown below.
AwesomeDrawingQuizViewFactory.java
public class AwesomeDrawingQuizViewModelFactory implements ViewModelProvider.Factory {
...
// Add below
private FirebaseRemoteConfig remoteConfig;
// Add a parameter for FirebaseRemoteConfig object
public AwesomeDrawingQuizViewModelFactory(
@NonNull Context context, @NonNull FirebaseRemoteConfig remoteConfig) {
...
// Add below
this.remoteConfig = remoteConfig;
}
@NonNull
@Override
@SuppressWarnings("unchecked")
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (modelClass.isAssignableFrom(GameViewModel.class)) {
// Pass FirebaseRemoteConfig object as a parameter
return (T) new GameViewModel(drawingDao, remoteConfig);
} else if (modelClass.isAssignableFrom(SplashViewModel.class)) {
...
}
...
}
}
Now you will wire up Remote Config parameter to our game. Add a field to retain a FirebaseRemoteConfig
instance in GameViewModel
class.
GameViewModel.java
public final class GameViewModel extends ViewModel {
...
// Add below
private FirebaseRemoteConfig remoteConfig;
...
// Add a parameter for FirebaseRemoteConfig object
public GameViewModel(DrawingDao drawingDao, FirebaseRemoteConfig remoteConfig) {
this.drawingDao = drawingDao;
this.remoteConfig = remoteConfig;
}
...
}
Next, implement fetchRewardAmount()
method in GameViewModel
and add a call to fetchRewardAmount()
in startLevel()
method.
public final class GameViewModel extends ViewModel {
...
// Define a key for Remote Config Parameter
private static final String KEY_REWARD_AMOUNT = "reward_amount";
void startLevel() {
numCorrectAnswers = 0;
gameDifficulty = GameSettings.DIFFICULTY_NORMAL;
// Add a call to fetchRewardAmount()
fetchRewardAmount();
seenWords.clear();
startLevel(1);
}
...
// Add fetchRewardAmount() method
private void fetchRewardAmount() {
this.disclosedLettersOnReward = (int) remoteConfig.getLong(KEY_REWARD_AMOUNT);
Log.d("GameViewModel", "Reward amount set to " + disclosedLettersOnReward);
}
...
}
Create a Remote Config parameter
Go to the Firebase console and select the Awesome Drawing Quiz project you created earlier. Then click Remote Config -> ADD YOUR FIRST PARAMETER button.
Name the parameter as reward_amount and set its default value to 2. Then click ADD PARAMETER button.
Click PUBLISH CHANGES button to make this configuration live to the users.
Run your app again, and ask for a hint. Notice that you now get 2 letters as your reward!
Now instead of having to use a hard-coded reward amount, your game can fetch the number of letters to show from Remote Config, which means you can change the reward amount at any time without requiring your users to download an app update.
12. Use A/B Testing to Optimize Ad Behavior (Tip 6)
When you are updating your app and using Firebase Remote Config to push it to an application with an active user base, you want to make sure you get it right. You might be uncertain about the following:
The best way to implement a feature to optimize the user experience.
Too often, app developers don't learn that their users dislike a new feature or an updated user experience until their app's rating in the app store declines. A/B testing can help measure whether your users like new variants of features, or whether they prefer the app as it currently exists. Plus, keeping most of your users in a control group ensures that most of your user base can continue to use your app without experiencing any changes to its behavior or appearance until the experiment has concluded.
The best way to optimize the user experience for a business goal.
Sometimes you're implementing product changes to maximize a metric like revenue or retention. With A/B testing, you set your business objectives, and Firebase does the statistical analysis to determine if a variant is outperforming the control group for your selected objective.
To A/B test feature variants with a control group, do the following:
- Create your experiment.
- Validate your experiment on a test device.
- Manage your experiment.
Recall that you just changed your game to give out two letters as a hint. However, you are not sure whether this new amount is good enough to help your users to clear a level and improve retention compared to the old value.
With Firebase A/B Testing, you can test out whether your hypothesis is true or not.
Create an Experiment
Go to the Firebase console and select Awesome Drawing Quiz project. Then, select A/B Testing under GROW section.
Click the CREATE EXPERIMENT button. From the following dialog, select Remote Config to create a Remote Config Experiment.
First, start with Experiment basics. Enter ‘Reward amount Test' as the name. Then select your game (com.google.firebase.codelab.awesomedrawingquiz) as the target app. Since you don't want to run an experiment aggressively, you will set this experiment to target 10% of all users.
Click NEXT button to configure experiment for a control group and variant group. Enter the name of the variant group as ‘Two letters as a reward.'
Next, click the ADD PARAMETER button and select reward_amount from the parameter list. Then enter 2 as a value for ‘Two letters as a reward' group, and change the value to 1 for the control group.
Click NEXT button to set a goal of the experiment. Since you want to confirm whether giving more hints (reveals 2x letters than the control group) helps users to beat a level or not, select level_success event as a goal metric.
Review an Experiment before it runs
Once you Click REVIEW button, a new experiment will be created. You can review your experiment settings at a glance.
If an experiment is in draft stage, you can test the experiment on your device before it rolled out to users. Once you click Details section, the section will expand, and you'll see Test devices menu on the screen. Click MANAGE TEST DEVICES button.
In the dialog, you can assign your test device to either a control group or a variant group by using Instance ID token. The following screenshot shows that a test device is assigned to the variant group(Two letters as a reward) group.
Run an Experiment
You can run an experiment by clicking START EXPERIMENT button. After you start an experiment, you can't modify experiment settings anymore.
Once an experiment has been running for a while, you can check in on its progress and see what your results look like for the users who have participated in your experiment so far.
It's totally up to you how many days that experiment will run, which variant to choose, etc.. However, it is highly encouraged to read the following sections before you make a decision.
To find more details on running experiments, refer to the following articles.
- Monitor an Experiment
- Roll out an Experiment to all users
- Expand an Experiment
- Duplicate or stop an Experiment
13. Send Push Notifications to Engage users (Tip 7)
Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably deliver messages at no cost. By using FCM, you can send push notifications to your users to drive user engagement and retention.
Add Firebase Cloud Messaging to our game
Add the dependency for Firebase Cloud Messaging to app/build.gradle
file.
implementation 'com.google.firebase:firebase-messaging:17.0.0'
Next, create AwesomeDrawingQuizMessagingService
class that extends FirebaseMessagingService
under com.google.firebase.codelab.awesomedrawingquiz.service
package. This is required to do any message handling, for example, receiving notification on apps in the background.
AwesomeDrawingQuizMessagingService.java
public class AwesomeDrawingQuizMessagingService extends FirebaseMessagingService {
// No additional code required
}
Next, create AwesomeDrawingQuizInstanceIdService
class that extends FirebaseInstanceIdService
under com.google.firebase.codelab.awesomedrawingquiz.service
package. It handles the creation, rotation, and updating of registration tokens, which is required for sending to specific devices or for creating device groups.
AwesomeDrawingQuizInstanceIdService.java
public class AwesomeDrawingQuizInstanceIdService extends FirebaseInstanceIdService {
// No additional code required
}
Finally, register these services in the app manifest as follows:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<application>
...
<!-- Register AwesomeDrawingQuizMessagingService -->
<service
android:name=".service.AwesomeDrawingQuizMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- Register AwesomeDrawingQuizInstanceIdService -->
<service
android:name=".service.AwesomeDrawingQuizInstanceIdService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
Send a notification message from Notifications composer
You can send push notifications to users by using Notifications composer without having to implement your own server for sending push messages.
First, go to Firebase console then select Cloud Messaging menu under GROW section. Then click SEND YOUR FIRST MESSAGE button to compose a new message.
In the Compose message screen, you can enter Message text (a message content that users will see) and Message label (Used to identify the message on Firebase console; not shown to users) as you want.
You can specify a delivery date of the message. If you choose Send Now, the message will be sent immediately, once you click the SEND MESSAGE button.
If you want to schedule a message, you can select Send Later option instead. You can choose the date, time, and time zone of a scheduled message.
Next, target users that you want to send a message. You can choose targeted users by User segment, Topic, and Single device.
If you choose User segment, you have to select an App before you define additional conditions(User audiences, User property, App version, Languages, and Predictions). For example, the below screenshot shows a configuration that targets all users of Awesome Drawing Quiz app.
Similarly, you can also target Expert users, a user audience that you have created before, as follows.
If you're interested in sending a message by Topic, please refer to this documentation for more details.
Additionally, you can define Conversion events of the message and configure Advanced options(Notification title, Android Notification channel, etc.). These two steps are optional.
Once all configurations are done, you can draft a message by clicking SAVE AS A DRAFT, or send/schedule a message by clicking the SEND MESSAGE button.
Please note that if you want to see the message on your device, you make sure that Awesome Drawing Quiz is not in the foreground. Otherwise, it will silently consume your notification.
14. Fine-tune Push Notification Message (Tip 8)
When you are reaching out to your users or starting a new marketing campaign, you want to make sure that you get it right. A/B testing can help you find the optimal wording and presentation by testing message variants on selected portions of your user base. Whether your goal is better retention or conversion on an offer, A/B testing can perform statistical analysis to determine if a message variant is outperforming the control group for your selected objective.
To A/B test feature variants with a control group, do the following:
- Create your experiment.
- Validate your experiment on a test device.
- Manage your experiment.
Create an Experiment
By using Notification composer in Firebase console, you can evaluate multiple variants on a single notification message.
Go to the Firebase console and select Awesome Drawing Quiz project. Then, select A/B Testing menu under GROW section.
Click CREATE EXPERIMENT button at the top-right corner of the screen. From the following dialog, select Notifications to create a Notification Experiment.
First, start with Experiment basics. Enter ‘Re-engage users' as a name. Then select your game(com.google.firebase.codelab.awesomedrawingquiz) as a target app. Since you don't want to run an experiment aggressively, you set this experiment to target 10% of all users.
Click NEXT button to configure experiment for a control group and variant group. You will test which push message scenario will help to re-engage our users. The scenarios are as follows:
- Control group: Don't send a push message
- 5000_drawings: More than 5000 drawings are still waiting for you!
- good_day_to_guess: It's a good day to guess - try few more drawings to keep your streak!
Start by adding a new variant by clicking the ADD VARIANT button. Then enter the content for each variant as follows:
Please note that you left the control group's message field blank. If you leave the field blank, Firebase will not send a notification to this group.
Click NEXT to set a goal for the experiment. Since you want to make users play a few more levels by receiving a message, set the stage_start event as a goal metric.
Finally, you can specify message options including delivery date, title, custom data, etc. For the purpose of this experiment, you can leave everything set to their default values..
Review an Experiment before it runs
Once you Click REVIEW button, a new experiment will be created. You can review your experiment settings at a glance.
If an experiment is in draft stage, you can test the experiment on your device before it rolled out to users. Once you click the Details section, the section will expand, and you will see a Test devices menu on the screen. Click the MANAGE TEST DEVICES button.
In the dialog, you can assign your test device to either a control group or a variant group by using Instance ID token. The following screenshot shows that a test device is being sent the "5000 drawings" notification.
Run an Experiment
You can run an experiment by clicking START EXPERIMENT button. Once you start an experiment, you can't modify the experiment settings anymore.
Once an experiment has been running for a while, you can check in on its progress and see what your results look like for the users who have participated in your experiment so far.
It's totally up to you how many days that experiment will run, which variant to choose, etc.. However, it is highly encouraged to read the following sections before you make a decision.
- Monitor an Experiment
- Roll out an Experiment to all users
- Expand an Experiment
- Duplicate or stop an Experiment
15. Predict user behavior with Firebase Predictions (Tip 9)
Firebase Predictions applies machine learning to your analytics data to create dynamic user groups based on your users' predicted behavior.
Enable Analytics data sharing and Predictions
Firebase Predictions uses the data you log with Google Analytics for Firebase to make its predictions. Since you've already added Analytics into your game, the only step left is to share this data with Firebase Predictions.
Go to the Firebase console and select Predictions panel. You will see the following screen.
Click TURN PREDICTIONS ON button to enable Analytics data sharing for Predictions.
Predefined Predictions
By default, Predictions provides four types of predictions: churn and not_churn, which predicts which users will disengage (or won't) from your app over the next 7 days (that is, they will not open the app or app-related notification messages), and spend and not_spend, which predicts which users will (or won't) spend money in your app over the next seven days.
Once you turn on Predictions in your project, you'll see the following screen that shows you a list of predictions provided by Firebase by default.
Predictions needs sufficient event data volume to make meaningful predictions. If Predictions does not have sufficient data to make a prediction, it will display "Preparing a prediction" message as you can see from the above screenshot.
Once prediction data is ready for use, its status will be updated, and the number of users that can be targeted along with its risk tolerance will also be shown on the prediction card. The following screenshot shows an example of prediction cards:
For more information about predefined predictions, refer to developer documentation.
Custom Predictions
In addition to Predefined Predictions, Firebase Predictions allows us to create predictions based on any conversion event in your analytics data.
In this Codelab, we'll make two Custom Predictions based on the level_success
custom event. We need to mark level_success
event as a conversion event to make predictions based on it.
Select Events under ANALYTICS, then mark level_success as a conversion event as shown in the below screenshot.
Next, select the Predictions menu under GROW. Then click Create a prediction button to create a custom prediction.
We'll create two predictions based on the level_success event. First one is will_win_level, which predicts users who are likely to successfully complete a level. Next one is will_not_win_level, which predicts users who are not likely to beat a level.
Create each prediction as shown below.
Once you finish creating two custom predictions, you'll see those predictions in the predictions list as follows.
Similar to Predefined Predictions, Firebase also requires sufficient event volume to make predictions for Custom Predictions.
Once prediction data is ready for use, its status will be updated, and the number of users that can be targeted along with its risk tolerance will also be shown on the prediction card.
16. Target users based on Predictions (Tip 10)
Firebase Predictions makes it easy to provide your app's users a different experience depending on your users' predicted behavior.
Adjust Difficulty to users who are likely to churn
You can use Firebase Predictions to identify users who are likely to disengage from your game, and apply a user retention strategy to those users. In this section, we'll lower the difficulty of our game for users that are predicted to churn out.
First, we need to make game difficulty remotely configurable. To do so, let's declare game difficulty as a Remote Config parameter.
Open remote_config_defaults.xml file, then add an entry for new parameter ‘difficulty' with its default value.
remote_config_defaults.xml
<?xml version="1.0" encoding="utf-8"?>
<defaultsMap>
<!-- Add below -->
<entry>
<key>difficulty</key>
<value>1</value>
</entry>
...
</defaultsMap>
Difficulty value of 1 means ‘Normal' difficulty in your game. You can refer to GameSettings.java
to see predefined difficulties. (Easy, Normal, Hard)
GameSettings.java
public final class GameSettings {
public static final int MAX_LEVEL = 6;
public static final int DIFFICULTY_EASY = 0;
public static final int DIFFICULTY_NORMAL = 1;
public static final int DIFFICULTY_HARD = 2;
}
Next, open GameViewModel.java
file. Then implement fetchDifficulty()
method and add a call to fetchDifficulty()
in startLevel()
method as follows:
GameViewModel.java
public final class GameViewModel extends ViewModel {
// Define a key for Remote Config Parameter
private static final String KEY_DIFFICULTY = "difficulty";
...
void startLevel() {
numCorrectAnswers = 0;
// Replaces gameDifficulty = GameSettings.DIFFICULTY_NORMAL;
fetchDifficulty();
fetchRewardAmount();
seenWords.clear();
startLevel(1);
}
...
// Add a method to fetch game difficulty from Remote Config
private void fetchDifficulty() {
int difficulty = (int) remoteConfig.getLong(KEY_DIFFICULTY);
Log.d("GameViewModel", "Game difficulty set to " + difficulty);
this.gameDifficulty = difficulty;
}
...
}
Now your game will fetch the game difficulty by Remote Config, which means you can change the game difficulty dynamically. Since you want to lower the difficulty to users who are likely to disengage, you need to define a condition that is used to segment your users.
To do so, select Remote Config menu under GROW section in Firebase console. Then click ADD PARAMETER button to add a new Remote Config parameter. Once a dialog pops up, enter difficulty as a parameter key and set 1 as a default value.
In this Codelab, we'll target user groups who are likely to churn, which have low to medium risk tolerance level. Before you can target users in Remote Config, you need to define a condition for each of them.
Click Add value for condition > Define a new condition. Then you'll see the following dialog.
Let's start with defining a condition for a predicted user group who are predicted to churn in low risk tolerance. Name it Likely to churn, then select com.google.firebase.codelab.awesomedrawingquiz as an App.
Click AND button to add a new constraint. Select Prediction > Predict: churn from the list then select Low risk tolerance. This will target a smaller group of users, but it will minimize the chance of including false positives.
Once you click CREATE CONDITION button, a new condition will be added. Set a value for this condition to 0. (DIFFICULTY_EASY
)
Click the UPDATE button. You'll see new conditions are added in the parameter.
Finally, click PUBLISH CHANGES button to make this configuration live to the users.
Now Remote Config will adjust the game difficulty by predicted user behavior. Users who are likely to churn will get easier game experience than the others.
Send push notifications to users who are not likely to clear a level
You may want to encourage users who are predicted to not able to clear a level to increase retention rate. In this case, you can target that kind of users by using the ‘will_not_win_level' custom prediction that we created in the previous section.
First, select Cloud Messaging menu under GROW section in Firebase console. Then click NEW MESSAGE button to compose a new message.
After composing a message text, move on to Target section to specify users who will receive a message. Select com.google.firebase.codelab.awesomedrawingquiz as a target app, then click AND.
Next, you will add a condition to target users who are not likely to fully complete a level. To do so, select Predict: will_not_win_level as a condition, and select Low risk tolerance level. (Note: You can choose any risk tolerance level that you want)
Now all set! Once you click the SEND MESSAGE button, a push message will be delivered only to users who are not likely to clear a level, without disturbing other users.
17. Congratulations
You've reached the end of the codelab, you now can make go/no-go decisions on a new ad implementation based on data, change app settings on the fly, learn more about your users, and create customized app experiences based on your users' predicted behavior.
Learn More
- Read AdMob with Firebase for more details on why and how AdMob and Firebase are better together
- Read the Rewarded Video Publisher Get Started guide for more details on AdMob rewarded video ads
Comments
Post a Comment