Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ jobs:
run: npm install

- name: Build
env:
VITE_GA_ID: ${{ secrets.VITE_GA_ID }}
run: npm run build

- name: Setup Pages
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"react": "^18.3.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
"react-ga4": "^2.1.0",
"react-hook-form": "^7.61.1",
"react-resizable-panels": "^2.1.9",
"react-router-dom": "^6.30.1",
Expand Down
17 changes: 17 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,28 @@ import { useGameStore } from "@/store/gameStore";
import { toast } from "sonner";
import { formatCurrency } from "@/lib/utils";
import { GAME_CONFIG, calculateCurrentIncome } from "@/config/gameConfig";
import { initGA, trackPageView } from "@/lib/analytics";
import { useLocation } from "react-router-dom";

const queryClient = new QueryClient();

const AnalyticsTracker = () => {
const location = useLocation();

useEffect(() => {
trackPageView(location.pathname + location.search);
}, [location]);

return null;
};

const App = () => {
const offlineProcessed = useRef(false);

useEffect(() => {
initGA();
}, []);

// Offline income calculation — runs once on mount
useEffect(() => {
if (offlineProcessed.current) return;
Expand Down Expand Up @@ -65,6 +81,7 @@ const App = () => {
<Toaster />
<Sonner />
<BrowserRouter>
<AnalyticsTracker />
<Routes>
<Route path="/" element={<Index />} />
<Route path="/collection" element={<Collection />} />
Expand Down
43 changes: 43 additions & 0 deletions src/lib/analytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import ReactGA from "react-ga4";

const GA_MEASUREMENT_ID = import.meta.env.VITE_GA_ID;

export const initGA = () => {
if (GA_MEASUREMENT_ID) {
ReactGA.initialize(GA_MEASUREMENT_ID);
console.log("GA Initialized");
}
};

export const trackPageView = (path: string) => {
if (GA_MEASUREMENT_ID) {
ReactGA.send({ hitType: "pageview", page: path });
}
};

export const trackEvent = (category: string, action: string, label?: string, value?: number) => {
if (GA_MEASUREMENT_ID) {
ReactGA.event({
category,
action,
label,
value,
});
}
};

export const trackPackOpening = (packName: string, cost: number) => {
trackEvent("Game", "Pack Opened", packName, cost);
};

export const trackUpgrade = (upgradeType: string, level: number, cost: number) => {
trackEvent("Game", "Upgrade Purchased", `${upgradeType} - Level ${level}`, cost);
};

export const trackDimensionStart = (level: number) => {
trackEvent("Game", "Dimension Started", `Level ${level}`);
};

export const trackDimensionEnd = (level: number, reward: number) => {
trackEvent("Game", "Dimension Ended", `Reached Level ${level}`, reward);
};
29 changes: 22 additions & 7 deletions src/store/gameStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import {
Character,
GameState as BaseGameState,
} from "@/types/game";
import {
trackPackOpening,
trackUpgrade,
trackDimensionStart,
trackDimensionEnd,
} from "@/lib/analytics";

interface GameState extends BaseGameState {
addCard: (card: GameCard) => boolean;
Expand Down Expand Up @@ -191,6 +197,8 @@ export const useGameStore = create<GameState>()(
seeds: state.seeds - pack.cost,
}));

trackPackOpening(pack.name, pack.cost);

return newCards;
},

Expand Down Expand Up @@ -230,6 +238,7 @@ export const useGameStore = create<GameState>()(
dimensionLevel: 1,
currentEnemy: enemy,
}));
trackDimensionStart(1);
return true;
},

Expand Down Expand Up @@ -268,6 +277,8 @@ export const useGameStore = create<GameState>()(
},

resetDimension: (reward) => {
const { dimensionLevel } = get();
trackDimensionEnd(dimensionLevel, reward);
set((s) => ({
seeds: s.seeds + reward,
isDimensionActive: false,
Expand Down Expand Up @@ -296,13 +307,17 @@ export const useGameStore = create<GameState>()(

if (seeds < cost) return false;

set((s) => ({
seeds: s.seeds - cost,
upgrades: {
...s.upgrades,
[type]: s.upgrades[type] + 1,
},
}));
set((s) => {
const newLevel = s.upgrades[type] + 1;
trackUpgrade(type, newLevel, cost);
return {
seeds: s.seeds - cost,
upgrades: {
...s.upgrades,
[type]: newLevel,
},
};
});
return true;
},

Expand Down
Loading