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
@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyAregLaXQ-WqRQTltTRyjQx3-lfxLl4Cng</string>
<key>GCM_SENDER_ID</key>
<string>334225114072</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.alexandrevazquez.PortfolioJournal</string>
<key>PROJECT_ID</key>
<string>portfoliojournal-ef2d7</string>
<key>STORAGE_BUCKET</key>
<string>portfoliojournal-ef2d7.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:334225114072:ios:a0a50b5835ac042e3d28ad</string>
</dict>
</plist>
-269
View File
@@ -31,10 +31,6 @@
</array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-1549720748100858~9632507420</string>
<key>GADDelayAppMeasurementInit</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
@@ -54,271 +50,6 @@
<string>Use Face ID to unlock your portfolio data.</string>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUserTrackingUsageDescription</key>
<string>This app uses tracking to provide personalized ads and improve your experience. Your data is not sold to third parties.</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4fzdc2evr5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4pfyvq9l8r.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2fnua5tdw4.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ydx93a7ass.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>5a6flpkh64.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>p78axxw29g.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v72qych5uu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ludvb6z3bs.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cp8zw746q7.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3sh42y64q3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>c6k4g5qg8m.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>s39g8k73mm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3qy4746246.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>f38h382jlk.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>hs6bdukanm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v4nxqhlyqp.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>wzmmz9fp6w.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>yclnxrl5pm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>t38b2kh725.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7ug5zh24hu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>gta9lk7p23.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>vutu7akeur.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>y5ghdn5j9k.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>n6fk4nfna4.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v9wttpbfk9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>n38lu8286q.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>47vhws6wlr.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>kbd757ber7.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>9t245vhmpl.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>eh6m2bh4zr.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>a2p9lx4jpn.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>22mmun2rn5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4468km3ulz.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2u9pt9hc89.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>8s468mfl3y.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>klf5c3l5u5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ppxm28t8ap.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ecpz2srf59.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>uw77j35x4d.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>pwa73g5rt2.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>mlmmfzh3r3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>578prtvx9j.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4dzt52r2t5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>e5fvkxwrpn.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>8c4e2ghe7u.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>zq492l623r.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3rd42ekr43.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3qcr597p9d.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>su67r6k2v3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>kbd757ywx3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>44n7hlldy6.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>k674qkevps.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2rq3zucswp.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>5tjdwbrq8w.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>97r2b46745.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>b9bk5wbcq9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>44jx6755aq.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>kbmxgpxpgc.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>tl55sbb4fm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>9g2aggbj52.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>g2y4y55b64.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>c3frkrj4fj.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>r26jy69rpl.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>275upjj5gd.skadnetwork</string>
</dict>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
@@ -85,16 +85,12 @@
"feature_predictions_desc" = "KI-gestützte 12-Monats-Prognosen";
"feature_export" = "Daten exportieren";
"feature_export_desc" = "Export nach CSV und JSON";
"feature_no_ads" = "Keine Werbung";
"feature_no_ads_desc" = "Dauerhaft werbefrei";
"paywall_benefit_history_title" = "Deine vollständige Historie";
"paywall_benefit_history_subtitle" = "Jeder Snapshot, Beitrag und Gewinn seit Tag eins";
"paywall_benefit_charts_title" = "Charts, die Muster zeigen";
"paywall_benefit_charts_subtitle" = "Allokation, Drawdown, Performance, alles an einem Ort";
"paywall_benefit_forecasts_title" = "12-Monats-Prognosen";
"paywall_benefit_forecasts_subtitle" = "Sieh, wohin sich dein Portfolio wahrscheinlich entwickelt";
"paywall_benefit_noads_title" = "Keine Werbung, jemals";
"paywall_benefit_noads_subtitle" = "Klares, fokussiertes Erlebnis ohne Ablenkung";
"settings_title" = "Einstellungen";
"subscription" = "Abo";
"notifications" = "Benachrichtigungen";
@@ -109,8 +109,6 @@
"feature_predictions_desc" = "AI-powered 12-month forecasts";
"feature_export" = "Export Data";
"feature_export_desc" = "Export to CSV and JSON formats";
"feature_no_ads" = "No Ads";
"feature_no_ads_desc" = "Ad-free experience forever";
// Paywall benefits (1.2.0)
"paywall_benefit_history_title" = "Your complete history";
@@ -119,8 +117,6 @@
"paywall_benefit_charts_subtitle" = "Allocation, drawdown, performance — all in one place";
"paywall_benefit_forecasts_title" = "12-month forecasts";
"paywall_benefit_forecasts_subtitle" = "See where your portfolio is likely heading";
"paywall_benefit_noads_title" = "No ads, ever";
"paywall_benefit_noads_subtitle" = "Clean, focused experience with no distractions";
// MARK: - Settings
"settings_title" = "Settings";
@@ -154,8 +154,6 @@
"paywall_benefit_charts_subtitle" = "Asignación, drawdown, rendimiento — todo en un lugar";
"paywall_benefit_forecasts_title" = "Previsiones a 12 meses";
"paywall_benefit_forecasts_subtitle" = "Ve a dónde se dirige tu cartera";
"paywall_benefit_noads_title" = "Sin anuncios, nunca";
"paywall_benefit_noads_subtitle" = "Una experiencia limpia y sin distracciones";
// MARK: - Onboarding pages (1.2.0)
"onboarding_clarity_title" = "Sabe exactamente dónde estás";
@@ -85,16 +85,12 @@
"feature_predictions_desc" = "Prévisions IA sur 12 mois";
"feature_export" = "Exporter les données";
"feature_export_desc" = "Export vers CSV et JSON";
"feature_no_ads" = "Sans publicité";
"feature_no_ads_desc" = "Expérience sans publicité à vie";
"paywall_benefit_history_title" = "Votre historique complet";
"paywall_benefit_history_subtitle" = "Chaque snapshot, contribution et gain depuis le premier jour";
"paywall_benefit_charts_title" = "Des graphiques qui révèlent des tendances";
"paywall_benefit_charts_subtitle" = "Allocation, drawdown, performance, le tout au même endroit";
"paywall_benefit_forecasts_title" = "Prévisions à 12 mois";
"paywall_benefit_forecasts_subtitle" = "Voyez où votre portefeuille pourrait aller";
"paywall_benefit_noads_title" = "Aucune pub, jamais";
"paywall_benefit_noads_subtitle" = "Une expérience propre et centrée, sans distractions";
"settings_title" = "Réglages";
"subscription" = "Abonnement";
"notifications" = "Notifications";
@@ -85,16 +85,12 @@
"feature_predictions_desc" = "Previsioni a 12 mesi basate su IA";
"feature_export" = "Esporta dati";
"feature_export_desc" = "Esporta in CSV e JSON";
"feature_no_ads" = "Niente pubblicità";
"feature_no_ads_desc" = "Esperienza senza pubblicità per sempre";
"paywall_benefit_history_title" = "La tua cronologia completa";
"paywall_benefit_history_subtitle" = "Ogni snapshot, contributo e guadagno dal primo giorno";
"paywall_benefit_charts_title" = "Grafici che rivelano schemi";
"paywall_benefit_charts_subtitle" = "Allocazione, drawdown, performance: tutto in un unico posto";
"paywall_benefit_forecasts_title" = "Previsioni a 12 mesi";
"paywall_benefit_forecasts_subtitle" = "Guarda dove probabilmente andrà il tuo portafoglio";
"paywall_benefit_noads_title" = "Niente pubblicità, mai";
"paywall_benefit_noads_subtitle" = "Esperienza pulita e focalizzata, senza distrazioni";
"settings_title" = "Impostazioni";
"subscription" = "Abbonamento";
"notifications" = "Notifiche";
@@ -85,16 +85,12 @@
"feature_predictions_desc" = "AI による12か月予測";
"feature_export" = "データを書き出し";
"feature_export_desc" = "CSV と JSON に書き出し";
"feature_no_ads" = "広告なし";
"feature_no_ads_desc" = "ずっと広告なしで使えます";
"paywall_benefit_history_title" = "完全な履歴";
"paywall_benefit_history_subtitle" = "初日からのすべての snapshot、追加資金、利益を確認";
"paywall_benefit_charts_title" = "傾向が見えるチャート";
"paywall_benefit_charts_subtitle" = "配分、ドローダウン、パフォーマンスを一か所で確認";
"paywall_benefit_forecasts_title" = "12か月予測";
"paywall_benefit_forecasts_subtitle" = "ポートフォリオの行き先を見通せます";
"paywall_benefit_noads_title" = "広告は一切なし";
"paywall_benefit_noads_subtitle" = "気が散らない、集中できる体験";
"settings_title" = "設定";
"subscription" = "サブスクリプション";
"notifications" = "通知";
@@ -85,16 +85,12 @@
"feature_predictions_desc" = "Previsões de 12 meses com IA";
"feature_export" = "Exportar dados";
"feature_export_desc" = "Exporte para CSV e JSON";
"feature_no_ads" = "Sem anúncios";
"feature_no_ads_desc" = "Experiência sem anúncios para sempre";
"paywall_benefit_history_title" = "Seu histórico completo";
"paywall_benefit_history_subtitle" = "Cada snapshot, contribuição e ganho desde o primeiro dia";
"paywall_benefit_charts_title" = "Gráficos que revelam padrões";
"paywall_benefit_charts_subtitle" = "Alocação, drawdown, desempenho: tudo em um só lugar";
"paywall_benefit_forecasts_title" = "Previsões de 12 meses";
"paywall_benefit_forecasts_subtitle" = "Veja para onde sua carteira provavelmente está indo";
"paywall_benefit_noads_title" = "Sem anúncios, nunca";
"paywall_benefit_noads_subtitle" = "Experiência limpa e focada, sem distrações";
"settings_title" = "Ajustes";
"subscription" = "Assinatura";
"notifications" = "Notificações";