AdMob+Firebase 101 Android: Setup & Analytics Basics

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?

Novice Intermediate Proficient

How would you rate your level of experience with Firebase?

Novice Intermediate Proficient

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:

  • android_studio_folder.png101-base — Starting code that you will build in this codelab.
  • android_studio_folder.png101-complete_and_102-base — Completed code for this codelab & starter for the 102 codelab.
  • android_studio_folder.png102-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:

  1. Go to the AdMob Console.
  2. From the Apps menu, click "Add App".
  3. When asked "Have you published your app on Google Play or the App Store," answer "NO."
  4. 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.

  1. Click the Apps menu in AdMob frontend, then select "Awesome Drawing Quiz" from the app list.
  2. Click ADD AD UNIT to create a new Rewarded Video ad unit.
  3. Select Rewarded for the Ad format.

7672f41ec611101b.png

  1. 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.

6d067814a2c38264.png

  1. When successfully created, you will see the instructions similar to the following: ff872a005a07b75e.png
  2. 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

  1. Go to the Firebase console.
  2. 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.
  3. 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.
  4. Click on Create project.

Add the Android app

  1. From the overview screen of your new project, click Add Firebase to your Android app.
  2. Enter the codelab's package name: com.codelab.awesomedrawingquiz
  3. Set a nickname for your app: Awesome Drawing Quiz
  4. Leave the SHA-1 field blank since SHA-1 is not required for this project.
  5. 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 android_studio_folder.pngapp directory in your project.

32419a0fa25a1405.png

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.

  1. Sign in to your AdMob account at https://apps.admob.com.
  2. Click Apps in the sidebar.
  3. 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.
  4. Click App settings in the sidebar.
  5. Click Link to Firebase.
  6. Select "Link to an existing Firebase project and create a new Firebase app" option. Then Select "Awesome Drawing Quiz" project from the dropdown menu.
  7. 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

10fe118249e11150.png

User metrics card (AdMob)

From the user metrics card, you can see how changes to your ads experience might impact user behavior.

5f56366f1b31d4a1.png

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.

658a2868777690ea.png

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.

98cb283977b023a.png

Ad events reporting (Firebase)

Ad-specific events (click, impression, and reward events) are automatically collected and available for use in Google Analytics for Firebase.

bf77bd8c00c1441b.png

6. Run the project

Once you compile and run the project, you'll see the following screen when the app starts.

15f1d8041988974c.png

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.

8e87e96256d6874a.png 9c4a0143c3234cb2.png

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.

edcf6f0d833ea4ea.png 47ab9a07b1c71711.png

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:

  1. Open the Terminal tool window in Android Studio (View > Tool Windows > Terminal).

c8dc1b4f08a224b8.png

  1. 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.

827059255d09ac00.png

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.

475db00d05d03ab8.png

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:

  1. Go to the Firebase console and select the Awesome Drawing Quiz project you created earlier.
  2. Click Analytics > Events from the navigation menu.
  1. Click Manage Custom Definitions.
  2. In the Custom dimensions tab, click Create custom dimensions.
  3. In the Event parameter name field, enter level_name and click Save to complete parameter registration.

3d20ee9d7de74e9b.png

  1. Next, select the Custom metrics tab and click Create custom metrics.
  2. 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.

25da426bbc0c612c.png

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:

43de290f9f1a0ac9.png

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.

313814372cd7c8a4.png

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.

d9eeaa019d1bceb4.png

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 android_studio_folder.png101-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.