Firebase setup
your own project.
Create the project, deploy the rules, indexes and Cloud Functions, connect the app and switch on App Check. The full reference is firebase/README.md in the package.
01Create the project
- Create a Firebase projectIn the Firebase console, add a project. Remember its project id.
- Upgrade to BlazeCloud Functions, Cloud Scheduler and calls to the ad networks and stores only work on the Blaze (pay-as-you-go) plan. Set a budget alert in Google Cloud Billing. Required
- Enable AuthenticationBuild → Authentication → Sign-in method. Enable Anonymous (the "Continue as guest" button), Google and Apple. The app signs in with these three and lets a guest link Google or Apple later (
app/lib/data/firebase_backend.dart). - Create FirestoreBuild → Firestore Database, Native mode. Pick a location close to your users.
Firebase's own guides describe it: for Google on Android add your app's SHA-1 and SHA-256 fingerprints in Project settings; for Apple add the Sign in with Apple capability in Xcode and configure it in your Apple developer account. The package ships no iOS entitlements file, so Xcode creates one when you add the capability.
02Point the backend at your project
firebase/.firebaserc ships with demo-watchandearn, an emulator-only id. Replace it with yours:
cd firebase
firebase login
firebase use --add # pick your project; or edit .firebaserc by hand
03Choose the Functions region
Functions deploy to us-central1 by default (firebase/functions/src/index.ts). To use another region, create firebase/functions/.env from the example and set it:
cd firebase/functions
cp .env.example .env # then edit FUNCTIONS_REGION, e.g. europe-west1
Variable in firebase/functions/.env | Default | Purpose |
|---|---|---|
FUNCTIONS_REGION | us-central1 | Region of every function. |
ENFORCE_APP_CHECK | true | App Check on every callable. Set false only while you wire App Check up. |
If you change the region, use the same one in three places: the app build (--dart-define=FUNCTIONS_REGION=…, see Build switches), the console's Backend → Cloud Functions base URL, and every callback URL you give to ad networks and partners.
This file holds no secrets. Ad network secrets and store keys are entered in the console and stored in the Firestore document config/private, which no app can read.
04Deploy rules, indexes and functions
cd firebase/functions && npm ci && cd ..
firebase deploy --only firestore:rules,firestore:indexes,functions
The deploy builds the TypeScript first (predeploy in firebase/firebase.json). At the end it prints the URLs of the HTTP functions (ssvAdmob, ssvUnity, ssvIronsource, offerPostback, owAdgem, owLootably, owBitlabs, owCpx, paypalWebhook); you also find them in Firebase console → Functions. Building the indexes can take a few minutes.
The deploy also creates the scheduled jobs (Cloud Scheduler) and the Firestore triggers (firebase/README.md §9):
| Job or trigger | When (UTC) | What |
|---|---|---|
expireAdSessions | hourly | Unused ad sessions → expired |
settleEvents | every 15 min | Pays the prizes of ended events once |
analyticsDaily | 00:30 | Yesterday's rollup and D1/D7 retention |
pullAdReports | 12:00 | Yesterday's AdMob revenue, only when connected |
sendPushCampaigns | every 5 min | Sends due push campaigns and their inbox copies |
releaseWallet 4.0 | hourly | Pending cash past its hold → available |
walletTotals 4.0 | every 15 min | Live total of what you owe users (stats/wallet) |
pollPaypalPayouts 4.0 | every 30 min | PayPal batches still processing (fallback for a missed webhook) |
onReviewDecision | trigger | Credits an approved offerwall hold once (points or cash) |
onWalletOp 4.0 | trigger | Applies the console's payout and wallet actions once |
onSponsorWrite | trigger | Sponsor booking → revenue event |
syncPublicProfile | trigger | Name and avatar changes → public profile |
Until the operator console has run once, the Functions use the defaults from docs/CONTRACT.md, docs/CONTRACT-3.1.md and docs/CONTRACT-4.0.md (all money switches off; firebase/functions/src/config.ts). The console writes config/public and config/private on start and on every save.
05Connect the app (flutterfire configure)
app/lib/firebase_options.dart is a placeholder with empty values. While it is empty the app shows a setup screen. Replace it:
dart pub global activate flutterfire_cli
cd app
flutterfire configure # choose your project and the android, ios and web platforms
Run it again after you change the application id or bundle id (see Rebranding), so the Firebase apps match the new ids.
06App Check
Every callable function refuses calls without a valid App Check token in production (firebase/functions/src/guard.ts). The app activates App Check on Android and iOS (app/lib/core/firebase_setup.dart): Play Integrity on Android, App Attest with DeviceCheck fallback on iOS, and the debug provider in debug builds.
- Register the appsFirebase console → App Check → Apps. Register the Android app with Play Integrity and the iOS app with App Attest (and DeviceCheck).
- Add debug tokens for developmentA debug build prints a debug token in the device log the first time it starts. Add it in Firebase console → App Check → Apps → your app → Manage debug tokens. Without it a debug build gets
permission-deniedorunauthenticatederrors. - Enforce for FirestoreApp Check → APIs → Cloud Firestore → Enforce.
- While wiring upYou may set
ENFORCE_APP_CHECK=falseinfirebase/functions/.envand redeploy. Turn it back totruebefore release. The emulator never enforces App Check.
Play Integrity tokens are valid for the app as distributed by Google Play. Add your upload and app signing certificate fingerprints in Firebase Project settings, and test release behaviour with an internal-testing build from Play Console.
07Indexes and rules
firebase/firestore.indexes.json holds the composite indexes (ad-session expiry, open fraud flags, push campaigns, events, the review queue, redemptions, revenue events by source and offerwall conversions, payout requests by user, status and method, conversions by user, and wallet entries by state and release time) and the collection-group overrides the console and account deletion need (ledger.createdAt descending, daily.day, leaderboard entries.points and entries.uid, friends.uid). firebase/firestore.rules lets a user read only their own data and change only their displayName, settings, equipped cosmetics they own and the read mark of their inbox items. Points, ledger, streaks, leaderboards and everything that credits are written only by the server. Since 4.0 a user can also read their own wallet, wallet entries and payout requests, and never write them; payoutDestinations, payoutEvents and config/private are closed to clients.
08Check it worked
- Firebase console → Functions lists
ensureProfile,requestAdSession,ssvAdmob,owAdgemand the other functions in your region - Firestore → Indexes shows every index as Enabled
- After the console started once, Firestore has
config/publicandconfig/private - The app starts past the setup screen and "Continue as guest" works