All posts
Data Platform

First-Party Analytics on AWS for a Few Dollars a Month: The Pipeline Behind This Site

By

October 26, 2026

9 min read

A visitor id, a session id and a page view id; a collector on our own domain; Firehose into S3; Athena with saved queries. How we built analytics that ad blockers do not drop, nobody else holds, and that costs less than a coffee at our traffic, and the three bugs we found on the way.

Analytics
Amazon Data Firehose
Athena
S3
First-party data

Why build it at all

Hosted analytics is the right answer for many sites. We built our own for three reasons that apply to a lot of B2B companies: a meaningful share of a technical audience blocks third-party trackers, we wanted the raw events next to our own data rather than in a dashboard we rent, and at our traffic a serverless pipeline costs almost nothing. It is the same design we deploy for clients, so it also had to be something we would trust there.

Three ids hold it together

Id

What it identifies

How long it lives

Visitor (distinct_id)

A browser, before anyone signs in — and after, alongside the user id

Two years, in a first-party cookie on the parent domain, renewed on each visit

Session (session_id)

A visit: activity with no gap longer than thirty minutes

Slides with each event; a second tab is the same visit

Page view (page_view_id)

One page being looked at

Carried on every click and form event from that page

The page view id is the one most setups skip and the one that answers the most useful question — which page, and which button on it, a lead came from — as a join rather than a guess from timestamps. Campaign tags (utm_* and ad click ids) are read once on arrival and stamped on every event in the visit.

Want a second opinion on this for your system?

Book a free 30-minute call. You'll leave knowing what we'd do first and roughly what it costs, whether or not you hire us.

The collector

A Lambda function behind CloudFront at /v1/events on the site's own domain. Same origin means no CORS and nothing for third-party blocklists to match. It checks the write key before reading the body, validates each event on its own so one bad event never costs the batch, stamps the project and the time it received the event from its own clock — never from the payload — and sends good events to Firehose and bad ones to a quarantine prefix in S3 where they can be inspected.

Storage and queries

Firehose buffers for five minutes and writes gzipped, newline-delimited JSON into S3 under a date prefix. A Glue table with partition projection makes each day queryable the moment it lands, with no crawler. Athena runs saved queries: visits and visitors by day, landing pages by source, clicks toward booking, visits by channel (search, AI assistants, social, paid, email, direct) and experiment results with a confidence range. Duplicates — Firehose can deliver a batch twice — are removed in the queries by event id.

Three bugs we found building it

  1. Anything tracked before the analytics code finished loading was silently lost — including the first page of every visit's content events. Calls now queue until the provider is ready, with page views flushed first so the events after them carry the right page view id.

  2. Nothing that does not run JavaScript could read the site. The pages were a single-page app; crawlers and AI assistants received an empty shell. Every page is now prerendered at build time.

  3. Dates written as 2026-10-24 displayed as October 23 for every visitor west of London, because a bare date parses as midnight UTC. Small, embarrassing, and invisible from the developer's own time zone.

None of these showed up in tests. All three showed up within minutes of driving the real site in a browser and reading what the collector received — which is the habit we would recommend to anyone building tracking: look at the events, not the dashboard.

hoolco Monthly Review

Once a month: what changed in tech that month and what it means for you, from cloud and AI to security and the tools you build with. Every item links to its source. No sales pitch, unsubscribe in one click.

As of October 26, 2026. Provided as is, for general information, and accurate to the best of our knowledge on the date shown. Not legal, compliance, tax, financial or other professional advice. Prices, limits and vendor services change; check current vendor documentation before relying on anything here. Terms of use.