← Все инструкции

Firebase, аналитика, реклама и пуши

Шпаргалка: что и зачем настраивать в новом Expo-приложении, чтобы события уходили в Google Analytics, реклама в Google Ads видела установки, а пуш-уведомления доходили. Значения в примерах взяты из AiAstrology, в новом приложении подставь свои (таблица в самом конце).

Как всё связано

Приложение
→
Firebase SDK
→
Google Analytics
→
Google Ads
Сервер
→
Expo Push
→
FCM (Android) / APNs (iOS)
→
Телефон

Это две независимые цепочки. Первая — аналитика и реклама: приложение рассказывает Google, кто установил приложение и что делал. Вторая — пуши: сервер отправляет уведомления через Expo. Общее у них одно: оба работают через один Firebase-проект, а на Android пушам тоже нужен google-services.json.

Кто есть кто

FirebaseGoogle-платформа для приложений. Нам из неё нужны SDK аналитики и FCM для пушей.
Google Analytics (GA4)Куда Firebase складывает события. Здесь выбирают «ключевые события».
Google AdsРеклама. Импортирует установки и ключевые события как конверсии и учится на них.
google-services.jsonКонфиг Firebase для Android: какой проект, какое приложение.
GoogleService-Info.plistТо же самое для iOS.
Expo PushСервис Expo: принимает пуш от нашего сервера и передаёт его Google или Apple.
FCMFirebase Cloud Messaging: доставляет пуши на Android.
APNsApple Push Notification service: доставляет пуши на iOS.

Чек-лист для нового приложения

Шаги по порядку. Галочки сохраняются только в этом браузере.

Часть 1. Аналитика и реклама
Зачем вообще. Чтобы реклама на установку приложения (Google Ads App campaigns) работала, Google должен знать, кто установил приложение после клика и кто потом сделал что-то ценное (прошёл онбординг, купил). Тогда алгоритм показывает рекламу похожим людям, а мы видим цену установки и покупки.
AndroidiOS
УстановкиGoogle Play сам передаёт их в Google Ads. SDK не нужен, достаточно связать аккаунты (шаг 7).Apple ничего не передаёт в Google. Нужен Firebase SDK: он шлёт событие first_open, Google Ads считает его установкой.
Действия в приложенииТолько через Firebase → Google Analytics → импорт в Google Ads.

1Создать Firebase-проект

Зачем: всё остальное (конфиги, аналитика, FCM для пушей) привязано к проекту.
  1. console.firebase.google.com → Create a project.
  2. На шаге про Google Analytics оставить его включённым и выбрать или создать GA-аккаунт. Без этого события некуда будет складывать. Если забыл: Project settings → Integrations → Google Analytics.

В AiAstrology проект называется aiastrology-3a616.

2Добавить приложения и скачать конфиги

Зачем: конфиг — это «паспорт» приложения в Firebase-проекте (id проекта, id приложения, API key, bundle id). По нему SDK понимает, куда слать события. Без конфига сборка падает на prebuild. Настоящим секретом конфиг не считается: эти данные всё равно зашиты в APK/IPA.

⚙️ Project settings → General, ниже блок Your apps.

Firebase: Project settings Your apps: список приложений проекта

Android

Add app → Android, package name как expo.android.package в app.json. SHA-1 не обязателен (нужен для Google Sign-In, берётся из eas credentials). Скачать google-services.json.

iOS

Add app → значок iOS+.

Add app: выбор платформы iOS

Заполнить и нажать Register app:

Register app: bundle ID, nickname, App Store ID

Скачать GoogleService-Info.plist. Следующие шаги мастера, «Add Firebase SDK» и «Add initialization code», пропустить (Next → Continue to console). Они для нативного Swift-проекта, а у нас SDK ставится через npm, и инициализацию плагин добавляет сам (шаг 3).

Шаг Add Firebase SDK: пропустить Шаг Add initialization code: пропустить

Куда положить

