Back to all articles

Mobile App Analytics & Tracking: Complete Implementation Guide 2025

Apps with analytics-driven development see 3x better retention and 2x higher revenue. Yet 60% of apps track less than 5 events. Data-driven apps outperform competitors by making decisions based on user behavior, not assumptions. This guide shows you how to implement comprehensive analytics and use data to grow your app.

Why Analytics Matter

Impact of Analytics

  • Better decisions: Data reveals what users actually do (not what you think)
  • Higher retention: Identify and fix friction points
  • More revenue: Optimize conversion funnels
  • Faster iteration: A/B test features with confidence
  • User understanding: Know your audience deeply
  • ROI proof: Demonstrate business value

What to Track

Essential metrics:

User metrics:
- Daily/Monthly Active Users (DAU/MAU)
- New users
- Returning users
- Session length
- Session frequency
- User lifetime value (LTV)

Engagement metrics:
- Feature usage
- Time in app
- Screens per session
- Actions per session
- Content interactions

Retention metrics:
- Day 1, 7, 30 retention
- Cohort retention curves
- Churn rate
- Resurrection rate

Revenue metrics:
- Conversion rate
- Average revenue per user (ARPU)
- Lifetime value (LTV)
- Customer acquisition cost (CAC)
- LTV:CAC ratio

Technical metrics:
- Crash rate
- Error rate
- API latency
- Load times
- Network errors

Don't track everything!
Focus on metrics that drive decisions.

Analytics Platforms

Platform Comparison

Firebase Analytics:
✓ Free unlimited events
✓ Google ecosystem integration
✓ Real-time dashboards
✓ Automatic events
✓ Audience segmentation
✗ Limited raw data export
✗ 7-day data freshness
Best for: Most apps, tight Google integration

Mixpanel:
✓ Advanced funnel analysis
✓ Cohort analysis
✓ A/B testing built-in
✓ User profiles
✓ Flexible queries
✗ Expensive at scale
✗ Can be complex
Best for: Product analytics, SaaS apps

Amplitude:
✓ Powerful behavioral analytics
✓ Cohort analysis
✓ User journey mapping
✓ Predictive analytics
✓ Great for growth teams
✗ Expensive
✗ Learning curve
Best for: Growth-focused teams, data-driven orgs

App Annie (data.ai):
✓ Market intelligence
✓ Competitor analysis
✓ Download estimates
✓ Revenue estimates
✗ External data only
✗ Expensive
Best for: Market research, competitive analysis

PostHog:
✓ Open source
✓ Self-hostable
✓ Session recording
✓ Feature flags
✓ Complete control
✗ Self-hosting complexity
✗ Smaller community
Best for: Privacy-focused, self-hosted needs

Recommendation:
Start with Firebase (free, easy)
Add Mixpanel/Amplitude when you need deeper analysis

Implementation

Firebase Analytics

iOS Setup

// 1. Install via CocoaPods
pod 'Firebase/Analytics'

// 2. Initialize in AppDelegate
import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        FirebaseApp.configure()
        return true
    }
}

// 3. Track events
import FirebaseAnalytics

// Simple event
Analytics.logEvent("button_tapped", parameters: [
    "button_name": "sign_up",
    "screen": "home"
])

// Standard event (recommended)
Analytics.logEvent(AnalyticsEventSelectContent, parameters: [
    AnalyticsParameterItemID: "post_123",
    AnalyticsParameterItemName: "Getting Started Guide",
    AnalyticsParameterContentType: "article"
])

// Custom user properties
Analytics.setUserProperty("premium", forName: "subscription_status")
Analytics.setUserID("user_12345")

// Screen tracking
Analytics.logEvent(AnalyticsEventScreenView, parameters: [
    AnalyticsParameterScreenName: "home",
    AnalyticsParameterScreenClass: "HomeViewController"
])

// E-commerce events
Analytics.logEvent(AnalyticsEventPurchase, parameters: [
    AnalyticsParameterTransactionID: "T12345",
    AnalyticsParameterValue: 9.99,
    AnalyticsParameterCurrency: "USD",
    AnalyticsParameterItems: [
        [
            AnalyticsParameterItemID: "premium_monthly",
            AnalyticsParameterItemName: "Premium Subscription",
            AnalyticsParameterPrice: 9.99
        ]
    ]
])

