Three analytics tools on the site. One trackEvent() call. Ten event types tracked automatically - no changes to any component. Built it in 4.5 hours with Claude Code, along with OG images and SEO fixes.
The problem was obvious: prodfeat.ai kept growing, got a blog, CTA buttons, social links - almost a month in with zero analytics. Time to fix that.
What I did
Centralized module
Created analytics.ts - 38 lines of TypeScript. One function trackEvent(name, params). Internally it fires to three destinations:
// GA4
window.gtag('event', name, { ...params, send_to: GA4_ID })
// Yandex Metrica
window.ym(YM_ID, 'reachGoal', name, params)
// Vercel Analytics
track(name, strParams)
Components have no idea how many analytics tools are running underneath. Call trackEvent('cta_click', { label: 'Start' }) - it goes to GA4, Yandex Metrica, and Vercel simultaneously. Add a fourth service later - change only the module, zero component changes.
Event delegation instead of per-component wiring
Second file - analytics-events.ts. 132 lines. A single document.addEventListener('click') handles everything through CSS selectors and URL patterns.
One listener on document catches all clicks. Then a chain of checks:
- Click in
.sticky-nav? Sendnav_click - Button
.btn-primary? Sendcta_click - Link to
/blog/tag/*? Sendtag_click - External link? Detect the social network by domain or send
outbound_click
10 event types. Zero React component changes. Add a new button with class btn-primary - it’s tracked automatically.
Scroll depth for the blog is separate. Four thresholds (25%, 50%, 75%, 100%). The listener attaches only on /blog/* pages and removes itself after hitting 100%.
Why these three tools
Went with GA4 + Yandex Metrica + Vercel Analytics, even though GA4 alone would technically do the job.
- GA4 - the standard, free, event-based model. Downside: no heatmaps.
- Yandex Metrica - free heatmaps and session recordings. Microsoft Clarity does the same for free, but I’m more familiar with Metrica and it retains data longer.
- Vercel Analytics - cookieless, GDPR-friendly. Shows Core Web Vitals right in the Vercel dashboard.
Could have gone with just GA4 and Clarity for heatmaps. But I already know Metrica, and Vercel Analytics gives you performance data with no setup - it’s baked into the deployment. Three tools, each covering its own niche. One tool also rarely gives you fully accurate data - having multiple sources means you’re more likely to catch the real picture.
Result
analytics.ts - 38 lines. analytics-events.ts - 132 lines. 10 event types working with no manual wiring:
cta_click- CTA buttonsoutbound_click- external linkssocial_click- social networks (Telegram, YouTube, LinkedIn, GitHub, X)blog_post_click- click on a blog posttag_click- click on a tagnav_click- navigationguide_click,project_click,resource_click- landing page sectionsscroll_depth- scroll depth (25/50/75/100%)
What I learned
The first 40 minutes I tried going the React wrapper route for each button. withTracking(Button), withTracking(Link) - wrapped three components, realized I’d drown in it. Dropped it. Event delegation solved the whole thing 10x simpler - one listener on document instead of tracking code in every component. Add new elements - they get tracked automatically by CSS class.
I’d been skipping the centralized module on other projects. Every new analytics tool got pushed to “I’ll add it later.” When I finally built trackEvent() - I felt embarrassed I hadn’t done it sooner. Not sure yet whether to add Amplitude for product analytics - at 150 visitors a month, that’s overkill. I’ll revisit when traffic hits 2-3k.