ФайлКудаВ git
GoogleService-Info.plistкорень проектада
google-services.jsonв AiAstrology: android/app/
лучше: корень проекта
в AiAstrology нет, /android в .gitignore
В новом приложении сразу клади google-services.json в корень и указывай "googleServicesFile": "./google-services.json". Если он лежит в /android, то npx expo prebuild --clean его удалит, а EAS Build его не увидит, потому что папка в gitignore.

Если в консоли что-то поменяли у приложения (SHA, OAuth client), конфиг нужно скачать заново. В plist может стоять IS_ANALYTICS_ENABLED = false: это устаревшее поле, SDK его не читает.

3Поставить SDK и плагин

Зачем: отправлять события из JS без нативного SDK нельзя. Плагин при npx expo prebuild сам вписывает Firebase в нативные проекты.
yarn add @react-native-firebase/app @react-native-firebase/analytics

В AiAstrology стоит версия 26.4.0: версия 27 требует Node ≥ 24, а в проекте Node 20. Проверь node -v и, если нужно, укажи версию явно: @26.4.0.

app.json:

"ios":     { "googleServicesFile": "./GoogleService-Info.plist" },
"android": { "googleServicesFile": "./google-services.json" },
"plugins": [
  ["@react-native-firebase/app", { "ios": { "disableSPM": true } }],
  ["expo-build-properties", { "ios": { "extraPods": [
    { "name": "FirebaseCore", "modular_headers": true },
    { "name": "FirebaseCoreInternal", "modular_headers": true },
    { "name": "FirebaseCoreExtension", "modular_headers": true },
    { "name": "FirebaseInstallations", "modular_headers": true },
    { "name": "GoogleDataTransport", "modular_headers": true },
    { "name": "GoogleUtilities", "modular_headers": true },
    { "name": "nanopb", "modular_headers": true }
  ] } }]
]

Что плагин добавит при prebuild:

iOSFirebaseApp.configure() в AppDelegate, plist в Xcode-проект, поды Firebase
AndroidGradle-плагин com.google.gms.google-services, который читает google-services.json

Потом пересобрать: npx expo prebuild и обычная сборка. В Expo Go Firebase не работает, нужен dev build.

4Отправлять события в Firebase

Зачем: Google Ads умеет оптимизировать рекламу только по событиям, которые есть в Google Analytics.

Не нужно трогать экраны: достаточно в общей функции track() (src/services/analytics/index.ts) отправлять событие ещё и в Firebase.

reportEvent(name, attributes);          // AppMetrica
reportFirebaseEvent(name, attributes);  // Firebase

src/services/analytics/firebase.ts — можно копировать в новое приложение как есть:

import { getAnalytics, logEvent, logScreenView } from "@react-native-firebase/analytics";

/** Names Firebase reserves for its own automatic events (it collects those itself). */
const SKIPPED = new Set(["session_start", "app_background", "ad_impression"]);

export const reportFirebaseEvent = (name: string, params: Record<string, string | number | boolean>) => {
  if (SKIPPED.has(name)) return;
  try {
    const analytics = getAnalytics();
    const promise =
      name === "screen_view"
        ? logScreenView(analytics, { screen_name: String(params.screen), screen_class: String(params.screen) })
        : logEvent(analytics, name, params);
    void Promise.resolve(promise).catch((e: unknown) => {
      if (__DEV__) console.warn("Firebase logEvent failed", name, e);
    });
  } catch (e) {
    if (__DEV__) console.warn("Firebase logEvent failed", name, e);
  }
};
СобытиеВ FirebaseПочему
Обычные событиякак естьТе же имя и параметры, что в AppMetrica
screen_viewпросмотр экранаЧерез logScreenView попадает в стандартный отчёт «Экраны»
session_start, app_backgroundпропускаютсяИмена зарезервированы, Firebase пишет такие события сам
ad_impressionпропускаетсяИначе показы рекламы задвоятся в отчётах о доходе
first_openSDK шлёт самЭто и есть установка для Google Ads на iOS
Приватность: в Firebase уходят те же параметры, что в AppMetrica, уже после очистки в track(). Имена, даты рождения, места и тексты чатов не отправляются (правила в CLAUDE.md и ANALYTICS.md).

