Skip to content

feat(analytics): migrate from Firebase Analytics to Amplitude#232

Merged
BillChirico merged 2 commits into
mainfrom
develop
Dec 29, 2025
Merged

feat(analytics): migrate from Firebase Analytics to Amplitude#232
BillChirico merged 2 commits into
mainfrom
develop

Conversation

@BillChirico

@BillChirico BillChirico commented Dec 29, 2025

Copy link
Copy Markdown
Member

Summary

  • Migrate analytics from Firebase Analytics to Amplitude for better cross-platform support
  • Remove Firebase dependencies and configuration
  • Add Amplitude SDK integration for both native (iOS/Android) and web platforms
  • Update analytics utilities and event tracking

Changes

  • Replace Firebase Analytics with Amplitude SDK
  • Remove withFirebaseConfig.js and withModularHeaders.js plugins
  • Update app.config.ts to remove Firebase configuration
  • Refactor analytics platform implementations for native and web
  • Update analytics types and utilities
  • Add comprehensive analytics tests

Test Plan

  • Verify analytics events are tracked correctly on iOS
  • Verify analytics events are tracked correctly on Android
  • Verify analytics events are tracked correctly on web
  • Confirm Firebase dependencies are fully removed
  • Run full test suite

Important

Migrate analytics from Firebase to Amplitude, updating dependencies, types, and platform-specific implementations, and removing Firebase-related code.

  • Behavior:
    • Migrate from Firebase Analytics to Amplitude for cross-platform support.
    • Remove Firebase dependencies and configuration.
    • Add Amplitude SDK integration for iOS, Android, and web.
    • Update analytics utilities and event tracking.
  • Types:
    • Update types/analytics.ts to define Amplitude event types and user properties.
    • Add StepsCompletedBucket type.
  • Platform Implementations:
    • Implement Amplitude analytics in platform.native.ts and platform.web.ts.
    • Use amplitude.init() for initialization and amplitude.track() for event tracking.
  • Utilities:
    • Update analytics-utils.ts to handle Amplitude-specific logic.
    • Add calculateStepsCompletedBucket() function.
  • Configuration:
    • Remove Firebase configuration from app.config.ts.
    • Update .env.example to include Amplitude API key.
  • Testing:
    • Update tests to mock Amplitude SDK in jest.setup.js.
    • Remove Firebase-related tests and add tests for Amplitude integration.
  • Misc:
    • Update package.json to include Amplitude dependencies.
    • Remove Firebase-related files and plugins.

This description was created by Ellipsis for 599e89c. You can customize this summary. It will automatically update as commits are pushed.

* docs(analytics): add Amplitude migration implementation plan

* chore(deps): replace Firebase Analytics with Amplitude SDK

- Remove @react-native-firebase/analytics
- Remove @react-native-firebase/app
- Remove firebase
- Add @amplitude/analytics-react-native

* feat(analytics): update types for Amplitude with Title Case events

- Change event values to Title Case (Amplitude convention)
- Add 17 new events for comprehensive tracking (37 total)
- Add new user properties (onboarding_completed, task_streak_current, etc.)
- Simplify AnalyticsConfig to single apiKey
- Add StepsCompletedBucket type
- Support string arrays in EventParamValue

* refactor(analytics): simplify utils for Amplitude

- Remove Platform import (no longer needed)
- Update shouldInitializeAnalytics to check AMPLITUDE_API_KEY
- Add calculateStepsCompletedBucket helper
- Update tests for new behavior

* feat(analytics): implement Amplitude SDK for native platforms

- Replace Firebase with Amplitude SDK
- Add amplitude mock to jest.setup.js
- Update native platform implementation
- Use Identify class for user properties

* fix(analytics): add error handling and use constant for screen view

- Add try-catch to setUserPropertiesPlatform() for robustness
- Use AnalyticsEvents.SCREEN_VIEWED instead of hardcoded string
- Add JSDoc param documentation to trackScreenViewPlatform()

* feat(analytics): implement Amplitude SDK for web platform

- Replace Firebase with Amplitude browser SDK in platform.web.ts
- Add @amplitude/analytics-browser mock to jest.setup.js
- Update web platform tests for Amplitude
- Fix index.ts to use Amplitude configuration
- Install @amplitude/analytics-browser package

* refactor(analytics): update main module for Amplitude

- Export calculateStepsCompletedBucket utility
- Update tests for new export

