Should you just build attribution yourself?
You absolutely can — we did. Here is the honest scope: every part that looks trivial, every part that isn't, and the maintenance nobody estimates.
cookie + events table ≈ 2 days · a system you trust ≈ 6–10 weeks + forever
The first version takes a weekend and works. The version that survives redirects, bots, retries, de-duplication, identity merges, timezone-correct reporting and a sceptical CFO is a quarter of engineering plus permanent ownership.
If you are a technical team with an unusual data model, building is often correct — and this page is the scope document.
You can build this. It is not magic, there is no proprietary algorithm, and the data model is four tables. We built it, which is why we can be specific about what it costs.
The weekend version (and it works)
visitors(id, anonymous_id, first_touch_*, last_touch_*, person_id)
events(id, visitor_id, name, source, category, occurred_at, properties)
people(id, email, identified_at, identified_via)
conversions(id, visitor_id, person_id, value_cents, dedup_key, occurred_at)
Plus four pieces of code:
- A
before_actionthat mints a UUID and sets it in a first-partySet-Cookie— durable, HttpOnly, two years. This single step puts you ahead of most instrumented sites on the internet. - UTM and click-id capture on the landing request, written to the visitor as first touch if empty and last touch always.
- An identify call that binds an email to the visitor when someone signs up or subscribes.
- A conversion write from your payment webhook.
Two days of work. Genuinely useful. If your business is simple and your team is technical, this may be all you ever need — and you should build it rather than buy anything.
Then the tail
The gap between “it works” and “I would put this in a board deck” is where the estimate goes wrong:
Bots. Crawlers, uptime monitors, link previewers, prefetches, your own team. Your visitor count is wrong by a humiliating margin until this is handled, and you will find out in a meeting.
Turbo, SPAs and prefetch. Client-side navigation is not a document load. Speculative prefetch is not a visit. Both silently corrupt counts in opposite directions.
Redirect chains. UTMs get stripped by shorteners, 301s and consent flows. Capture has to happen on the first landing request or you lose the campaign entirely.
De-duplication. Client and server both report the purchase. Without a shared business key you double count; with a badly chosen key you drop real sales. Then webhooks retry and you need idempotency anyway.
Identity merges. One person, two devices, two anonymous ids, one email — arriving out of order. Merging correctly and idempotently is the single hardest part of the whole system, and it produces subtle wrong-number bugs for months after you think it is done.
Time. Timezones, day boundaries, “last 30 days” meaning three different things to three stakeholders, and the fact that late-arriving server events change yesterday’s totals after you already reported them.
Volume. The events table is the fastest-growing table you own. Indexes, partitioning, and denormalising first-touch onto the visitor so reporting does not need a join.
Reporting. Grouped aggregates, first vs last touch, ad spend joins, CAC and ROAS, and a UI someone will actually open.
The debugging surface. When a number looks wrong — and it will — you need a way to inspect one visitor’s raw event stream. Most homegrown systems skip this, and it is the feature you need most in the exact meeting where the numbers are challenged.
Six to ten weeks of focused engineering, in our experience, plus permanent ownership.
The honest comparison
| Build it yourself | Flowsk Signals | |
|---|---|---|
| Initial cost | 6–10 weeks of engineering | $29 / mo |
| Ongoing cost | Whoever owns it, forever | $29 / mo |
| Data ownership | Total | Yours, exportable |
| Fits your exact model | Perfectly | Generic |
| Bots, de-dup, merges, prefetch | You solve all of it | Solved |
| Journey explorer for debugging | You build it | Included |
| New browser policy next year | Your problem | Ours |
Build if
- Your data model is genuinely unusual and no product fits it.
- You already have a warehouse and a data team, so this is modelling rather than infrastructure.
- Attribution is close enough to your core product that owning it is strategic.
- You have a specific reason no third party may hold the data.
Buy if
- You want an answer this month rather than next quarter.
- Your engineers have higher-leverage work than bot filtering.
- You want the debugging surface without building it.
- $29 is less than the meeting you had about this.
What we would tell an engineer
Build the two-day version this week regardless. The server-set cookie plus UTM capture plus a conversion write from your webhook is a genuine upgrade over anything client-side, and you will understand the problem far better afterwards.
Then decide whether the remaining ninety percent is your best use of a quarter. Our Rails guide shows exactly how we do it in our own app — including the isolation boundary between the product and the dogfooding, which is the design decision we would most want to keep if we were starting again.
Frequently asked questions
What is the minimum viable build?
A server-set first-party cookie, an events table with (visitor_id, name, occurred_at, properties), UTM capture on the landing request, and a conversion write from your payment webhook. That genuinely works and takes a couple of days.
What breaks first?
Bots. Your visitor count will be wrong by an embarrassing margin until you filter crawlers, prefetches, uptime monitors and your own staff. Everyone discovers this the same way — by presenting a number that is 40% noise.
What is the hardest part?
Identity merges. One person, two devices, two anonymous ids, one email. Merging them correctly — and idempotently, when the events arrive out of order — is the part that eats a fortnight and produces subtle bugs for months.
Should I build if I already have a data warehouse?
It is much more attractive, yes. The events are already flowing and you have SQL people. The work becomes modelling rather than infrastructure, which is a far better trade.
You built it. Why should I buy yours instead?
Because we already paid the six weeks and the tail of bugs after it. If your data model is genuinely unusual, build — you will end up with something better shaped for you than any product.
Start with the measurement, not the build
Price what your current setup is losing before you scope anything. It is the number that tells you whether this is a weekend or a quarter.
Stop guessing which ad made the sale.
Flowsk Signals stitches the anonymous click to the email to the purchase — first-party, server-side, de-duplicated. One snippet, $29/mo, and every conversion comes with a receipt you can inspect.