5Проверить в DebugView

Зачем: в обычных отчётах GA события появляются через сутки. DebugView (Firebase → Analytics → DebugView) показывает их сразу, но только с устройств в режиме отладки.

iOS, запуск из Xcode

Product → Scheme → Edit Scheme → Run → Arguments → Arguments Passed On Launch → «+» → -FIRDebugEnabled.

Аргумент -FIRDebugEnabled в схеме Xcode

iOS, запуск через npm run ios

expo run:ios аргументы из схемы не передаёт, поэтому перезапусти приложение с флагом (Metro продолжает работать):

xcrun simctl terminate booted com.kapernikrs.aiastrology
xcrun simctl launch booted com.kapernikrs.aiastrology -FIRDebugEnabled

Android

adb shell setprop debug.firebase.analytics.app com.kapernikrs.aiastrology

Выключить: adb shell setprop debug.firebase.analytics.app .none., на iOS — запустить с -FIRDebugDisabled.

Как должно выглядеть: через 10–60 секунд идёт поток событий (screen_view, onboarding_step_completed…), зелёный флажок у first_open. Надпись «Debug Device 0» не страшна, если события идут.

DebugView с пришедшими событиями

Если пусто: проверь, что в Firebase подключён Google Analytics (Project settings → Integrations), и поищи FirebaseAnalytics в консоли Xcode. Без режима отладки события уходят пачкой примерно раз в час.

6Отметить ключевые события в Google Analytics

Зачем: Google Ads импортирует не все события, а только отмеченные как ключевые (key events, раньше «конверсии»). По ним реклама и учится.

Это делается в Google Analytics, не в Firebase: analytics.google.com или кнопка View more in Google Analytics в DebugView. Дальше Admin → Data display → Events.

Вкладка Key events показывает только уже отмеченные. Отмечать нужно на вкладке Recent events звёздочкой ☆ слева от имени.

Google Analytics: вкладка Key events

У нового ресурса Recent events первые сутки пустой. Это нормально, просто вернись завтра.

Google Analytics: Recent events пока пусто

Что отмечать

7Подключить Google Ads

Зачем: без связи кампания не видит ни установок, ни покупок и не может учиться.
  1. Android-установки: Google Ads → Инструменты → Связанные аккаунты → Google Play → запрос. Подтвердить в Play Console: Настройки → Связанные сервисы → Google Ads. Затем Цели → Конверсии → Новое действие → Приложение → Google Play → Установки.
  2. Firebase ↔ Google Ads: Firebase → Project settings → Integrations → Google Ads → Link. Нужны Owner/Editor в Firebase и Admin в Google Ads.
  3. Импорт конверсий: Google Ads → Цели → Конверсии → «+ Новое действие-конверсия» → Импорт → Google Analytics 4 → Приложение. Отметить first_open и ключевые события из шага 6.

Совет: сначала оптимизировать кампанию на first_open или onboarding_completed. На покупки переключаться, когда их хотя бы 10–20 в день, иначе алгоритму не хватает данных.

Часть 2. Пуш-уведомления
Как устроено. Приложение получает Expo push token (ExponentPushToken[…]) и отправляет его на сервер. Сервер шлёт пуш через expo-server-sdk в Expo, а Expo передаёт его в FCM (Android) или APNs (iOS). Поэтому Expo нужны ключи от FCM и от APNs. Без них Expo принимает пуш, но до телефона он не доходит.

Что уже есть в коде AiAstrology (переносится в новое приложение)

ГдеЧто делает
src/helpers/hooks/usePushNotifications.tsСпрашивает разрешение, создаёт Android-канал, получает токен по projectId из app.json → extra.eas.projectId
AuthService.sendPushTokenPOST /push/mobile после логина
server/…/push/mobileХранит токены: один на пользователя и устройство
server/…/cron/daily-horoscope-push.cron.tsЕжедневный пуш в DAILY_PUSH_HOUR (по умолчанию 8:00) по местному времени
src/helpers/hooks/usePushNavigator.tsПо тапу открывает экран из data.screen: horoscope / chats / people

