Reference
Analytics event tracking
This app is instrumented for Google Analytics 4. Every custom event uses GA4 snake_case naming, fires without altering app behavior, and is listed below with its trigger and parameters.
Setup: tracking is dormant until you set a real Measurement ID. In
index.html, replace window.GA_MEASUREMENT_ID = "G-XXXXXXXXXX" with your GA4 property id. Until then, the gtag loader is a no-op: no external requests, no data sent, nothing changes.
Events
| Event name | Fires when | Parameters | Status |
|---|---|---|---|
nav_click | Any nav, footer, or CTA link is clicked | link_id, link_text | LIVE |
theme_toggle | The light/dark toggle is used | theme | LIVE |
holding_add | A position is added to the portfolio | symbol, weight_pct | LIVE |
holding_remove | A position is removed | symbol | LIVE |
sample_portfolio_load | "Load sample portfolio" is clicked | none | LIVE |
portfolio_clear | "Clear all" is clicked | none | LIVE |
benchmark_change | The benchmark dropdown value changes | benchmark | LIVE |
backtest_run | A backtest is submitted | start, end, benchmark, holdings_count | LIVE |
backtest_complete | A backtest returns successfully | trading_days, total_return_pct, benchmark | LIVE |
backtest_error | A backtest request fails | message | LIVE |
copy_code | The API code sample is copied | location | LIVE |
scroll_depth | Page scroll crosses 25 / 50 / 75 / 100% | percent | LIVE |
Requested events that don't apply here
The original tracking spec targeted a design-system documentation site. Two of its interactions have no equivalent surface in this trading app, so they are intentionally not implemented rather than added as dead code:
| Requested | Why it's N/A | Status |
|---|---|---|
| Copy-to-clipboard on code samples | Adapted: this app has one code sample (the API example), and copying it fires copy_code. | MAPPED |
| Filter / search on component listings | There is no component library or searchable listing in this app. | OMITTED |
Implementation
All events route through one small wrapper, so nothing is sent unless GA4 is configured:
function track(name, params) {
try { if (window.gtag) window.gtag("event", name, params || {}); }
catch (e) {}
}
// examples
track("backtest_run", { start, end, benchmark, holdings_count });
track("scroll_depth", { percent: 50 });
Scroll depth thresholds fire once per page load. Nav tracking is attached to every element carrying a data-nav attribute, so new links are covered by adding that attribute, with no extra JS.