* chore(config): remove Firebase config, add Amplitude

- Remove googleServicesFile from iOS/Android config
- Remove Firebase plugins from app.config.ts
- Replace Firebase env vars with AMPLITUDE_API_KEY in .env.example
- Clean up Firebase documentation from config

* chore(cleanup): remove Firebase plugin files

- Delete withFirebaseConfig.js plugin
- Delete withModularHeaders.js plugin
- Delete firebase.json
- Delete associated test files

* test(config): remove Firebase-related tests from app.config

Firebase configuration was removed in the Amplitude migration.
Updated tests to reflect the new configuration structure.

* docs(changelog): add Amplitude Analytics migration entry

Added:
- Amplitude Analytics integration with native/web platform support
- 35+ Title Case analytics events for user engagement tracking
- 9 user properties for cohort analysis

Changed:
- Firebase Analytics replaced with Amplitude SDK
- Analytics module architecture updated with platform-specific implementations

Removed:
- Firebase Analytics dependencies and configuration files

* test(tasks): add accessibility tests for TaskCard status icons and due dates

* docs(changelog): add TaskCard accessibility tests and bug fix entries

* test(analytics): improve coverage for platform modules

- Add tests for uninitialized state (setUserId, setUserProperties, reset)
- Add test for undefined property values
- Add test for default screen class in trackScreenView

* docs(changelog): add analytics platform test coverage entry

* fix(analytics): rethrow initialization errors to enable retry

Platform implementations were catching errors and not rethrowing them,
causing initializeAnalytics() to set state='completed' even on failure.
This prevented retry and caused silent analytics failures.

- Rethrow errors from initializePlatformAnalytics in both platforms
- Add tests for error propagation behavior

* fix(analytics): remove unreachable code and trim API key

- Remove dead code: API key warning was unreachable after
  shouldInitializeAnalytics check
- Trim API key in config to match validation behavior
- Update JSDoc example to use AnalyticsEvents constant
- Remove obsolete test for removed warning

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Bill Chirico <undefined@users.noreply.github.com>

* refactor(analytics): remove unreachable API key warning

shouldInitializeAnalytics() already checks for API key existence,
so the warning at lines 128-131 was unreachable dead code.

- Remove redundant !config.apiKey check
- Use non-null assertion since key is guaranteed by shouldInitializeAnalytics()
- Remove test for unreachable code path

* fix(analytics): handle negative values in calculateStepsCompletedBucket

Negative step counts now correctly return '0' bucket instead of falling
through to '10-12'. Added test cases for negative values.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(changelog): add entry for negative bucket fix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(analytics): replace fragile exact event count with sanity check

Per PR review: hardcoded event count (37) is fragile and breaks when events
are legitimately added/removed. Changed to verify events are defined (>0).

* fix(analytics): add error handling to trackEventPlatform

Per PR review: wrap amplitude.track() in try-catch to prevent unexpected
exceptions from propagating, matching the pattern in setUserPropertiesPlatform.

* fix(analytics): add consistent error handling to setUserIdPlatform and resetAnalyticsPlatform

Per PR review: apply consistent error handling pattern across all Amplitude API
calls to prevent unexpected exceptions from propagating.

* fix(analytics): properly await Amplitude init() using .promise pattern

Per PR review: Amplitude SDK v2+ requires calling .promise on init() return
value to properly await initialization. Without this, tracking may occur
before initialization completes, causing potential data loss.

* fix(analytics): update Amplitude mocks to use .promise pattern

- Update jest.setup.js mocks for @amplitude/analytics-browser and
  @amplitude/analytics-react-native to return { promise: Promise.resolve() }
  from init() to match the actual SDK behavior
- Update test files to use mockReturnValueOnce with promise rejection
  instead of mockRejectedValueOnce for init error tests

* fix(docs): update CHANGELOG comparison links to reference v1.2.1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore(deps): add Sentry Spotlight for local dev debugging

- Install @spotlightjs/spotlight as dev dependency
- Add pnpm spotlight script to run the sidecar server
- Spotlight captures Sentry events locally in development

Usage: Run `pnpm spotlight` in a separate terminal before `pnpm web`

* test(analytics): add missing AnalyticsEvents constant assertions