8Android: ключ FCM V1 в Expo

Зачем: по этому ключу Expo от имени нашего Firebase-проекта отправляет пуши через FCM.
  1. google-services.json должен быть в сборке (шаг 2). Без него на устройстве getExpoPushTokenAsync падает с ошибкой про FirebaseApp.
  2. Firebase → Project settings → Service accounts → Generate new private key. Скачается JSON. Ссылка для AiAstrology.
  3. Загрузить JSON в Expo: eas credentials → Android → production → Google Service Account → Push Notifications (FCM V1). Или на expo.dev → проект → Credentials → Android.
Этот JSON — настоящий секрет (полный доступ к Firebase-проекту). В git не класть, после загрузки в Expo удалить. Legacy FCM server key не нужен: Google его отключил.

9iOS: APNs-ключ в Expo

Зачем: Apple доставляет пуши только тем, у кого есть ключ от Apple Developer аккаунта. Firebase здесь не участвует.
  1. Проще всего: eas credentials → iOS → production → Push Notifications → Set up a new key. EAS сам создаст ключ в Apple и привяжет его к проекту. Capability Push Notifications EAS тоже включает сам.
  2. Вручную: developer.apple.com → Certificates, IDs & Profiles → Keys → «+» → Apple Push Notifications service → скачать .p8 (скачивается только один раз), записать Key ID и Team ID → загрузить в eas credentials. Один APNs-ключ подходит для всех приложений аккаунта.

10Отправить тестовый пуш

  1. Взять токен с реального устройства (симулятор iOS токен не даёт), например из коллекции MobilePushToken после логина.
  2. Отправить через expo.dev/notifications или так:
    curl -H "Content-Type: application/json" -X POST https://exp.host/--/api/v2/push/send \
      -d '{"to":"ExponentPushToken[...]","title":"Test","body":"Hello","data":{"screen":"horoscope"}}'
  3. В ответе будет id. Через минуту проверить, что Google/Apple приняли пуш:
    curl -H "Content-Type: application/json" -X POST https://exp.host/--/api/v2/push/getReceipts \
      -d '{"ids":["<id>"]}'
ОтветЧто значит
status: okВсё работает
InvalidCredentialsНе загружен ключ FCM V1 (шаг 8) или APNs (шаг 9)
DeviceNotRegisteredПриложение удалено или токен устарел

На сервере используется new Expo() без токена. Если на expo.dev включить Enhanced Security for Push Notifications, нужен access token (expo.dev → Account settings → Access tokens) в server/.env и new Expo({ accessToken }).

11Выпустить версию

Реальные пользователи появятся в Firebase и Google Ads только после выхода версии с Firebase в App Store и Google Play. Рекламу на установки запускать после этого.

Справочник

Значения AiAstrology

В новом приложении замени их на свои.

ЧтоЗначениеГде взять
Bundle ID / packagecom.kapernikrs.aiastrologyapp.json
Firebase-проектaiastrology-3a616console.firebase.google.com
App Store ID6756072533ссылка на приложение в App Store
EAS projectIdd1def0ec-9920-48b9-9084-f37fabbd67e1app.json → extra.eas.projectId
EAS slugexpoAiAstrologyapp.json → slug

Грабли, на которые уже наступали

СимптомРешение
expo install @react-native-firebase/… ставит v27 и падает: @firebase/ai требует Node ≥ 24.12yarn add …@26.4.0 или обновить Node
pod install: «SPM + static linkage is not supported»disableSPM: true в опциях плагина
pod install: Unicode Normalization not appropriate for ASCII-8BITЗапускать с LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
После prebuild --clean Android не собирается, нет google-services.jsonФайл был в /android и удалился. Держать его в корне
Поменял конфиг, ничего не изменилосьНужна пересборка нативного приложения, Metro reload не поможет
Debug-сборка из xcodebuild падает на facebook::react::SealableС Firebase не связано. Собирать Debug из Xcode, Release собирается
Пуш «отправлен», но не пришёлПроверить receipt (шаг 10): почти всегда не загружен ключ FCM/APNs