First-party attribution for Ruby on Rails
Rails has everything the problem needs: a request cycle you own, cookies you can set server-side, background jobs for the ingestion, and a database that already knows who the user is. This is the stack where first-party attribution is genuinely easy — flowsk.com itself runs exactly this way.
Durable id (server-set) + client events (behaviour) + server events (truth) + dedup key
A concern sets the id cookie and records pageviews; model callbacks confirm identification and purchases. The one decision that matters on Ruby on Rails: who writes the visitor id. Written by JavaScript it lives 7 days in Safari; written by a server it lasts as long as you set it.
A `Trackable` concern with a `before_action` is all it takes: read or mint the id, set the cookie, enqueue the pageview job.
What Ruby on Rails gives you for free
Every stack has a natural advantage for first-party measurement. Use it before reaching for a tag manager.
`cookies.encrypted` / `cookies` in a `before_action` gives you a durable server-set id in three lines
Active Job keeps ingestion off the request cycle
Your models already know the email and the payment — the authoritative events are right there
What breaks on Ruby on Rails
The failure modes specific to this stack — the ones a generic install guide will not warn you about.
Turbo navigations are not document loads
Turbo Drive swaps the body without a full load, so a load-only pageview handler undercounts.
Fix Listen for `turbo:load` as well as `DOMContentLoaded`.
Cookies in API-only controllers
`ActionController::API` has no cookie middleware by default.
Fix Include `ActionController::Cookies` where you need the id.
Webhook idempotency
Payment webhooks retry. Without a de-duplication key you will record the same purchase several times.
Fix Use the payment intent or subscription id as the dedup key.
Frequently asked questions
How do I set a durable first-party cookie in Rails?
In a `before_action`: `cookies[:_fsk_id] ||= { value: SecureRandom.uuid, expires: 2.years.from_now, httponly: true, same_site: :lax }`. Because Rails writes it in the response, Safari's 7-day JavaScript cap does not apply.
How do I record pageviews without slowing requests down?
Enqueue an Active Job from the `before_action` and return immediately. The ingestion happens off the request cycle.
How do I handle Turbo navigations?
Server-side pageviews already work — every Turbo Drive navigation is still a real GET to your server. That is one more reason the server-side approach is more accurate on Hotwire apps than a client tag.
How does flowsk dogfood this?
`Signals::Internal` sets the `_fsk_id` cookie server-side and calls the same public `Signals::Client` facade our customers' API calls go through — no shortcuts into the internals. See docs/attribution_product.md.
Related guides
See the receipt for every conversion.
Flowsk Signals stitches the anonymous click to the email to the purchase — first-party, server-side, de-duplicated on a key you choose. One snippet, $29/mo, and a journey you can inspect event by event.
More free tools
Same deal — instant, no signup.