Cover all 35 event constants in analytics.test.ts to catch any
renamed or removed constants. Added assertions for:
- ONBOARDING_STEP_COMPLETED, ONBOARDING_SOBRIETY_DATE_SET
- SCREEN_VIEWED, TASK_VIEWED, TASK_STARTED
- MILESTONE_SHARED
- SPONSOR_CONNECTED, SPONSOR_INVITE_SENT, SPONSOR_INVITE_ACCEPTED
- MESSAGE_SENT, APP_OPENED, DAILY_CHECK_IN

* docs(changelog): consolidate duplicate Removed sections

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* 📝 Add docstrings to `feat/amplitude-analytics` (#231)

Docstrings generation was requested by @BillChirico.

* #229 (comment)

The following files were modified:

* `lib/analytics-utils.ts`
* `lib/analytics/index.ts`
* `lib/analytics/platform.native.ts`
* `lib/analytics/platform.web.ts`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat(analytics): track SAVINGS_UPDATED event when editing savings

- Add trackEvent call in handleSave with amount, frequency, is_first_setup
- Include isSetupMode in useCallback dependency array

* fix(analytics): add missing JSDoc closing delimiter in sanitizeValue

The JSDoc comment for the sanitizeValue function was missing its closing
`*/` delimiter, causing TypeScript to interpret the function declaration
as part of the comment and fail with TS2304: Cannot find name 'sanitizeValue'.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(analytics): add tracking for engagement, settings, and onboarding events

Add analytics tracking for:
- APP_OPENED, APP_BACKGROUNDED, APP_SESSION_STARTED, DAILY_CHECK_IN (engagement)
- SETTINGS_CHANGED for theme and dashboard preferences
- ONBOARDING_ABANDONED when user signs out during onboarding
- SAVINGS_UPDATED when editing savings settings

Also:
- Add AppState mock to jest.setup.js for testing
- Add AnalyticsEvents to analytics mock in layout tests

* fix: update comment to reference Amplitude instead of Firebase

Co-authored-by: Bill Chirico <undefined@users.noreply.github.com>

* feat(analytics): add comprehensive onboarding analytics tracking

Add tracking for all 7 onboarding events:
- ONBOARDING_STARTED: on mount
- ONBOARDING_SCREEN_VIEWED: on mount with screen_name
- ONBOARDING_FIELD_COMPLETED: for display_name, sobriety_date, savings_tracking
- ONBOARDING_SOBRIETY_DATE_SET: when date is changed (existing)
- ONBOARDING_STEP_COMPLETED: on completion with step_name, step_number
- ONBOARDING_COMPLETED: on completion with duration_seconds, savings_enabled
- ONBOARDING_ABANDONED: on sign out (added previously)

Uses refs to prevent duplicate field completion events.

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Bill Chirico <undefined@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings December 29, 2025 23:04
@vercel

vercel Bot commented Dec 29, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
sobers Ready Ready Preview, Comment Dec 29, 2025 11:09pm

@supabase

supabase Bot commented Dec 29, 2025

Copy link
Copy Markdown

This pull request has been ignored for the connected project vzwdsjphpabtxhmffous because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Dec 29, 2025

Copy link
Copy Markdown
Contributor

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between 581ee21 and 599e89c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • .env.example
  • CHANGELOG.md
  • __tests__/app/layout.test.tsx
  • __tests__/components/tasks/TaskCard.test.tsx
  • __tests__/config/app.config.test.ts
  • __tests__/lib/analytics-utils.test.ts
  • __tests__/lib/analytics.native.test.ts
  • __tests__/lib/analytics.test.ts
  • __tests__/lib/analytics.web.test.ts
  • __tests__/plugins/withFirebaseConfig.test.ts
  • __tests__/plugins/withModularHeaders.test.ts
  • __tests__/types/analytics.test.ts
  • app.config.ts
  • app/_layout.tsx
  • app/onboarding.tsx
  • components/settings/SettingsContent.tsx
  • components/sheets/EditSavingsSheet.tsx
  • components/tasks/TaskCard.tsx
  • docs/plans/2025-12-26-amplitude-analytics-implementation.md
  • firebase.json
  • jest.setup.js
  • lib/analytics-utils.ts
  • lib/analytics/index.ts
  • lib/analytics/platform.native.ts
  • lib/analytics/platform.web.ts
  • package.json
  • plugins/withFirebaseConfig.js
  • plugins/withModularHeaders.js
  • types/analytics.ts
 __________________________________
< The only good bug is a dead bug. >
 ----------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing touches
  • 🔄 Docstrings generation in progress.
🧪 Generate unit tests (beta)

❌ Error creating Unit Test PR.

  • Create PR with unit tests
  • Commit unit tests in branch develop
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude

claude Bot commented Dec 29, 2025

Copy link
Copy Markdown
Contributor

Claude finished @BillChirico's task in 2m 32s —— View job


PR Review: Firebase to Amplitude Analytics Migration

I've completed a comprehensive review of PR #232. This is a well-structured migration from Firebase Analytics to Amplitude with clean architecture and good test coverage.


Summary

Overall Assessment: Approve with minor observations

This PR successfully migrates analytics from Firebase to Amplitude while:

  • Maintaining clean separation of concerns with platform-specific implementations
  • Implementing proper PII sanitization
  • Adding comprehensive analytics event tracking across the app
  • Providing good test coverage
  • Following project conventions

Architecture Review

Strengths:

  1. Clean Platform Abstraction - The Metro bundler resolution pattern (platform.native.ts / platform.web.ts) is excellent for cross-platform code organization

  2. Proper State Management - The initializationPromise pattern in lib/analytics/index.ts:59-60 correctly handles:

    • Concurrent initialization calls
    • Retry after failure
    • Skip when already completed
  3. PII Protection - lib/analytics-utils.ts:17-28 properly strips sensitive fields:

    const PII_FIELDS = [
      'email', 'name', 'display_name', 'phone', 'password',
      'token', 'access_token', 'refresh_token', 'sobriety_date', 'relapse_date',
    ];
  4. Type Safety - Strong typing with AnalyticsEvents constants, EventParams, and UserProperties interfaces


Code Quality

Positive Observations:

  • Error Handling: Analytics failures are logged but don't crash the app (lib/analytics/index.ts:129-133)
  • Debug Mode: Proper debug logging controlled by isDebugMode()
  • SSR Safety: typeof window !== 'undefined' check in app/_layout.tsx:13 prevents SSR issues
  • Bucket Privacy: Using bucketed values (DaysSoberBucket, StepsCompletedBucket) instead of exact numbers protects user privacy

Test Coverage:

  • Platform-specific tests cover initialization, event tracking, and error cases
  • Analytics utility tests cover sanitization and bucket calculations
  • Jest mocks in jest.setup.js:737-765 properly mock both Amplitude SDKs

Security Review

No security concerns identified

  • API key is accessed via environment variable (EXPO_PUBLIC_AMPLITUDE_API_KEY)
  • PII fields are properly stripped before sending events
  • User IDs use Supabase UUIDs (pseudonymous)
  • Sensitive dates are excluded from analytics payloads

Minor Observations (Non-blocking)

  1. Web reset is synchronous - lib/analytics/platform.web.ts:163 calls amplitude.reset() without await, while native uses await amplitude.reset(). This is likely intentional since the browser SDK's reset() is synchronous, but worth noting for consistency.

  2. Test environment check - Both platform files and the main analytics module have __resetForTesting() that throws outside test environment - good defensive practice.

  3. Coverage threshold adjustment - CHANGELOG notes branch coverage lowered from 85% to 83% - reasonable given platform-specific conditionals that are difficult to test.


Files Reviewed

Category Files
Core Analytics lib/analytics/index.ts, platform.native.ts, platform.web.ts
Utilities lib/analytics-utils.ts
Types types/analytics.ts
Integration app/_layout.tsx, app/onboarding.tsx, components/settings/SettingsContent.tsx, components/tasks/TaskCard.tsx
Tests __tests__/lib/analytics*.ts, jest.setup.js
Config app.config.ts, .env.example, package.json

Conclusion

This is a clean, well-executed migration. The code follows best practices, has good test coverage, and properly handles cross-platform concerns. The removal of Firebase configuration and plugins is complete.

Recommendation: Approve

@claude claude Bot added feature New feature frontend Frontend/UI related changes refactor Code refactoring and removed feature New feature labels Dec 29, 2025
@coderabbitai

coderabbitai Bot commented Dec 29, 2025

Copy link
Copy Markdown
Contributor

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #233

@coderabbitai

coderabbitai Bot commented Dec 29, 2025

Copy link
Copy Markdown
Contributor

Note

Unit test generation is an Early Access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

coderabbitai Bot added a commit that referenced this pull request Dec 29, 2025
Docstrings generation was requested by @BillChirico.

* #232 (comment)

The following files were modified:

* `lib/analytics-utils.ts`
* `lib/analytics/index.ts`
* `lib/analytics/platform.web.ts`
@codecov

codecov Bot commented Dec 29, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.45695% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.02%. Comparing base (581ee21) to head (118f90d).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
app/_layout.tsx 70.83% 7 Missing ⚠️
lib/analytics/platform.native.ts 82.05% 7 Missing ⚠️
lib/analytics/platform.web.ts 81.08% 7 Missing ⚠️
app/onboarding.tsx 62.50% 6 Missing ⚠️
components/settings/SettingsContent.tsx 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #232      +/-   ##
==========================================
- Coverage   92.91%   92.02%   -0.89%     
==========================================
  Files          79       79              
  Lines        3936     3836     -100     
  Branches     1316     1288      -28     
==========================================
- Hits         3657     3530     -127     
- Misses        269      296      +27     
  Partials       10       10              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vibe-kanban-cloud

Copy link
Copy Markdown

Review Complete

Your review story is ready!

View Story

Comment !reviewfast on this PR to re-generate the story.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request migrates analytics from Firebase Analytics to Amplitude for improved cross-platform support. The migration involves removing Firebase dependencies and configuration, adding Amplitude SDK integration for native and web platforms, updating analytics utilities and types, and adding comprehensive analytics tests.

Key changes:

  • Replaced Firebase Analytics SDK with Amplitude SDK for both native and web platforms
  • Updated event naming from snake_case to Title Case per Amplitude conventions
  • Simplified analytics configuration from 4 Firebase parameters to a single Amplitude API key
  • Added new analytics events and user properties
  • Removed Firebase-specific plugins and configuration files

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated no comments.

Show a summary per file
File Description
types/analytics.ts Updated type definitions to support Amplitude; changed event names to Title Case; added array support to EventParamValue; added new user properties and event constants
pnpm-lock.yaml Removed Firebase packages; added Amplitude browser and React Native SDKs; added Spotlight for debugging
plugins/withFirebaseConfig.js Deleted Firebase configuration plugin (no longer needed)
plugins/withModularHeaders.js Deleted Firebase modular headers plugin (no longer needed)
package.json Removed Firebase dependencies; added Amplitude packages and Spotlight
lib/analytics/platform.web.ts Rewrote web analytics to use Amplitude instead of Firebase; simplified implementation
lib/analytics/platform.native.ts Rewrote native analytics to use Amplitude; removed Firebase-specific code
lib/analytics/index.ts Updated initialization logic for Amplitude single API key configuration
lib/analytics-utils.ts Removed Platform.OS checks; added calculateStepsCompletedBucket utility
jest.setup.js Added mocks for Amplitude SDKs; added AppState mock
firebase.json Deleted Firebase configuration file
components/tasks/TaskCard.tsx Added accessibility labels to status icons (unrelated to analytics migration)
components/sheets/EditSavingsSheet.tsx Added SAVINGS_UPDATED event tracking
components/settings/SettingsContent.tsx Added SETTINGS_CHANGED event tracking
app/onboarding.tsx Enhanced onboarding analytics with field completion, abandonment, and screen view tracking
app/_layout.tsx Added app lifecycle analytics (opened, backgrounded, session started, daily check-in)
app.config.ts Removed Firebase configuration and plugins
tests/types/analytics.test.ts Rewrote tests for Amplitude event naming and new types
tests/lib/analytics.test.ts Updated tests for Amplitude configuration
tests/config/app.config.test.ts Removed Firebase configuration tests
tests/app/layout.test.tsx Added AnalyticsEvents to mock
.env.example Replaced Firebase environment variables with Amplitude API key

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@BillChirico BillChirico merged commit 892b031 into main Dec 29, 2025
21 of 24 checks passed
@BillChirico BillChirico deleted the develop branch December 29, 2025 23:11
BillChirico added a commit that referenced this pull request Dec 30, 2025
* feat(analytics): migrate from Firebase Analytics to Amplitude (#229)

* docs(analytics): add Amplitude migration implementation plan

* chore(deps): replace Firebase Analytics with Amplitude SDK

- Remove @react-native-firebase/analytics
- Remove @react-native-firebase/app
- Remove firebase
- Add @amplitude/analytics-react-native

* feat(analytics): update types for Amplitude with Title Case events

- Change event values to Title Case (Amplitude convention)
- Add 17 new events for comprehensive tracking (37 total)
- Add new user properties (onboarding_completed, task_streak_current, etc.)
- Simplify AnalyticsConfig to single apiKey
- Add StepsCompletedBucket type
- Support string arrays in EventParamValue

* refactor(analytics): simplify utils for Amplitude

- Remove Platform import (no longer needed)
- Update shouldInitializeAnalytics to check AMPLITUDE_API_KEY
- Add calculateStepsCompletedBucket helper
- Update tests for new behavior

* feat(analytics): implement Amplitude SDK for native platforms

- Replace Firebase with Amplitude SDK
- Add amplitude mock to jest.setup.js
- Update native platform implementation
- Use Identify class for user properties

* fix(analytics): add error handling and use constant for screen view

- Add try-catch to setUserPropertiesPlatform() for robustness
- Use AnalyticsEvents.SCREEN_VIEWED instead of hardcoded string
- Add JSDoc param documentation to trackScreenViewPlatform()

* feat(analytics): implement Amplitude SDK for web platform

- Replace Firebase with Amplitude browser SDK in platform.web.ts
- Add @amplitude/analytics-browser mock to jest.setup.js
- Update web platform tests for Amplitude
- Fix index.ts to use Amplitude configuration
- Install @amplitude/analytics-browser package

* refactor(analytics): update main module for Amplitude

- Export calculateStepsCompletedBucket utility
- Update tests for new export

* chore(config): remove Firebase config, add Amplitude

- Remove googleServicesFile from iOS/Android config
- Remove Firebase plugins from app.config.ts
- Replace Firebase env vars with AMPLITUDE_API_KEY in .env.example
- Clean up Firebase documentation from config

* chore(cleanup): remove Firebase plugin files

- Delete withFirebaseConfig.js plugin
- Delete withModularHeaders.js plugin
- Delete firebase.json
- Delete associated test files

* test(config): remove Firebase-related tests from app.config

Firebase configuration was removed in the Amplitude migration.
Updated tests to reflect the new configuration structure.

* docs(changelog): add Amplitude Analytics migration entry

Added:
- Amplitude Analytics integration with native/web platform support
- 35+ Title Case analytics events for user engagement tracking
- 9 user properties for cohort analysis

Changed:
- Firebase Analytics replaced with Amplitude SDK
- Analytics module architecture updated with platform-specific implementations

Removed:
- Firebase Analytics dependencies and configuration files

* test(tasks): add accessibility tests for TaskCard status icons and due dates

* docs(changelog): add TaskCard accessibility tests and bug fix entries

* test(analytics): improve coverage for platform modules

- Add tests for uninitialized state (setUserId, setUserProperties, reset)
- Add test for undefined property values
- Add test for default screen class in trackScreenView

* docs(changelog): add analytics platform test coverage entry

* fix(analytics): rethrow initialization errors to enable retry

Platform implementations were catching errors and not rethrowing them,
causing initializeAnalytics() to set state='completed' even on failure.
This prevented retry and caused silent analytics failures.

- Rethrow errors from initializePlatformAnalytics in both platforms
- Add tests for error propagation behavior

* fix(analytics): remove unreachable code and trim API key

- Remove dead code: API key warning was unreachable after
  shouldInitializeAnalytics check
- Trim API key in config to match validation behavior
- Update JSDoc example to use AnalyticsEvents constant
- Remove obsolete test for removed warning

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Bill Chirico <undefined@users.noreply.github.com>

* refactor(analytics): remove unreachable API key warning

shouldInitializeAnalytics() already checks for API key existence,
so the warning at lines 128-131 was unreachable dead code.

- Remove redundant !config.apiKey check
- Use non-null assertion since key is guaranteed by shouldInitializeAnalytics()
- Remove test for unreachable code path

* fix(analytics): handle negative values in calculateStepsCompletedBucket

Negative step counts now correctly return '0' bucket instead of falling
through to '10-12'. Added test cases for negative values.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(changelog): add entry for negative bucket fix

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(analytics): replace fragile exact event count with sanity check

Per PR review: hardcoded event count (37) is fragile and breaks when events
are legitimately added/removed. Changed to verify events are defined (>0).

* fix(analytics): add error handling to trackEventPlatform

Per PR review: wrap amplitude.track() in try-catch to prevent unexpected
exceptions from propagating, matching the pattern in setUserPropertiesPlatform.

* fix(analytics): add consistent error handling to setUserIdPlatform and resetAnalyticsPlatform

Per PR review: apply consistent error handling pattern across all Amplitude API
calls to prevent unexpected exceptions from propagating.

* fix(analytics): properly await Amplitude init() using .promise pattern

Per PR review: Amplitude SDK v2+ requires calling .promise on init() return
value to properly await initialization. Without this, tracking may occur
before initialization completes, causing potential data loss.

* fix(analytics): update Amplitude mocks to use .promise pattern

- Update jest.setup.js mocks for @amplitude/analytics-browser and
  @amplitude/analytics-react-native to return { promise: Promise.resolve() }
  from init() to match the actual SDK behavior
- Update test files to use mockReturnValueOnce with promise rejection
  instead of mockRejectedValueOnce for init error tests

* fix(docs): update CHANGELOG comparison links to reference v1.2.1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore(deps): add Sentry Spotlight for local dev debugging

- Install @spotlightjs/spotlight as dev dependency
- Add pnpm spotlight script to run the sidecar server
- Spotlight captures Sentry events locally in development

Usage: Run `pnpm spotlight` in a separate terminal before `pnpm web`

* test(analytics): add missing AnalyticsEvents constant assertions

Cover all 35 event constants in analytics.test.ts to catch any
renamed or removed constants. Added assertions for:
- ONBOARDING_STEP_COMPLETED, ONBOARDING_SOBRIETY_DATE_SET
- SCREEN_VIEWED, TASK_VIEWED, TASK_STARTED
- MILESTONE_SHARED
- SPONSOR_CONNECTED, SPONSOR_INVITE_SENT, SPONSOR_INVITE_ACCEPTED
- MESSAGE_SENT, APP_OPENED, DAILY_CHECK_IN

* docs(changelog): consolidate duplicate Removed sections

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* 📝 Add docstrings to `feat/amplitude-analytics` (#231)

Docstrings generation was requested by @BillChirico.

* #229 (comment)

The following files were modified:

* `lib/analytics-utils.ts`
* `lib/analytics/index.ts`
* `lib/analytics/platform.native.ts`
* `lib/analytics/platform.web.ts`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* feat(analytics): track SAVINGS_UPDATED event when editing savings

- Add trackEvent call in handleSave with amount, frequency, is_first_setup
- Include isSetupMode in useCallback dependency array

* fix(analytics): add missing JSDoc closing delimiter in sanitizeValue

The JSDoc comment for the sanitizeValue function was missing its closing
`*/` delimiter, causing TypeScript to interpret the function declaration
as part of the comment and fail with TS2304: Cannot find name 'sanitizeValue'.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(analytics): add tracking for engagement, settings, and onboarding events

Add analytics tracking for:
- APP_OPENED, APP_BACKGROUNDED, APP_SESSION_STARTED, DAILY_CHECK_IN (engagement)
- SETTINGS_CHANGED for theme and dashboard preferences
- ONBOARDING_ABANDONED when user signs out during onboarding
- SAVINGS_UPDATED when editing savings settings

Also:
- Add AppState mock to jest.setup.js for testing
- Add AnalyticsEvents to analytics mock in layout tests

* fix: update comment to reference Amplitude instead of Firebase

Co-authored-by: Bill Chirico <undefined@users.noreply.github.com>

* feat(analytics): add comprehensive onboarding analytics tracking

Add tracking for all 7 onboarding events:
- ONBOARDING_STARTED: on mount
- ONBOARDING_SCREEN_VIEWED: on mount with screen_name
- ONBOARDING_FIELD_COMPLETED: for display_name, sobriety_date, savings_tracking
- ONBOARDING_SOBRIETY_DATE_SET: when date is changed (existing)
- ONBOARDING_STEP_COMPLETED: on completion with step_name, step_number
- ONBOARDING_COMPLETED: on completion with duration_seconds, savings_enabled
- ONBOARDING_ABANDONED: on sign out (added previously)

Uses refs to prevent duplicate field completion events.

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Bill Chirico <undefined@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* 📝 Add docstrings to `develop`

Docstrings generation was requested by @BillChirico.

* #232 (comment)

The following files were modified:

* `lib/analytics-utils.ts`
* `lib/analytics/index.ts`
* `lib/analytics/platform.web.ts`

* fix: add missing trailing newlines to files

The docstrings PR removed trailing newlines from the end of files.
This commit restores them to follow POSIX file format conventions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Bill Chirico <bill@chirico.dev>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Bill Chirico <undefined@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend Frontend/UI related changes refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants