GA4 Content Engagement Metrics for Developers: Moving Beyond Page Views
Page views are a lying metric. They tell you someone loaded a URL, but they do not tell you if that person read your content, copied a code block, or closed the tab in disgust. For developers and indie founders building in public, optimizing for raw traffic is a waste of engineering time. You need to measure high-intent engagement.
Over the past week, I pushed 65 commits to my personal site repository (rishh-website) and 17 commits to my automated data aggregator (brand-bot). A major focus of this sprint was solving a core strategic problem: how to stop guessing which technical articles actually drive product signups and start measuring it programmatically.
By integrating Google Analytics 4 (GA4) directly into a markdown-based publishing workflow, you can move past vanity metrics and capture the precise moments a reader transitions from a passive browser to an active user.
Why Page Views Mislead Technical Founders
A high page view count does not correlate with product adoption. On my personal site, rishh.com, the Search Console data shows highly specific intent but low click-through rates for unoptimized content. For example, over the last 30 days, the query "rishh" generated 34 impressions and 0 clicks, while the root domain https://rishh.com/ pulled in 1 click.
More telling are the blog posts for my personal finance app, Vitta:
https://rishh.com/vitta/blog/festive-gifting-budget-vitta-app/— 0 clickshttps://rishh.com/vitta/blog/manage-cash-expenses-with-vitta/— 0 clickshttps://rishh.com/vitta/blog/managing-irregular-income-for-indian-freelancers/— 0 clicks
Without custom engagement tracking, these zeroes look like a total failure. But if a single user landed on the irregular income piece via an external community link, read 90% of the page, and then downloaded the app, that post was highly successful. Standard GA4 out-of-the-box tracking won't show you this. It logs a session start and nothing else.
Contrast this with the metrics for my AI resume tailoring tool, SwitchWithAI. In the last 7 days, the GA4 top pages report shows:
/login— 58 sessions / 57 users/— 28 sessions / 25 users/blog— 24 sessions / 24 users/tailor— 19 sessions / 19 users/pricing— 18 sessions / 18 users
The blog traffic (/blog with 24 sessions) is nearly equal to the landing page traffic (/ with 28 sessions). To optimize this funnel, I need to know if the people reading the blog are the same ones hitting /login or /pricing. If you cannot tie blog engagement directly to app conversions, you are writing content in the dark.
How to Integrate GA4 into a Markdown Publishing Workflow
If your blog is built like mine—using static markdown files parsed into React or HTML—you can automate the injection of custom GA4 tracking parameters directly from your YAML front matter. This allows you to categorize posts, track reading depth, and measure feature clicks without writing custom JS for every new page.
Here is the TypeScript implementation I use to initialize GA4, parse page metadata, and track custom engagement events like code block copies and scroll milestones.
// analytics.ts
import { useEffect } from 'react';
interface BlogPostMetadata {
title: string;
category: string;
wordCount: number;
}
export const initGA = (measurementId: string) => {
if (typeof window === 'undefined') return;
const script = document.createElement('script');
script.async = true;
script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
document.head.appendChild(script);
window.dataLayer = window.dataLayer || [];
window.gtag = function () {
window.dataLayer.push(arguments);
};
window.gtag('js', new Date());
window.gtag('config', measurementId, {
send_page_view: false // Handled manually for SPA routing
});
};
export const trackPageView = (url: string, meta: BlogPostMetadata) => {
if (typeof window === 'undefined' || !window.gtag) return;
window.gtag('event', 'page_view', {
page_path: url,
page_title: meta.title,
content_category: meta.category,
word_count: meta.wordCount,
});
};
export const useScrollTracking = (title: string) => {
useEffect(() => {
if (typeof window === 'undefined' || !window.gtag) return;
const milestones = [25, 50, 75, 90];
const trackedMilestones = new Set<number>();
const handleScroll = () => {
const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollTop = window.scrollY;
const scrollPercentage = Math.round((scrollTop / scrollHeight) * 100);
milestones.forEach((milestone) => {
if (scrollPercentage >= milestone && !trackedMilestones.has(milestone)) {
trackedMilestones.add(milestone);
window.gtag!('event', 'content_scroll_depth', {
post_title: title,
depth_percentage: milestone,
});
}
});
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [title]);
};
export const trackCodeCopy = (title: string, codeSnippet: string) => {
if (typeof window === 'undefined' || !window.gtag) return;
window.gtag('event', 'code_copy', {
post_title: title,
code_length: codeSnippet.length,
});
};
This setup ensures that every time a developer copies a code block or scrolls past 90% of a deep-dive technical post, GA4 records a custom event. You can then map these events to conversion goals in the Google Analytics dashboard.
Measuring What Matters: Custom Events vs. Page Views
Standard GA4 implementations track "user engagement" using a metric called user_engagement, which fires periodically when the tab is active. For technical blogs, this is insufficient. You need custom event telemetry to capture actual developer utility.
1. Scroll Depth Milestones
A user who lands on a technical tutorial and bounces immediately has a low dwell time. But a user who scrolls to 90% is highly engaged. By tracking milestones at 25%, 50%, 75%, and 90%, you can pinpoint exactly where readers lose interest. If 80% of your readers drop off at the 50% mark, your code explanation is likely too dense or your repository links are missing.
2. Code Block Interaction
Developers do not read blog posts like novels; they scan for the code block, copy it, and paste it into their IDE. Tracking code copies using the trackCodeCopy function shown above tells you which specific code snippets are solving real problems for your users.
3. Cross-Domain Funnel Attrition
If you run a blog on rishh.com but your product lives on switchwithai.com, standard GA4 cookies will treat a user navigating between them as two separate individuals. You must configure cross-domain tracking in your GA4 Admin panel under Data Streams > Configure Tag Settings > Configure Your Domains. This links the user identity across domains, allowing you to prove that a blog post on resume optimization directly caused a /login conversion on SwitchWithAI.
The Strategy Behind Engineering Your Content
As an engineer completing an MBA, I look at every line of code through the lens of return on investment. Writing technical tutorials takes hours of deep focus. If those hours do not result in measurable brand equity, newsletter signups, or SaaS trial registrations, the code is a liability.
By treating your publishing pipeline as an engineering system—complete with event listeners, telemetry, and conversion funnels—you turn content generation from a guessing game into a predictable growth engine. You stop focusing on ranking for high-volume, low-intent search terms and start optimizing for the exact user path that leads to product adoption.
If you want to read more about how I build and scale technical products, check out my guide on Why I Chose Firebase/Supabase Over AWS Cognito for My Indie SaaS.