Global leaderboards (Firebase Firestore) + personal usage analytics (Google Analytics 4) for all 5 games.
After every game ends, a bottom sheet slides up showing:
- Your final score
- A name input to submit your score to the global leaderboard
- Top 5 scores for that game (live from Firestore)
The /leaderboard page shows all 5 game leaderboards with real-time updates via Firestore onSnapshot.
GA4 tracks game_end and score_submitted events — visible in your Google Analytics dashboard.
| File | Purpose |
|---|---|
firebase-config.js |
Your Firebase + GA4 credentials (fill in once) |
analytics.js |
Shared module — Firebase init, GA4, leaderboard panel UI |
leaderboard.html |
Full leaderboard page, all 5 games, real-time |
firestore.rules |
Firestore security rules to deploy |
Each game HTML now loads Firebase CDN + analytics.js before </body> and calls Analytics.trackGameEnd(...) at game-over.
- Go to console.firebase.google.com
- New project → name it (e.g.
brain-arcade) → Continue - Disable Google Analytics for now (you'll use GA4 separately) → Create project
- Click Web (
</>icon) → Register app → copy thefirebaseConfigobject
- In the Firebase console → Build → Firestore Database
- Create database → Start in production mode → choose a region (e.g.
asia-south1for India) → Enable
npm install -g firebase-tools
firebase login
firebase init firestore # select your project, accept defaults
# copy firestore.rules content into the generated firestore.rules file
firebase deploy --only firestore:rulesOr paste the rules directly in the Firebase console under Firestore → Rules.
Open firebase-config.js and replace the placeholder values:
window.FIREBASE_CONFIG = {
apiKey: "AIza...",
authDomain: "brain-arcade-xxxx.firebaseapp.com",
projectId: "brain-arcade-xxxx",
storageBucket: "brain-arcade-xxxx.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abcdef"
};- Go to analytics.google.com → Admin → Create Property
- Web data stream → enter your GitHub Pages URL (
https://ujjwal5.github.io/brain-arcade/) - Copy the Measurement ID (format:
G-XXXXXXXXXX) - Paste it in
firebase-config.js:
window.GA_MEASUREMENT_ID = "G-XXXXXXXXXX";git add .
git commit -m "Add Firebase leaderboard and GA4 analytics"
git pushleaderboards/{game}/scores/{auto-id}
playerName string max 20 chars
score number game-specific (see below)
game string 'chain' | 'wordle' | 'grid' | '2048' | 'letterlock'
metadata object extra context
timestamp Timestamp
| Game | Score | Direction | Metadata |
|---|---|---|---|
| Chain | words linked | higher = better | { reason, rank } |
| Wordle | guesses used (1–6), 99 = DNF | lower = better (wins only shown) | { won, guesses, streak } |
| Grid | numbers found (0–49) | higher = better | { reason, timeLeft } |
| 2048 | tile-merge score | higher = better | { won, bestTile } |
| LetterLock | points scored | higher = better | { wordsFound, bestWord } |
| Event | When | Parameters |
|---|---|---|
game_end |
Every game over | game_name, score, metadata fields |
score_submitted |
Player submits to leaderboard | game_name, score |
View these in GA4 → Reports → Engagement → Events.
Free tier (Spark plan) limits:
- 50,000 reads / day
- 20,000 writes / day
- 20,000 deletes / day
- 1 GiB storage
For a personal project this is effectively unlimited. You'd need thousands of daily active players to exceed it.
The Firestore rules validate:
scoremust be a non-negative number ≤ 999,999playerNamemust be a string ≤ 20 chars- All required fields must be present
- No updates or deletes allowed
Since this is a client-side app with no server auth, scores can still be crafted manually. This is acceptable for a personal/fun leaderboard. If you want stronger guarantees, add Firebase Anonymous Auth and rate-limit writes per UID.