Skip to main content

Uninstall Tracking through Firebase Analytics

This guide provides instructions for setting up uninstall tracking for Android apps using the Apptrove .NET MAUI SDK and Firebase Analytics. Uninstall tracking monitors user churn, enabling analysis of retention and optimization of acquisition strategies by sending uninstall data to Apptrove.

End Goal

After completing this setup, you will set the Apptrove ID as a Firebase user property:

var appTroveId = await AppTroveSDK.GetAppTroveId();
FirebaseAnalytics.GetInstance(context).SetUserProperty("ct_objectId", appTroveId);
Alternative Method

For FCM-based uninstall tracking, see Through Cloud FCM.


Overview

Uninstall tracking uses Firebase Analytics to capture the app_remove event, which is automatically logged when an Android app is uninstalled. This data is sent to Apptrove MMP via Firebase Cloud Functions, providing insights into user retention and campaign performance.


Setup

Follow these steps to configure uninstall tracking:

Step 1: Add Firebase Analytics to Your App

Integrate Firebase Analytics to track the app_remove event.

1.1 Install Firebase Packages

Add the Firebase Analytics NuGet package to your .csproj:

<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<PackageReference Include="Xamarin.Firebase.Analytics" Version="122.0.0.2" />
</ItemGroup>

Run to restore packages:

dotnet restore

1.2 Add google-services.json

  1. Go to the Firebase Console
  2. Select your project → Project settingsGeneral tab
  3. Download google-services.json for your Android app
  4. Place it in Platforms/Android/ folder
  5. Set build action in your .csproj:
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<GoogleServicesJson Include="Platforms\Android\google-services.json" />
</ItemGroup>

1.3 Create Firebase Analytics Helper

Create Platforms/Android/FirebaseAnalyticsHelper.cs:

using Android.Content;
using Firebase.Analytics;

namespace YourApp.Platforms.Android;

public static class FirebaseAnalyticsHelper
{
private static FirebaseAnalytics? _analytics;

public static void Initialize(Context context)
{
_analytics = FirebaseAnalytics.GetInstance(context);
}

public static void SetAppTroveIdForUninstallTracking(string appTroveId)
{
if (_analytics == null)
{
var context = global::Android.App.Application.Context;
_analytics = FirebaseAnalytics.GetInstance(context);
}

_analytics.SetUserProperty("ct_objectId", appTroveId);
Console.WriteLine($"[Firebase Analytics] Set ct_objectId: {appTroveId}");
}
}

1.4 Set a Common Identifier

Set the Apptrove ID as a Firebase user property to link analytics data. Add this to your App.xaml.cs:

using AppTroveSDK.Maui;

public partial class App : Application
{
protected override async void OnStart()
{
base.OnStart();

// Initialize SDK first
var config = new AppTroveSDKConfig(
"YOUR_SDK_KEY",
AppTroveEnvironment.Production
);

AppTroveSDK.Initialize(config);

// Set user property for uninstall tracking (Android only)
#if ANDROID
await SetAppTroveUserPropertyAsync();
#endif
}

private async Task SetAppTroveUserPropertyAsync()
{
#if ANDROID
try
{
var appTroveId = await AppTroveSDK.GetAppTroveId();

if (!string.IsNullOrEmpty(appTroveId))
{
Platforms.Android.FirebaseAnalyticsHelper.SetAppTroveIdForUninstallTracking(appTroveId);
Console.WriteLine($"[Uninstall Tracking] Set ct_objectId: {appTroveId}");
}
else
{
Console.WriteLine("[Uninstall Tracking] AppTrove ID not available");
}
}
catch (Exception ex)
{
Console.WriteLine($"[Uninstall Tracking] Error setting user property: {ex.Message}");
}
#endif
}
}

This sets the ct_objectId property to the Apptrove ID, creating a common identifier for uninstall tracking.

note

Ensure the Apptrove SDK is initialized before calling GetAppTroveId().

Step 2: Set the app_remove Event as a Conversion Event

Configure the app_remove event as a conversion event in Firebase:

  1. Log in to the Firebase Console.
  2. Select your project and navigate to Analytics > Events.
  3. Find the app_remove event and enable the Mark as conversion toggle.

Step 3: Use Firebase Cloud Functions

Prerequisites

  • Node.js 20.x or 22.x (use nvm for easy version management)
  • Firebase CLI (npm install -g firebase-tools)
  • Firebase project on Blaze plan (required for analytics triggers)
  • Google account with access to Firebase Console
  • App with Firebase Analytics SDK integrated
  • Apptrove account (for uninstall event tracking)

Set Up Node.js and Firebase CLI

# Install Node Version Manager (nvm) if not already installed
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Install and use Node.js 22 (recommended)
nvm install 22
nvm use 22

# Install Firebase CLI globally
npm install -g firebase-tools

# Login to Firebase
firebase login

Create or Select Your Firebase Project

If you already have a Firebase project for your app:

If you need to create a new Firebase project:

  • In the Firebase Console, click Add project and follow the steps
  • Link Google Analytics when prompted
  • Register your Android app and download google-services.json for your app

Initialize Firebase Functions in Your Project Directory

# Create a new directory for your project (if needed)
mkdir YourProjectName
cd YourProjectName

# Initialize Firebase in this directory
firebase init functions
  • Choose:
    • Use an existing project (if you already have one) or create a new one
    • Language: JavaScript
    • ESLint: Yes (recommended)
    • Install dependencies: Yes

Prepare Your Functions Directory

  • Your folder structure should look like this:
    YourProjectName/
    functions/
    index.js
    package.json
    .eslintrc.js
    ...
  • If you already have a functions directory, use it.

Add the Uninstall Tracking Function Code

Replace the contents of functions/index.js with:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const axios = require("axios");

