feat: add GA4 key events tracking (run_simulation, open_example, create_project, compile_code, visit_github)
Co-authored-by: davidmonterocrespo24 <47928504+davidmonterocrespo24@users.noreply.github.com>pull/37/head
parent
156a6159b7
commit
13ee547ad7
|
|
@ -0,0 +1,108 @@
|
|||
# Analytics Events
|
||||
|
||||
Velxio uses **Google Analytics 4 (GA4)** to measure key user interactions. Events are fired via `gtag` and should be marked as **Key Events** in the GA4 dashboard to track conversions and engagement.
|
||||
|
||||
The tracking utility lives in [`frontend/src/utils/analytics.ts`](../frontend/src/utils/analytics.ts).
|
||||
|
||||
---
|
||||
|
||||
## Key Events
|
||||
|
||||
### `run_simulation`
|
||||
|
||||
Fired when the user clicks the **Run** button to start a simulation.
|
||||
|
||||
| Property | Value |
|
||||
|------------------|--------------|
|
||||
| `event_category` | `engagement` |
|
||||
|
||||
**Location:** `EditorToolbar.tsx` → `handleRun()`
|
||||
|
||||
---
|
||||
|
||||
### `open_example`
|
||||
|
||||
Fired when a user loads a sample project from the Examples gallery.
|
||||
|
||||
| Property | Value |
|
||||
|------------------|------------------------|
|
||||
| `event_category` | `engagement` |
|
||||
| `event_label` | Title of the example |
|
||||
|
||||
**Location:** `ExamplesPage.tsx` → `handleLoadExample()`
|
||||
|
||||
---
|
||||
|
||||
### `create_project`
|
||||
|
||||
Fired when a user successfully saves a **new** project (not when updating an existing one).
|
||||
|
||||
| Property | Value |
|
||||
|------------------|--------------|
|
||||
| `event_category` | `engagement` |
|
||||
|
||||
**Location:** `SaveProjectModal.tsx` → `handleSave()`
|
||||
|
||||
---
|
||||
|
||||
### `compile_code`
|
||||
|
||||
Fired when code compilation starts (user clicks the **Compile** button).
|
||||
|
||||
| Property | Value |
|
||||
|------------------|---------------|
|
||||
| `event_category` | `development` |
|
||||
|
||||
**Location:** `EditorToolbar.tsx` → `handleCompile()`
|
||||
|
||||
---
|
||||
|
||||
### `visit_github`
|
||||
|
||||
Fired when a user clicks any link pointing to the Velxio GitHub repository.
|
||||
|
||||
| Property | Value |
|
||||
|------------------|-----------------|
|
||||
| `event_category` | `external_link` |
|
||||
|
||||
**Locations:**
|
||||
- `LandingPage.tsx` — nav bar, hero CTA, and footer GitHub links
|
||||
- `AppHeader.tsx` — editor header GitHub link
|
||||
|
||||
---
|
||||
|
||||
## Implementation
|
||||
|
||||
All helpers are exported from `frontend/src/utils/analytics.ts`:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
trackRunSimulation,
|
||||
trackOpenExample,
|
||||
trackCreateProject,
|
||||
trackCompileCode,
|
||||
trackVisitGitHub,
|
||||
} from '../utils/analytics';
|
||||
```
|
||||
|
||||
Example usage:
|
||||
|
||||
```typescript
|
||||
// Fire an event
|
||||
trackRunSimulation();
|
||||
|
||||
// Fire an event with a label
|
||||
trackOpenExample('Blink LED');
|
||||
```
|
||||
|
||||
The module safely checks whether `gtag` is available before calling it, so it does not throw errors in environments where the GA script is not loaded (e.g., local development without the GA tag).
|
||||
|
||||
---
|
||||
|
||||
## Marking Events as Key Events in GA4
|
||||
|
||||
1. Open **Google Analytics → Admin → Events**.
|
||||
2. Locate the event by name (e.g. `run_simulation`).
|
||||
3. Toggle **Mark as key event** to enable conversion tracking.
|
||||
|
||||
Repeat for each event listed above.
|
||||
|
|
@ -7,6 +7,7 @@ import { InstallLibrariesModal } from '../simulator/InstallLibrariesModal';
|
|||
import { parseCompileResult } from '../../utils/compilationLogger';
|
||||
import type { CompilationLog } from '../../utils/compilationLogger';
|
||||
import { exportToWokwiZip, importFromWokwiZip } from '../../utils/wokwiZip';
|
||||
import { trackCompileCode, trackRunSimulation } from '../../utils/analytics';
|
||||
import './EditorToolbar.css';
|
||||
|
||||
interface EditorToolbarProps {
|
||||
|
|
@ -43,6 +44,7 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
|
|||
setCompiling(true);
|
||||
setMessage(null);
|
||||
setConsoleOpen(true);
|
||||
trackCompileCode();
|
||||
|
||||
const fqbn = BOARD_FQBN[boardType];
|
||||
const boardLabel = BOARD_LABELS[boardType];
|
||||
|
|
@ -81,6 +83,7 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
|
|||
|
||||
const handleRun = () => {
|
||||
if (compiledHex) {
|
||||
trackRunSimulation();
|
||||
startSimulation();
|
||||
setMessage(null);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../../store/useAuthStore';
|
||||
import { trackVisitGitHub } from '../../utils/analytics';
|
||||
|
||||
interface AppHeaderProps {}
|
||||
|
||||
|
|
@ -55,6 +56,7 @@ export const AppHeader: React.FC<AppHeaderProps> = () => {
|
|||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="GitHub — Velxio"
|
||||
onClick={trackVisitGitHub}
|
||||
style={{ display: 'flex', alignItems: 'center', gap: 5, color: '#ccc', textDecoration: 'none', fontSize: 13 }}
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useEditorStore } from '../../store/useEditorStore';
|
|||
import { useSimulatorStore } from '../../store/useSimulatorStore';
|
||||
import { useProjectStore } from '../../store/useProjectStore';
|
||||
import { createProject, updateProject } from '../../services/projectService';
|
||||
import { trackCreateProject } from '../../utils/analytics';
|
||||
|
||||
interface SaveProjectModalProps {
|
||||
onClose: () => void;
|
||||
|
|
@ -56,6 +57,7 @@ export const SaveProjectModal: React.FC<SaveProjectModalProps> = ({ onClose }) =
|
|||
saved = await updateProject(currentProject.id, payload);
|
||||
} else {
|
||||
saved = await createProject(payload);
|
||||
trackCreateProject();
|
||||
}
|
||||
setCurrentProject({
|
||||
id: saved.id,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { ExamplesGallery } from '../components/examples/ExamplesGallery';
|
|||
import { useEditorStore } from '../store/useEditorStore';
|
||||
import { useSimulatorStore } from '../store/useSimulatorStore';
|
||||
import type { ExampleProject } from '../data/examples';
|
||||
import { trackOpenExample } from '../utils/analytics';
|
||||
|
||||
export const ExamplesPage: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -18,6 +19,7 @@ export const ExamplesPage: React.FC = () => {
|
|||
|
||||
const handleLoadExample = (example: ExampleProject) => {
|
||||
console.log('Loading example:', example.title);
|
||||
trackOpenExample(example.title);
|
||||
|
||||
// Switch board type if the example specifies one
|
||||
const targetBoard = example.boardType || 'arduino-uno';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../store/useAuthStore';
|
||||
import { trackVisitGitHub } from '../utils/analytics';
|
||||
import './LandingPage.css';
|
||||
|
||||
const GITHUB_URL = 'https://github.com/davidmonterocrespo24/velxio';
|
||||
|
|
@ -417,7 +418,7 @@ export const LandingPage: React.FC = () => {
|
|||
<span>Velxio</span>
|
||||
</div>
|
||||
<div className="landing-nav-links">
|
||||
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" className="nav-link">
|
||||
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" onClick={trackVisitGitHub} className="nav-link">
|
||||
<IcoGitHub /> GitHub
|
||||
</a>
|
||||
<Link to="/docs" className="nav-link">Docs</Link>
|
||||
|
|
@ -458,7 +459,7 @@ export const LandingPage: React.FC = () => {
|
|||
<IcoZap />
|
||||
Launch Editor
|
||||
</Link>
|
||||
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" className="cta-secondary">
|
||||
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" onClick={trackVisitGitHub} className="cta-secondary">
|
||||
<IcoGitHub />
|
||||
View on GitHub
|
||||
</a>
|
||||
|
|
@ -564,7 +565,7 @@ export const LandingPage: React.FC = () => {
|
|||
<span>Velxio</span>
|
||||
</div>
|
||||
<div className="footer-links">
|
||||
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer">GitHub</a>
|
||||
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" onClick={trackVisitGitHub}>GitHub</a>
|
||||
<Link to="/docs">Docs</Link>
|
||||
<Link to="/examples">Examples</Link>
|
||||
<Link to="/editor">Editor</Link>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Google Analytics 4 Key Events Tracking
|
||||
*
|
||||
* Provides helper functions to fire GA4 custom events for key user actions.
|
||||
* Each function maps to an event that should be marked as a Key Event in GA4.
|
||||
*/
|
||||
|
||||
declare function gtag(command: 'event', eventName: string, eventParams?: Record<string, unknown>): void;
|
||||
|
||||
function fireEvent(eventName: string, params: Record<string, string | number | boolean>): void {
|
||||
if (typeof gtag === 'function') {
|
||||
gtag('event', eventName, params);
|
||||
}
|
||||
}
|
||||
|
||||
/** Fired when the user starts a simulation (clicks Run). */
|
||||
export function trackRunSimulation(): void {
|
||||
fireEvent('run_simulation', { event_category: 'engagement' });
|
||||
}
|
||||
|
||||
/** Fired when a user loads a sample project from the examples gallery. */
|
||||
export function trackOpenExample(exampleTitle?: string): void {
|
||||
fireEvent('open_example', {
|
||||
event_category: 'engagement',
|
||||
...(exampleTitle ? { event_label: exampleTitle } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
/** Fired when a user successfully creates a new project. */
|
||||
export function trackCreateProject(): void {
|
||||
fireEvent('create_project', { event_category: 'engagement' });
|
||||
}
|
||||
|
||||
/** Fired when code compilation starts. */
|
||||
export function trackCompileCode(): void {
|
||||
fireEvent('compile_code', { event_category: 'development' });
|
||||
}
|
||||
|
||||
/** Fired when a user clicks any GitHub repository link. */
|
||||
export function trackVisitGitHub(): void {
|
||||
fireEvent('visit_github', { event_category: 'external_link' });
|
||||
}
|
||||
Loading…
Reference in New Issue