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 nameFires whenParametersStatus
nav_clickAny nav, footer, or CTA link is clickedlink_id, link_textLIVE
theme_toggleThe light/dark toggle is usedthemeLIVE
holding_addA position is added to the portfoliosymbol, weight_pctLIVE
holding_removeA position is removedsymbolLIVE
sample_portfolio_load"Load sample portfolio" is clickednoneLIVE
portfolio_clear"Clear all" is clickednoneLIVE
benchmark_changeThe benchmark dropdown value changesbenchmarkLIVE
backtest_runA backtest is submittedstart, end, benchmark, holdings_countLIVE
backtest_completeA backtest returns successfullytrading_days, total_return_pct, benchmarkLIVE
backtest_errorA backtest request failsmessageLIVE
copy_codeThe API code sample is copiedlocationLIVE
scroll_depthPage scroll crosses 25 / 50 / 75 / 100%percentLIVE

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:

RequestedWhy it's N/AStatus
Copy-to-clipboard on code samplesAdapted: this app has one code sample (the API example), and copying it fires copy_code.MAPPED
Filter / search on component listingsThere 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.