// Set your SDK key here (or use environment variables for security)
const SDK_KEY = "YOUR_SDK_KEY_HERE";

admin.initializeApp();

// Defensive: Only export analytics trigger if available
if (!functions.analytics) {
// This will prevent deployment errors in unsupported environments
console.warn("Analytics triggers are not available in this environment.");
exports.sendAndroidUninstallToTrackierApptrove = () => {};
} else {
exports.sendAndroidUninstallToTrackierApptrove = functions.analytics
.event("app_remove")
.onLog(async (event) => {
// Defensive extraction of user properties
const userProps =
event.user && event.user.userProperties ?
event.user.userProperties :
{};
const installId =
userProps.ct_objectId && userProps.ct_objectId.value ?
userProps.ct_objectId.value :
"";
const mode =
userProps.ct_mode && userProps.ct_mode.value ?
userProps.ct_mode.value :
"production";
const cuid =
userProps.ct_uid && userProps.ct_uid.value ?
userProps.ct_uid.value :
"";
const cmail =
userProps.ct_mail && userProps.ct_mail.value ?
userProps.ct_mail.value :
"";

if (!installId) {
functions.logger.warn(
"No ct_objectId found in event",
{userProps},
);
return null;
}

const url = "https://events.trackier.io/v1/uninstall";
const data = {
installId,
sdkKey: SDK_KEY,
mode,
cuid,
cmail,
meta: event,
};

try {
const response = await axios.post(
url,
data,
{
headers: {"Content-Type": "application/json"},
timeout: 10000,
},
);
functions.logger.log(
"Tracked uninstall",
{
installId,
status: response.status,
data: response.data,
},
);
} catch (error) {
functions.logger.error(
"Uninstall tracking failed",
{
installId,
status: error.response ? error.response.status : "N/A",
data: error.response ? error.response.data : error.message,
},
);
}
return null;
});
}

Set Up Dependencies In package.json

{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint:fix": "eslint . --fix",
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "20"
},
"main": "index.js",
"dependencies": {
"axios": "^1.10.0",
"firebase-admin": "^11.0.0",
"firebase-functions": "^3.23.0"
},
"devDependencies": {
"eslint": "^8.15.0",
"eslint-config-google": "^0.14.0"
},
"private": true
}

ESLint Configuration

Create a .eslintrc.js file in your functions directory:

// .eslintrc.js
module.exports = {
parserOptions: {
ecmaVersion: 2020, // or at least 2015
sourceType: 'module', // if you're using ES modules (import/export)
},
env: {
es6: true,
node: true, // if you're in a Node.js environment
},
};

Deploy Your Function And Fix lint Error

# In the functions directory
cd functions

# Install dependencies
npm install

# (Optional) Run linter and auto-fix issues
npm run lint:fix

firebase deploy --only functions
  • If you see errors about CPU/Gen 2 or function already existing as 2nd Gen:
    firebase functions:delete sendAndroidUninstallToTrackierApptrove --force

    // After delete your function redeploy the function

    firebase deploy --only functions
  • Ignore warnings about outdated firebase-functions if you need analytics triggers.

Verify and Debug

A. See Data in Firebase Console

  • Go to Firebase Console
  • Select your project
  • Navigate to Analytics > Dashboard and look for the app_remove event

B. Use Analytics DebugView

  • In the Firebase Console, go to Analytics > DebugView
  • Enable DebugView on your device:
    adb shell setprop debug.firebase.analytics.app <your.app.package>
    # Example:
    adb shell setprop debug.firebase.analytics.app com.example.myapp
    # To turn off:
    adb shell setprop debug.firebase.analytics.app .none.
  • Open your app and trigger uninstall or other events
  • Watch for real-time events in DebugView

C. Check Cloud Function Logs

  • Look for logs like Tracked uninstall or Uninstall tracking failed

D. Check Apptrove Uninstall Log

  • Log in to your Apptrove dashboard
  • Navigate to uninstall/event logs
  • Filter by installId or other user properties
  • Confirm the uninstall event was received


Troubleshooting & Tips

  • Analytics triggers not working?
    • Make sure you are on Blaze plan and Analytics is linked
    • Only deploy to production (not emulator)
    • Use firebase-functions@3.x and firebase-admin@11.x
  • CPU/Gen 2 errors?
    • Remove any "cpu" option from firebase.json or CLI flags
    • Delete the function if it was previously deployed as Gen 2, then redeploy
  • Dependency conflicts?
    • Downgrade firebase-admin to ^11.0.0 if needed
  • Linting errors?
    • Use npm run lint:fix and break up long lines/fix indentation
  • Function not triggering?
    • Ensure your app is setting the user property:
      var appTroveId = await AppTroveSDK.GetAppTroveId();
      FirebaseAnalyticsHelper.SetAppTroveIdForUninstallTracking(appTroveId);
    • Use Analytics DebugView to verify the event is sent
  • Still stuck?

Best Practices

  • Test Firebase Integration: Verify Firebase Analytics is correctly set up by logging custom events and checking the Firebase Console.
  • Secure Firebase Configuration: Store google-services.json securely and avoid committing it to public repositories.
  • Call Setup Early: Execute the uninstall tracking setup code as early as possible in the app lifecycle to ensure the Apptrove ID is set.
  • Monitor Uninstall Data: Regularly check the Apptrove Panel to analyze uninstall trends and optimize retention strategies.
  • Comply with Privacy Regulations: Ensure uninstall tracking complies with GDPR, CCPA, and other privacy laws, obtaining user consent where required.
  • Use Development Environment: Test uninstall tracking in development mode to avoid affecting production data.

For further assistance, refer to the Apptrove Documentation Portal or contact support at support@trackier.com.