Back to Portfolio

Headline Goat: A/B testing in a single binary

A self-hosted A/B testing tool for headlines — one Go binary with embedded SQLite, no external dependencies. Add it to any site, test your copy, and get statistically significant results.

Posted by

Headline Goat mascot

Objectives

  • 🙋🏻‍♀️ Build the simplest possible A/B testing tool for headlines
  • 🙋🏻‍♀️ Zero external dependencies — no databases, no SaaS, no SDKs
  • 🙋🏻‍♀️ Statistically rigorous winner detection
  • 🙋🏻‍♀️ Works with any site — drop in a script tag and go

Results

  • ✅ Single 18MB Go binary — runs anywhere, deploys in seconds
  • ✅ Embedded SQLite — no Postgres, no Redis, no config
  • ✅ Wilson score intervals + z-test for significance
  • ✅ CLI + web dashboard for monitoring tests
  • ✅ In production on lansky.tech itself

Highlights

How It Works

Add data-hlg-name and data-hlg-variants attributes to any HTML element. Include the tiny client script. Headline Goat randomly assigns visitors to variants, tracks views and conversions, and tells you when it has a statistically significant winner. That's it.

Statistical Rigor

No premature "Winner!" declarations. Headline Goat uses Wilson score confidence intervals and two-proportion z-tests to only declare a winner at 95% confidence. It even estimates how long you need to wait based on your current traffic rate.

Dual Interface

Manage tests via CLI (hlg create, hlg status) or the built-in web dashboard. Every CLI command supports --json for automation. The dashboard is embedded in the binary — no separate frontend to deploy.

Bot Detection

The client-side script detects headless browsers, Cypress, Phantom, and other automated tools — filtering them from your test data so results reflect real human behavior.

Deploy Anywhere

Cross-compiled for Linux, macOS, and ARM. Ships with Docker support, systemd configs, and reverse proxy guides for Nginx, Caddy, and Cloudflare Tunnel. Install with a one-liner shell script.

Challenges and Solutions

Flash Prevention

The biggest UX challenge with client-side A/B testing is content flash — visitors briefly seeing the wrong variant before JavaScript kicks in. I solved this with a CSS-first strategy that hides variants until assignment completes, ensuring a seamless experience.

Single Binary Philosophy

Keeping everything in one binary (server, database, dashboard, client script) meant embedding assets at compile time and using SQLite in WAL mode for concurrent reads. The result: a tool you can audit in ~7,000 lines of Go.

Dogfooding in production

Headline Goat is running on this very site — the hero tagline you saw on the homepage is being A/B tested right now. I built this tool because existing A/B testing solutions were either too expensive, too complex, or required sending your data to a third party. Sometimes the best tool is the one you build yourself.