1. Introduction
Ads are a crucial part of your app's overall user experience. Good ad implementations can help improve your overall app experience and even improve user retention and engagement. For example, Rewarded ads enable you to provide 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, making an excellent ads experience isn't easy. You may have questions like: How often should you show these ads? Where and when should you show them? What should the award be? 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, AdMob, and several other powerful yet easy-to-use tools that Firebase offers, fine tuning your app in a data-driven way has become much easier and more streamlined. Today, we'll be showing you how you can get started!
What you'll build
This codelab is the first of three codelabs that will guide you through building an app called Awesome Drawing Quiz, a game that lets players guess the name of the drawing. It will demonstrate how you can incorporate Rewarded Ads and Firebase services in your game.
In this codelab, you'll integrate Google Analytics for Firebase to record some important app events. Also, you'll learn how to read the app analytics shown in the Firebase console.
If you run into any issues (code bugs, grammatical errors, unclear wording, etc.) as you work through this codelab, please report the issue via the Report a mistake link in the lower left corner of the codelab.
What you'll learn
- How to setup Google Analytics for Firebase in your app
- How to record the app events
- How to read the app analytics shown in the Firebase console
What you'll need
- Android Studio version 4.1+
- A Google account
- A test device with Android 5.0+ with a USB cable to connect your device, or an Android Emulator running AVD (Android Virtual Device) with a system image that supports Play Store/Google APIs
How would you rate your level of experience with AdMob?
How would you rate your level of experience with Firebase?
2. Setup development environment
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 named admob-firebase-codelabs-android
.
...or clone the GitHub repository from the command line.
$ git clone https://github.com/googlecodelabs/admob-firebase-codelabs-android
The repository contains four folders as follows:
- 101-base — Starting code that you will build in this codelab.
- 101-complete_and_102-base — Completed code for this codelab & starter for the 102 codelab.
- 102-complete — Completed code for the 102 codelab.
Import the starter app
Launch Android Studio and choose "Import project" on the welcome screen. Then select the 101-base directory from the code you have downloaded.
You should now have the project open in Android Studio.
3. 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 Console.
- From the Apps menu, click "Add App".
- When asked "Have you published your app on Google Play or the App Store," answer "NO."
- Name the app "Awesome Drawing Quiz," choose "Android" as the Platform, then click "Add".
Once you created an AdMob app in your account, follow the steps described below to create a new Rewarded Video Ad Unit.
- Click the Apps menu in AdMob frontend, then select "Awesome Drawing Quiz" from the app list.
- 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 the reward amount to 1, and the reward item to "hint" (this is the reward that the app currently gives to users). Click CREATE AD UNIT to create a new Rewarded Video ad unit.
- When successfully created, you will see the instructions similar to the following:
- Go back to the Android project, and update the AdMob app id and ad unit id constants to the ones that you have created in the previous step.
strings.xml
<!-- Update the value with your AdMob app id -->
<string name="admob_app_id">YOUR_ADMOB_APP_ID</string>
GameActivity.kt
// Update the value with your Rewarded Video ad unit id
private const val AD_UNIT_ID = "<YOUR_AD_UNIT_ID>";
4. Setup Firebase Project
Create a new project from the Firebase Console
- Go to the Firebase console.
- Select Add Project, and name your project "Awesome Drawing Quiz". Make sure that the Enable Google Analytics for this project radio button is turned on.
- Select the Google Analytics account you plan to use. For most, selecting the Default Account for Firebase option should suffice, but if you have another Google Analytics account you would like to use, select that here.
- Click on Create project.
Add the Android app
- From the overview screen of your new project, click Add Firebase to your Android app.
- Enter the codelab's package name: com.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.
Declare dependency versions
Let's start by adding the version of each dependency required to integrate Firebase in the project. Open dependencies.gradle
file located at the project root, then add google-services plugin, Firebase Analytics SDK and Firebase Core SDK version.
dependencies.gradle
ext {
...
// TODO: Declare google-services plugin version (101)
googleServicesPluginVersion = '4.3.4'
...
// TODO: Declare Firebase BOM version (101)
firebaseBomVersion = '26.2.0'
...
}
Apply google-services plugin to your app
The google-services plugin uses the google-services.json
file to configure your application to use Firebase.
Add google-services as a classpath in the build.gradle
file located at the project root directory.
build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
...
dependencies {
classpath "com.android.tools.build:gradle:$androidPluginVersion"
// TODO: Add google-services plugin (101)
classpath "com.google.gms:google-services:$googleServicesPluginVersion"
...
}
}
...
Then, apply the google-services plugin by adding a line in app/build.gradle
file as follows:
app/build.gradle
apply plugin: 'com.android.application'
// TODO: Apply google-services plugin (101)
apply plugin: 'com.google.gms.google-services'
android {
...
}
dependencies {
...
}
Add Firebase SDK to the project
Still in your app/build.gradle
file, add the Analytics SDK to the app dependencies.
app/build.gradle
apply plugin: 'com.android.application'
android {
...
}
dependencies {
...
// TODO: Import the Firebase BoM (101)
implementation platform("com.google.firebase:firebase-bom:$firebaseBomVersion")
// COMPLETE: Add Firebase Analytics dependency (101)
implementation 'com.google.firebase:firebase-analytics-ktx'
...
}
...
Sync your project with gradle files
To make sure that all dependencies are available to your app, sync your project with Gradle files. Select File > Sync Project with Gradle Files menu to sync your project with Gradle files.
5. Link AdMob to Firebase Project
Complete the steps below to link your apps to Firebase.
- Sign in to your AdMob account at https://apps.admob.com.
- Click Apps in the sidebar.
- Select "Awesome Drawing Quiz". If you don't see it in the list of recent apps, you can click View all apps to search a list of all of the apps you've added to AdMob.
- Click App settings in the sidebar.
- Click Link to Firebase.
- Select "Link to an existing Firebase project and create a new Firebase app" option. Then Select "Awesome Drawing Quiz" project from the dropdown menu.
- After you click the "CONTINUE" button, you'll see "Successfully linked" message. Click the "DONE" button to finish.
Once you link your AdMob app to Firebase Project, it will unlock some additional features both on AdMob and Firebase console as follows:
Revenue card (AdMob)
From the Revenue card, you can take a holistic look at all possible revenue streams in a single place. Supported revenue sources are as follows:
- AdMob (Estimated)
- Mediated Ad Networks (Observed)
- In-app purchases
- E-Commerce purchases
User metrics card (AdMob)
From the user metrics card, you can see how changes to your ads experience might impact user behavior.
Rewarded Ads Report (AdMob)
The Rewarded Ads Report offers a variety of metrics that will help publishers understand how users are interacting with their rewarded ads.
Total revenue card (Firebase)
After you link your AdMob app to Firebase, Total revenue card on Firebase dashboard will display the revenue from the AdMob along with in-app-purchases and e-commerce purchases.
Ad events reporting (Firebase)
Ad-specific events (click, impression, and reward events) are automatically collected and available for use in Google Analytics for Firebase.
6. Run the project
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 skip the level by clicking the ‘SKIP' button.
You may want an additional clue that helps you guess the answer. You can get an extra clue by clicking the ‘HINT' button and watching a Rewarded Video ad. After you complete watching the ad, one extra letter will be disclosed as a reward.
7. Add app events
To deeply understand the user journey in the Awesome Drawing Quiz, you will define a few custom events that track user's behavior in the game as follows:
Event name | Triggered... | Parameters |
game_start | when a user starts a new game | 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_reward_prompt | when a user taps the hint button, and is prompted to watch a Rewarded Video Ad | ad_unit_id |
ad_reward_impression | when a user starts to watch a Rewarded Video Ad | ad_unit_id |
level_success | when a user submits a correct answer (clears a level) | level_name, number_of_attempts, elapsed_time_sec, hint_used |
level_fail | when a user skips a level | level_name, number_of_attempts, elapsed_time_sec, hint_used |
game_complete | when the game is over | number_of_correct_answers |
Description of each parameter associated with each event is as follows:
Event name | Parameter name | Description |
level_start | level_name | Name of the drawing shown in the level (e.g., "banana") |
level_wrong_answer | level_name | when a user submits a wrong answer |
ad_reward_prompt | ad_unit_id | An ad unit id used to display a Rewarded Video Ad |
ad_reward_impression | ad_unit_id | An ad unit id used to display a Rewarded Video Ad |
level_success | level_name | Name of the drawing shown in the level (e.g., "banana") |
level_success | number_of_attempts | Number of attempts made to clear a level |
level_success | elapsed_time_sec | Elapsed time to clear a level, in seconds |
level_success | hint_used | Whether a user used a hint (watched a Rewarded Video Ad) or not to clear a level (1: used a hint / 0: cleared a level without a hint) |
level_fail | level_name | Name of the drawing shown in the level (e.g., "banana") |
level_fail | number_of_attempts | Number of attempts made to clear a level |
level_fail | elapsed_time_sec | Elapsed time to clear a level, in seconds |
level_fail | hint_used | Whether a user used a hint (watched a Rewarded Video Ad) or not to clear a level (1: used a hint / 0: cleared a level without a hint) |
game_complete | number_of_correct_answers | Number of levels cleared in the game |
Create a helper class for logging custom events
To log the analytics event with ease, you will create a helper class to manage custom events.
First, create a new Kotlin file (not a Kotlin class) and name it QuizAnalytics.kt
under com.codelab.awesomedrawingquiz
package. Create fields that define the name of your custom events and their parameters.
QuizAnalytics.kt
private const val EVENT_AD_REWARD_PROMPT = "ad_reward_prompt"
private const val EVENT_AD_REWARD_IMPRESSION = "ad_reward_impression"
private const val EVENT_LEVEL_FAIL = "level_fail"
private const val EVENT_LEVEL_SUCCESS = "level_success"
private const val EVENT_LEVEL_WRONG_ANSWER = "level_wrong_answer"
private const val EVENT_GAME_START = "game_start"
private const val EVENT_GAME_COMPLETE = "game_complete"
private const val PARAM_AD_UNIT_ID = "ad_unit_id"
private const val PARAM_ELAPSED_TIME_SEC = "elapsed_time_sec"
private const val PARAM_HINT_USED = "hint_used"
private const val PARAM_NUMBER_OF_ATTEMPTS = "number_of_attempts"
private const val PARAM_NUMBER_OF_CORRECT_ANSWERS = "number_of_correct_answers"
Next, add extension functions that help you log custom events in your game. Note that most of the custom events include parameters so that you have more context of each event. Also note that a couple of event names and parameters (FirebaseAnalytics.Event.LEVEL_NAME
and FirebaseAnalytics.Event.LEVEL_START
) are already defined by Analytics, so we're going to use those.
QuizAnalytics.kt
...
fun FirebaseAnalytics.logGameStart() = logEvent(EVENT_GAME_START, null)
fun FirebaseAnalytics.logLevelStart(levelName: String) {
logEvent(FirebaseAnalytics.Event.LEVEL_START) {
param(FirebaseAnalytics.Param.LEVEL_NAME, levelName)
}
}
fun FirebaseAnalytics.logLevelWrongAnswer(levelName: String) {
logEvent(EVENT_LEVEL_WRONG_ANSWER) {
param(FirebaseAnalytics.Param.LEVEL_NAME, levelName)
}
}
fun FirebaseAnalytics.logAdRewardPrompt(adUnitId: String) {
logEvent(EVENT_AD_REWARD_PROMPT) {
param(PARAM_AD_UNIT_ID, adUnitId)
}
}
fun FirebaseAnalytics.logAdRewardImpression(adUnitId: String) {
logEvent(EVENT_AD_REWARD_IMPRESSION) {
param(PARAM_AD_UNIT_ID, adUnitId)
}
}
fun FirebaseAnalytics.logLevelSuccess(
levelName: String,
numberOfAttempts: Int,
elapsedTimeSec: Int,
hintUsed: Boolean
) {
logEvent(EVENT_LEVEL_SUCCESS) {
param(FirebaseAnalytics.Param.LEVEL_NAME, levelName)
param(PARAM_NUMBER_OF_ATTEMPTS, numberOfAttempts.toLong())
param(PARAM_ELAPSED_TIME_SEC, elapsedTimeSec.toLong())
param(PARAM_HINT_USED, if (hintUsed) 1 else 0)
}
}
fun FirebaseAnalytics.logLevelFail(
levelName: String,
numberOfAttempts: Int,
elapsedTimeSec: Int,
hintUsed: Boolean
) {
logEvent(EVENT_LEVEL_FAIL) {
param(FirebaseAnalytics.Param.LEVEL_NAME, levelName)
param(PARAM_NUMBER_OF_ATTEMPTS, numberOfAttempts.toLong())
param(PARAM_ELAPSED_TIME_SEC, elapsedTimeSec.toLong())
param(PARAM_HINT_USED, if (hintUsed) 1 else 0)
}
}
fun FirebaseAnalytics.logGameComplete(
numberOfCorrectAnswers: Int
) {
logEvent(EVENT_GAME_COMPLETE) {
param(PARAM_NUMBER_OF_CORRECT_ANSWERS, numberOfCorrectAnswers.toLong())
}
}
Log analytics events in the game
In the GameViewModel
class, add a new property for the FirebaseAnalytics
instance.
GameViewModel.kt
class GameViewModel(
...
// TODO: Accept FirebaseAnalytics instance as a parameter (101)
private val analytics: FirebaseAnalytics,
) : ViewModel() {
...
}
Next, in the AwesomeDrawingQuizViewModelFactory
class, add a new property as you previously did in GameViewModel
.
AwesomeDrawingQuizViewModelFactory.kt
class AwesomeDrawingQuizViewModelFactory(
...
// TODO: Accept FirebaseAnalytics instance as a parameter (101)
private val analytics: FirebaseAnalytics,
) : ViewModelProvider.Factory {
...
}
Next, in the AwesomeDrawingQuiz
class, add the provideFirebaseAnalytics()
function and update the provideViewModelFactory()
function to pass the FirebaseAnalytics
instance to the AwesomeDrawingViewModelFactory
.
AwesomeDrawingQuiz.kt
class AwesomeDrawingQuiz : Application() {
...
fun provideViewModelFactory() = AwesomeDrawingQuizViewModelFactory(
this,
provideGameSettings(),
// TODO: Pass FirebaseAnalytics instance as a parameter (101)
provideFirebaseAnalytics(),
)
// TODO: Provide FirebaseAnalytics instance (101)
private fun provideFirebaseAnalytics() = Firebase.analytics
...
}
Now you're ready to implement custom events. First, in the startGame()
function, call logGameStart()
to indicate a game has started.
Because logGameStart()
is an extension function of FirebaseAnalytics
class, you can call it from the instance of the FirebaseAnalytics
class.
GameViewModel.kt
fun startGame() {
...
// TODO: Log game_start event (101)
analytics.logGameStart()
...
}
Next, in the checkAnswer()
function, add level_success
and level_wrong_answer
events.
GameViewModel.kt
fun checkAnswer(userAnswer: String) {
...
if (correct) {
...
// TODO: Log level_success event (101)
analytics.logLevelSuccess(
levelName = drawing.word,
numberOfAttempts = numAttempts,
elapsedTimeSec = elapsedTimeInSeconds,
hintUsed = isHintUsed,
)
...
} else {
// TODO: Log level_wrong_answer event (101)
analytics.logLevelWrongAnswer(levelName = drawing.word)
...
}
}
Next, in the skipLevel()
function, add level_fail event to mark the level as failed.
GameViewModel.kt
fun skipLevel() {
...
// TODO: Log level_fail event (101)
analytics.logLevelFail(
levelName = drawing.word,
numberOfAttempts = numAttempts,
elapsedTimeSec = elapsedTimeInSeconds,
hintUsed = isHintUsed,
)
...
}
Next, implement logAdRewardPrompt()
and logAdRewardImpression()
functions to track the user's behavior regarding the Rewarded Video Ad.
GameViewModel.kt
fun logAdRewardPrompt(adUnitId: String) {
// TODO: Log ad_reward_prompt event (101)
analytics.logAdRewardPrompt(adUnitId)
}
fun logAdRewardImpression(adUnitId: String) {
// TODO: Log ad_reward_impression event (101)
analytics.logAdRewardImpression(adUnitId)
}
Finally, modify requestNewDrawing()
and finishGame()
function to add level_start and game_complete custom events.
GameViewModel.kt
private fun requestNewDrawing() {
...
drawingRequestDisposable = drawingDao.getRandomDrawings(seenWords)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { d ->
...
// TODO: Log level_start event (101)
analytics.logLevelStart(d.word)
...
}
}
private fun finishGame() {
// TODO: Log game_complete event (101)
analytics.logGameComplete(numCorrectAnswers)
...
}
8. Debug analytics events
You can use DebugView in the Firebase console to verify that events are 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 any errors 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.
To enable Debug mode, complete the following steps:
- Open the Terminal tool window in Android Studio (View > Tool Windows > Terminal).
- 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.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 your project in the Firebase console and select Analytics > 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 on 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. Enable custom dimensions and metrics
By default, Google Analytics for Firebase collects the total number of events. For each event parameter you're interested in, you need to explicitly turn on reporting for that parameter. Google Analytics for Firebase can then display additional cards to show the stats for custom parameters.
To register custom dimensions and metrics:
- Go to the Firebase console and select the Awesome Drawing Quiz project you created earlier.
- Click Analytics > Events from the navigation menu.
- Click Manage Custom Definitions.
- In the Custom dimensions tab, click Create custom dimensions.
- In the Event parameter name field, enter level_name and click Save to complete parameter registration.
- Next, select the Custom metrics tab and click Create custom metrics.
- Enter parameter name, unit of measurements for the following parameters.
Parameter name | Parameter type | Unit of Measurement |
number_of_attempts | Number | Standard |
hint_used | Number | Standard |
elapsed_time_sec | Number | Seconds |
number_of_correct_answers | Number | Standard |
10. Get insights from the Event report
As you've added a few events in the game, you should be able to answer the questions regarding the user behavior of the game. Here are a few insights that you can get from the Firebase events report.
Which level has the highest number of wrong answers?
To answer this question, you should find out how many level_wrong_answer
events were triggered per each level.
Click the level_wrong_answer
from the events report. In the level_wrong_answer
event report, find the level_name
card. You'll see the values associated with the level_name
parameter on that card as follows.
According to the above screenshot, you can easily find out the horizon has the highest number of wrong answers, which means it's difficult to users compared to the other levels.
By using the insight you've got from here, you can decide not to provide difficult levels to novice users to keep a high retention rate.
How many attempts were made to clear a level, on average?
In the Awesome Drawing Quiz, users can submit the answer to each level as much as they want.
Because you've enabled parameter reporting on the number_of_attempts
parameter in the level_success
event, you can see the detailed metrics for that parameter.
Click the level_success
event from the events report. In the level_success
event report, find the number_of_attemps
card. You'll see the average number of attempts on that card as follows:
You can use the insight from here to optimize the difficulty of the game on average. For example, if the average number of attempts are too close to 1, you may consider making the game a little bit more challenging.
Did users try to solve the question by getting a hint, even though they failed to clear a level at last?
When a user decides to skip a level, a level_fail
event is triggered. There can be many reasons for the user's decision.
However, since the game can give them a hint after they watch a Rewarded Video Ad, it's important to know whether the user tried to clear the level with the help of the hint.
Click the level_fail
event from the events report. In the level_fail
event report, find the hint_used
card. You'll see the average number of hint_used
event parameters. Note that the parameter's value is 1 if a hint was used and 0 if a hint wasn't used.
If the numbers on the hint_used
card are close to 0, it's the signal that the reward (hint) is not helpful enough for these users. Also, you're losing the opportunity to increase the revenue from a Rewarded Video Ad.
Therefore, you should consider offering a larger reward, so users can engage with the game more deeply, providing you with an uplift in revenue from Rewarded Video Ads.
How many levels were cleared in each game, on average?
There are a total of 6 levels for each game in the Awesome Drawing Quiz. Once the user finishes 6 levels (no matter whether they cleared or failed each level), a game_complete
event is triggered with number_of_correct_answers
as a parameter. The number_of_correct_answers
parameter indicates the number of levels where the user provided a correct answer.
Click game_complete
event from the events report. In the game_complete event report, find the number_of_correct_answers
card. You'll see the average number of number_of_correct_answers
event parameters.
If the average number of cleared levels is too low, you should consider rearranging the levels in the game to help people beat the earlier levels more easily, so they can keep playing your game without losing interest.
11. All done!
You have completed AdMob+Firebase 101 Android Codelab. You can find the completed code for this Codelab on 101-complete_and_102-base folder.
In the next part of the AdMob+Firebase Codelab, you'll learn how to use a funnel to visualize the app event flow. The next part will also cover how to use the Remote Config and A/B testing to optimize the parameter value in the game without an app update.