Jan 14, 2026

Custom JSON Health Check Responses in ASP.NET Core

When building modern APIs, health checks are a common way to expose the status of your application. By default, ASP.NET Core health checks return a very minimal response (often just HTTP status codes). But what if you want to return a clean JSON payload that can easily be consumed by monitoring systems?

Step 1: Create a Custom JSON Response Writer

ASP.NET Core’s HealthCheckOptions allows us to plug in a custom ResponseWriter. Here’s one that outputs a JSON response containing the health status:

private async Task JsonResponseWriter(HttpContext context, HealthReport report)
{
    context.Response.ContentType = "application/json";
    await JsonSerializer.SerializeAsync(
        context.Response.Body,
        new { Status = report.Status.ToString() },
        new JsonSerializerOptions 
        { 
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase 
        }
    );
}

What this does:

  • Sets the response type to application/json.

  • Serializes an anonymous object containing the health check Status.

  • Uses camelCase naming to keep JSON consistent with API conventions.


Step 2: Hook the Writer into Health Checks

Now, wire up the health check middleware in your pipeline:

app.UseHealthChecks("/health", new HealthCheckOptions 
{ 
    ResponseWriter = JsonResponseWriter 
});

Explanation:

  • Requests to /health will trigger your health checks.

  • Instead of the default plain-text response, your JsonResponseWriter will return JSON like:

{
  "status": "Healthy"
}

Step 3: Configure Global JSON Options

To keep your entire API’s JSON responses consistent, configure the JsonSerializerOptions in Startup.cs (or Program.cs for minimal hosting):

services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.IgnoreNullValues = true;
        options.JsonSerializerOptions.WriteIndented = true;
    });


  • IgnoreNullValues = true → Null properties won’t clutter your responses.

  • WriteIndented = true → JSON output is more readable (great for debugging).

With this setup:

  • Hitting /health gives a clean JSON response.

  • All controllers return JSON using consistent formatting.

  • Monitoring tools can easily parse your app’s health status.

Example response:

{
  "status": "Healthy"
}

Conclusion

By adding a custom ResponseWriter and configuring global JSON options, you can make your ASP.NET Core health checks more API-friendly. This approach is simple, clean, and integrates seamlessly into modern monitoring setups like Kubernetes, Prometheus, or cloud load balancers.


Jan 12, 2026

Fixing Google Analytics Integration in a Next.js App

When I tried to add Google Analytics to my React/Next.js project, I used the GoogleTagManager React component with my GA4 tag ID:

    
<GoogleTagManager gtmId="G-XXXXXXXXXX" />
    
  

The build succeeded, but Analytics showed “No data received in past 48 hours.”

The Problem

Using the GoogleTagManager component with a GA4 ID (G-XXXXXXXXXX) only created a preload link in the <head>:

    
<link rel="preload" href="https://www.googletagmanager.com/gtm.js?id=G-XXXXXXXXXX" as="script"/>
    
  

This preload line fetched the script but did not initialize GA4 tracking. As a result, Google Analytics never received events.

The Solution

Instead of relying on the preload link, I injected the full GA4 snippet using Next.js’s next/script. This ensures the script loads after hydration and initializes correctly.

Sample Code

    
import Script from "next/script";

export default function Layout({ children }) {
  return (
    <html lang="en">
      <head>
        {/* Load GA4 script */}
        <Script
          src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"
          strategy="afterInteractive"
        />

        {/* Initialize GA4 */}
        <Script id="ga4-init" strategy="afterInteractive">
          {`
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', 'G-XXXXXXXXXX');
          `}
        </Script>
      </head>
      <body>{children}</body>
    </html>
  );
}
    
  

Replace G-XXXXXXXXXX with your own GA4 Measurement ID.

Key Takeaways

  • The GoogleTagManager React component with a GA4 ID only creates a preload link — it doesn’t initialize Analytics.
  • GA4 requires the full gtag.js snippet with initialization code.
  • Use next/script in Next.js for safe script injection.
  • Verify events in Analytics → Realtime after deployment.

👉 This adjustment solved the issue and got my Analytics dashboard flowing with data again.