Android Setup

// 1. Add dependencies (build.gradle)
dependencies {
    implementation platform('com.google.firebase:firebase-bom:32.7.0')
    implementation 'com.google.firebase:firebase-analytics-ktx'
}

// 2. Initialize (automatic with google-services.json)

// 3. Track events
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase

class MainActivity : AppCompatActivity() {
    private lateinit var analytics: FirebaseAnalytics
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        analytics = Firebase.analytics
    }
    
    fun trackButtonClick(buttonName: String) {
        analytics.logEvent("button_tapped") {
            param("button_name", buttonName)
            param("screen", "home")
        }
    }
    
    // Standard event
    fun trackContentView(itemId: String, itemName: String) {
        analytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT) {
            param(FirebaseAnalytics.Param.ITEM_ID, itemId)
            param(FirebaseAnalytics.Param.ITEM_NAME, itemName)
            param(FirebaseAnalytics.Param.CONTENT_TYPE, "article")
        }
    }
    
    // User properties
    fun setUserProperties(userId: String, isPremium: Boolean) {
        analytics.setUserId(userId)
        analytics.setUserProperty(
            "subscription_status",
            if (isPremium) "premium" else "free"
        )
    }
    
    // Screen tracking
    fun trackScreen(screenName: String) {
        analytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW) {
            param(FirebaseAnalytics.Param.SCREEN_NAME, screenName)
            param(FirebaseAnalytics.Param.SCREEN_CLASS, [email protected])
        }
    }
    
    // Purchase event
    fun trackPurchase(transactionId: String, value: Double, itemId: String) {
        analytics.logEvent(FirebaseAnalytics.Event.PURCHASE) {
            param(FirebaseAnalytics.Param.TRANSACTION_ID, transactionId)
            param(FirebaseAnalytics.Param.VALUE, value)
            param(FirebaseAnalytics.Param.CURRENCY, "USD")
            param(FirebaseAnalytics.Param.ITEMS, arrayOf(
                Bundle().apply {
                    putString(FirebaseAnalytics.Param.ITEM_ID, itemId)
                    putString(FirebaseAnalytics.Param.ITEM_NAME, "Premium Subscription")
                    putDouble(FirebaseAnalytics.Param.PRICE, value)
                }
            ))
        }
    }
}

Event Naming Convention

Best practices:

Format: object_action
✓ button_tapped
✓ post_viewed
✓ user_registered
✓ video_started
✓ purchase_completed

✗ buttonTap (inconsistent casing)
✗ UserRegistered (wrong case)
✗ clicked_button (action first)
✗ view post (spaces)

Parameter naming:
✓ screen_name
✓ button_name
✓ post_id
✓ user_id

Standard events (use when applicable):
- login
- sign_up
- purchase
- add_to_cart
- begin_checkout
- search
- share
- view_item
- select_content

Custom events (your specific actions):
- tutorial_completed
- profile_photo_uploaded
- filter_applied
- workout_finished
- recipe_saved

Limits:
iOS: 500 distinct event names
Android: 500 distinct event names
Parameter name: 40 chars max
Parameter value: 100 chars max

Organization:
Group related events:
- onboarding_step_1_viewed
- onboarding_step_2_viewed
- onboarding_step_3_viewed
- onboarding_completed

Makes querying easier!

Automatic Tracking

Firebase auto-tracks:

iOS automatic events:
- app_open (first open & reopens)
- first_open
- session_start
- user_engagement (every 10s while active)
- screen_view (when enabled)
- app_update
- app_remove

Android automatic events:
- app_open
- first_open
- session_start
- user_engagement
- screen_view (when enabled)
- app_update
- app_clear_data
- notification_receive
- notification_open

Enhanced tracking (recommended):

iOS:
// Enable screen tracking
// Info.plist
FirebaseAutomaticScreenReportingEnabled


// Or manual per screen
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    Analytics.setScreenName(
        "home",
        screenClass: String(describing: type(of: self))
    )
}

