quitar AdMob, Firebase Analytics y ATT de la app

"Portfolio Journal sin AdMob ni Google: es la única forma de que 'sin
rastreo' sea verdad, y el ingreso por anuncios es despreciable" — la ficha
de App Store prometía "sin analíticas, sin rastreo, sin venta de datos"
mientras la app enlazaba GoogleMobileAds y FirebaseAnalytics, pedía permiso
de rastreo al arrancar y mandaba el importe del saldo a GA4 en el evento
snapshot_added.

SDKs fuera del proyecto (project.pbxproj): paquetes firebase-ios-sdk y
swift-package-manager-google-mobile-ads, productos FirebaseCore,
FirebaseAnalytics, GoogleMobileAds y FirebaseCrashlytics, más la fase de
build "Upload dSYMs to Crashlytics". Package.resolved se queda sin nada que
resolver. Con la fase de script fuera, ENABLE_USER_SCRIPT_SANDBOXING vuelve
a YES en el target app (estaba en NO solo por Crashlytics).

Código borrado:
- Services/AdMobService.swift entero — con él se van el flujo UMP,
  BannerAdView, BannerAdCoordinator y la llamada a
  ATTrackingManager.requestTrackingAuthorization().
- Services/FirebaseService.swift entero y sus 40 llamadas. Se borra en vez
  de dejarse como capa vacía: una clase llamada FirebaseService en una app
  que presume de no llevar Firebase es exactamente la clase de detalle que
  vuelve a colarse en una auditoría dentro de un año.
- El banner y su safeAreaInset en ContentView (bannerInsetView): las cinco
  pestañas ya no reservan 50 pt al pie.
- La entrada "Manage Ad Consent" de Ajustes y el @EnvironmentObject
  adMobService de SettingsView, ContentView y PortfolioJournalApp.
- AppConstants: bloque AdMob, bannerAdHeight, adConsentObtained,
  Features.enableAnalytics.
- SettingsViewModel.toggleAnalytics y analyticsEnabled — el flag no estaba
  conectado a nada ni tenía control en la interfaz. El atributo
  AppSettings.enableAnalytics se queda en CoreData con un comentario: no
  vale la pena una migración y un deploy de esquema CloudKit por borrarlo.
- Premium ya no promete "sin anuncios": fuera PremiumFeature.noAds, la
  entrada de IAPService.premiumFeatures y paywallBenefits, y las claves
  feature_no_ads / paywall_benefit_noads de los 7 idiomas. No se toca ni el
  precio ni el producto.

Info.plist: fuera NSUserTrackingUsageDescription, GADApplicationIdentifier,
GADDelayAppMeasurementInit y los 65 SKAdNetworkItems. Borrados también
GoogleService-Info.plist y los scripts Scripts/analyze_ga4.py y
Scripts/analyze_crashlytics.py, que ya no tienen de dónde leer.

Closes #50

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1u4K16xy7eQVtgsYNZ9Vn
This commit is contained in:
alexandrev-tibco
2026-09-18 16:09:04 +02:00
parent 319ab9589e
commit 7d2f605c16
39 changed files with 23 additions and 1503 deletions
@@ -96,9 +96,6 @@ struct ChartsContainerView: View {
if !viewModel.isPremium {
CompactPaywallBanner(showingPaywall: $viewModel.showingPaywall)
.onAppear {
FirebaseService.shared.logPaywallShown(trigger: "charts_banner")
}
}
chartContent
if viewModel.hiddenHistoryMonths > 0 {
@@ -581,7 +578,6 @@ struct ChartsContainerView: View {
/// 12-month window; tell them exactly how much is locked instead of hiding it.
private var lockedHistoryTeaser: some View {
Button {
FirebaseService.shared.logPaywallShown(trigger: "history_teaser")
viewModel.showingPaywall = true
} label: {
HStack(spacing: 8) {
@@ -611,9 +607,6 @@ struct ChartsContainerView: View {
chartTypeChipBar
if !viewModel.isPremium {
CompactPaywallBanner(showingPaywall: $viewModel.showingPaywall)
.onAppear {
FirebaseService.shared.logPaywallShown(trigger: "charts_banner")
}
}
iPhonePeriodControl
if hasActiveFilters {
@@ -862,7 +855,6 @@ struct ChartsContainerView: View {
/// back.
private func drillDown(to name: String) {
guard viewModel.isPremium else {
FirebaseService.shared.logPaywallShown(trigger: "chart_workable")
viewModel.showingPaywall = true
return
}
@@ -916,7 +908,6 @@ struct ChartsContainerView: View {
contributions: viewModel.contributionsData,
isPremium: viewModel.isPremium,
onPremiumNeeded: {
FirebaseService.shared.logPaywallShown(trigger: "chart_workable")
viewModel.showingPaywall = true
}
)
@@ -996,7 +987,6 @@ struct ChartsContainerView: View {
.multilineTextAlignment(.center)
Button {
FirebaseService.shared.logPaywallShown(trigger: "advanced_charts")
viewModel.showingPaywall = true
} label: {
Text(String(localized: "chart_locked_cta"))