Android:
// Enable automatic screen tracking
// AndroidManifest.xml


// Or manual per screen
override fun onResume() {
    super.onResume()
    analytics.setCurrentScreen(
        this,
        "home",
        MainActivity::class.java.simpleName
    )
}

Event Tracking Strategy

What Events to Track

Onboarding flow:
□ onboarding_started
□ onboarding_step_1_viewed
□ onboarding_step_2_viewed
□ onboarding_completed
□ onboarding_skipped
□ tutorial_started
□ tutorial_completed

Authentication:
□ sign_up_started
□ sign_up_completed
□ sign_up_method (email/Google/Apple)
□ login_started
□ login_completed
□ login_method
□ password_reset_requested
□ logout

Core features:
□ feature_x_accessed
□ feature_x_completed
□ feature_x_error
□ search_performed
□ filter_applied
□ sort_changed
□ content_viewed
□ content_created
□ content_edited
□ content_deleted
□ content_shared

E-commerce:
□ product_viewed
□ product_added_to_cart
□ cart_viewed
□ checkout_started
□ payment_info_entered
□ purchase_completed
□ purchase_failed
□ subscription_started
□ subscription_renewed
□ subscription_cancelled

Social:
□ post_created
□ post_liked
□ post_commented
□ post_shared
□ user_followed
□ user_unfollowed
□ message_sent
□ notification_received
□ notification_opened

Settings:
□ settings_opened
□ profile_edited
□ notification_settings_changed
□ privacy_settings_changed
□ account_deleted

Errors:
□ api_error
□ network_error
□ payment_error
□ validation_error

Implementation example:

class AnalyticsManager {
    static func trackOnboarding(step: Int, completed: Bool) {
        if completed {
            Analytics.logEvent("onboarding_completed", parameters: [
                "total_steps": step,
                "time_taken": elapsedTime
            ])
        } else {
            Analytics.logEvent("onboarding_step_viewed", parameters: [
                "step_number": step,
                "step_name": stepName
            ])
        }
    }
    
    static func trackPurchase(
        productId: String,
        price: Double,
        currency: String
    ) {
        Analytics.logEvent(AnalyticsEventPurchase, parameters: [
            AnalyticsParameterItemID: productId,
            AnalyticsParameterValue: price,
            AnalyticsParameterCurrency: currency,
            "payment_method": paymentMethod,
            "offer_id": offerId
        ])
    }
}

User Properties

Track user attributes:

Demographics:
- age_group (18-24, 25-34, etc.)
- gender
- country
- language

App behavior:
- subscription_status (free, trial, premium)
- account_age_days
- total_sessions
- total_purchases
- last_active_date

Preferences:
- theme (light, dark)
- notification_enabled
- content_category_preference

Segmentation:
- user_tier (power_user, casual, inactive)
- acquisition_channel (organic, paid, referral)
- cohort (2024_01, 2024_02)

Implementation:

// iOS
Analytics.setUserProperty("premium", forName: "subscription_status")
Analytics.setUserProperty("dark", forName: "theme_preference")
Analytics.setUserProperty("2024_01", forName: "cohort")

// Android
analytics.setUserProperty("subscription_status", "premium")
analytics.setUserProperty("theme_preference", "dark")
analytics.setUserProperty("cohort", "2024_01")

Limits:
- 25 user properties per app
- Property name: 24 chars max
- Property value: 36 chars max

Use sparingly for high-level segmentation!

Funnel Analysis

Creating Funnels

Common funnels:

Onboarding funnel:
1. app_open (100%)
2. onboarding_started (80%)
3. onboarding_step_1_completed (70%)
4. onboarding_step_2_completed (60%)
5. onboarding_completed (50%)

Identify drop-off: Step 2 → 3 loses 10%
Action: Simplify step 1 or add motivation

Purchase funnel:
1. product_viewed (100%)
2. add_to_cart (30%)
3. checkout_started (20%)
4. payment_info_entered (15%)
5. purchase_completed (12%)

Identify drop-off: Payment info → Purchase loses 3%
Action: Check payment errors, add trust signals

Subscription funnel:
1. paywall_viewed (100%)
2. pricing_tier_selected (40%)
3. trial_started (25%)
4. trial_converted (10%)

Identify drop-off: Trial → Conversion loses 15%
Action: Improve trial experience, send reminders

Feature adoption funnel:
1. feature_discovered (100%)
2. feature_first_use (60%)
3. feature_second_use (40%)
4. feature_power_user (10%)

Identify drop-off: First → Second use loses 20%
Action: Improve first experience, add tutorial

Funnel optimization process:
1. Track all funnel steps
2. Identify biggest drop-off
3. Hypothesize why users drop
4. A/B test improvements
5. Measure impact
6. Iterate

Cohort Analysis

Cohort = group of users with shared characteristic

Time-based cohorts:
- All users who signed up in January 2024
- Track retention over time
- Compare cohorts

Feature-based cohorts:
- Users who used Feature X
- Users who completed onboarding
- Premium subscribers

Retention cohort example:

Week 0: 1000 users signed up
Week 1: 600 returned (60% retention)
Week 2: 450 returned (45% retention)
Week 4: 350 returned (35% retention)
Week 8: 280 returned (28% retention)

Compare cohorts:
Jan 2024: 28% Week 8 retention
Feb 2024: 35% Week 8 retention (improved!)
Mar 2024: 40% Week 8 retention (even better!)

What changed? New onboarding in Feb!

Cohort queries in Firebase:
1. Select audience (e.g., signed up in Jan)
2. Track retention over time
3. Compare to other cohorts

Use cohorts to:
- Measure feature impact
- Track retention trends
- Validate A/B tests
- Understand user lifecycle

A/B Testing

Firebase A/B Testing

// Setup
// 1. Create experiment in Firebase Console
// 2. Define variants (Control, A, B)
// 3. Set targeting & goals

// iOS implementation
import FirebaseRemoteConfig

let remoteConfig = RemoteConfig.remoteConfig()

// Fetch config
remoteConfig.fetch { status, error in
    guard status == .success else { return }
    remoteConfig.activate()
}

// Get variant value
let buttonColor = remoteConfig["button_color"].stringValue ?? "blue"

if buttonColor == "green" {
    button.backgroundColor = .green
} else {
    button.backgroundColor = .blue
}

// Track goal
Analytics.logEvent("button_tapped", parameters: nil)

// Android implementation
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.ktx.Firebase

val remoteConfig = Firebase.remoteConfig

// Fetch config
remoteConfig.fetchAndActivate()
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val buttonColor = remoteConfig.getString("button_color")
            updateButtonColor(buttonColor)
        }
    }

// Get variant
fun updateButtonColor(color: String) {
    when (color) {
        "green" -> button.setBackgroundColor(Color.GREEN)
        else -> button.setBackgroundColor(Color.BLUE)
    }
}

What to A/B test:

UI/UX:
- Button colors
- Button text ("Sign Up" vs "Get Started")
- Layout variations
- Onboarding flows
- Navigation patterns

Pricing:
- Price points ($9.99 vs $7.99)
- Trial lengths (7 vs 14 days)
- Pricing page layout
- Feature emphasis

Features:
- Feature visibility
- Default settings
- Content recommendations
- Notification timing

Messaging:
- Copy variations
- CTA text
- Email subject lines
- Push notification text

A/B test best practices:
✓ Test one thing at a time
✓ Run until statistical significance
✓ Need 1000+ users per variant
✓ Run for at least 2 weeks
✓ Track multiple metrics
✓ Document learnings

Example test:
Hypothesis: Green button increases sign-ups
Control: Blue "Sign Up" button
Variant A: Green "Sign Up" button
Goal: sign_up_completed
Duration: 2 weeks
Sample: 5000 users (2500 each)

Results:
Control: 5% conversion (125 sign-ups)
Variant A: 6.5% conversion (162 sign-ups)
Result: +30% lift, statistically significant
Decision: Ship green button

Custom Dashboards

Key Dashboards

1. Executive Dashboard (Daily):
   - DAU/MAU
   - New users
   - Revenue
   - Retention rate
   - Crash-free rate
   - Top 3 issues

2. Product Dashboard (Daily):
   - Feature usage
   - User flows
   - Funnel conversions
   - A/B test results
   - User feedback

3. Growth Dashboard (Weekly):
   - Acquisition channels
   - Conversion rates
   - Viral coefficient
   - CAC by channel
   - LTV trends

4. Technical Dashboard (Real-time):
   - Crash rate
   - Error rate
   - API latency
   - Success rate by endpoint
   - Active users

5. Engagement Dashboard (Weekly):
   - Session length
   - Sessions per user
   - Feature adoption
   - Content engagement
   - Notification CTR

Dashboard tools:
- Firebase Console (built-in)
- Google Data Studio (free)
- Tableau
- Mixpanel
- Amplitude
- Custom (React + Chart.js)

Privacy & Compliance

Privacy Best Practices

Requirements:

1. User Consent:
   - iOS 14.5+: ATT prompt required
   - GDPR: Explicit consent needed
   - CCPA: Opt-out required
   
   Implementation:
   // iOS - App Tracking Transparency
   import AppTrackingTransparency
   
   func requestTracking() {
       ATTrackingManager.requestTrackingAuthorization { status in
           switch status {
           case .authorized:
               // Enable tracking
               enableAnalytics()
           case .denied, .restricted, .notDetermined:
               // Disable tracking
               disableAnalytics()
           @unknown default:
               break
           }
       }
   }

2. Data Minimization:
   - Only collect necessary data
   - Don't track PII without consent
   - Anonymize user data
   - Use user IDs, not emails

3. Transparency:
   - Privacy policy must disclose tracking
   - Explain what data is collected
   - Explain how data is used
   - Provide opt-out mechanism

4. Data Deletion:
   - Allow users to delete their data
   - Implement data retention policies
   - Delete inactive user data
   
   // iOS
   Analytics.resetAnalyticsData()
   
   // Android
   analytics.resetAnalyticsData()

5. Secure Storage:
   - Encrypt analytics data
   - Use secure transmission
   - Limit data access
   - Regular security audits

Compliance checklist:
□ Privacy policy updated
□ User consent implemented
□ ATT prompt (iOS)
□ Data deletion option
□ Anonymous tracking option
□ PII not collected
□ Data retention policy
□ Security measures in place

Performance Monitoring

Firebase Performance

// iOS
import FirebasePerformance

// Automatic traces (included):
- App start time
- Screen rendering
- Network requests

// Custom traces
let trace = Performance.startTrace(name: "image_processing")
// Do work
processImage()
trace?.stop()

// Network monitoring (automatic for URLSession)
let url = URL(string: "https://api.example.com/users")!
let task = URLSession.shared.dataTask(with: url)
task.resume() // Automatically tracked

// Android
import com.google.firebase.perf.FirebasePerformance
import com.google.firebase.perf.metrics.Trace

// Custom trace
val trace = FirebasePerformance.getInstance().newTrace("image_processing")
trace.start()
processImage()
trace.stop()

// Network monitoring (automatic for OkHttp)
// Add interceptor
val client = OkHttpClient.Builder()
    .addInterceptor(FirebasePerfOkHttpInterceptor())
    .build()

Key metrics:
- App start time (target < 2s)
- Screen load time (target < 1s)
- API latency (target < 500ms)
- Success rate (target > 99%)
- Crash-free rate (target > 99.5%)

Set up alerts:
- Crash rate > 1%
- API success rate < 95%
- App start time > 3s
- Network error rate > 5%

Conclusion

Analytics transform assumptions into insights and guesses into data-driven decisions. By tracking the right events, analyzing user behavior, optimizing funnels, and A/B testing improvements, you can systematically improve every aspect of your app. Remember: measure everything that matters, but focus on metrics that drive action. The apps that win are the ones that learn fastest from their data.

Analytics show you what users do, but support shows you what users need. Our support URL generator creates professional support pages that complement your analytics strategy by providing users with help when they need it most.

Need a Support URL for Your App?

Generate a compliant, professional support page in under a minute. Our easy-to-use generator creates everything you need for App Store and Google Play submissions.