Revenue attribution · first-touch · Stripe, read-only
Know which channel produces customers.
Not just visitors.
Every analytics tool can rank where your traffic comes from. The question a business actually needs answered is which of those channels produced the people who pay — and the channel sending the most visitors is very often not the one sending the most customers.
What the attribution report answers
Example figures
Channels
Sorted by MRR — deliberatelySorted by money rather than by visitors, because sorting by visitors reliably puts the channel that sends crowds at the top — here, the search traffic — while the channel that sends customers sits three rows down looking small.
Two ledgers, joined only on a channel name
The traffic ledger stays anonymous
Visits are counted the way Tastatur always counts them: no cookies, nothing stored on the device, a visitor identifier that stops working after 24 hours. The referrer is kept as a hostname only and classified into a channel the moment it is written.
The revenue ledger is your own customer data
Customers, subscriptions and payments are data your application already holds. Your server sends them to Tastatur directly — authenticated, server-to-server, under your own relationship with your customers. Email addresses are hashed on receipt and never stored in the clear.
There is no column joining the two. Nothing links a customer to a visitor identifier — not at collection, not later. The two ledgers meet only in the report, on channel names: all the visitors on one side, all the money on the other. That is a design constraint, not a limitation we apologise for, and because the source is AGPL-3.0 you can verify it rather than take our word.
The integration, in three steps
The browser knows where somebody came from; the payment happens somewhere else, possibly days later, possibly on another device. With nothing stored on the visitor's device there is no cookie to join the two — so the attribution travels with the signup and the payment instead.
1. Capture the first touch on the landing page. Reads the campaign tags and referrer of the current visit. Store it in your own form state or user record — calling it at the end of your funnel would read your own checkout as the traffic source.
const attribution = tastatur.attribution()
// { source, medium, campaign, landing_path, referrer_host, first_seen_at }
2. Send it when they sign up, from your server, with an API key from your site's settings. The email is hashed on receipt.
POST https://tastatur.dev/api/v1/identify
Authorization: Bearer tk_...
Content-Type: application/json
{
"external_id": "user_9182",
"email": "[email protected]",
"attribution": { "source": "reddit", "medium": "social", "landing_path": "/pricing" }
}
3. Attach it to Stripe Checkout. This is what makes attribution survive a closed tab, or a payment finished three days later on a phone: the first touch rides inside the checkout session's metadata and comes back to us on the payment webhook.
stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [...],
client_reference_id: user.id,
metadata: tastatur.checkoutMetadata(attribution)
})
First touch wins, and is never overwritten. Your app calls identify on every sign-in, so a last-write-wins design would re-attribute January's Reddit customer to whatever they searched in March — and every paid channel would decay towards "Direct" on its own. Attribution is written once; only an earlier first touch can amend it.
Connect Stripe, read-only
Connecting Stripe imports your history and keeps revenue flowing in as it happens — subscriptions, invoices, refunds, disputes. The connection is a Stripe App whose permissions are all read: Stripe shows you each one, item by item, before you install, and its review process pins the list. There is no code path here that writes to a connected Stripe account, and no access token is stored on our side — you can disconnect from either end, and revenue already recorded stays yours to keep or erase.
read
the only kind of permission the app asks for
0
access tokens stored on our side
2 yrs
of history imported on connect
1 click
to disconnect, from either end
Said plainly
This part of Tastatur is not anonymous, and does not pretend to be. A customer record carries the identifier your app assigned, a hashed email, and a first-touch channel. That is data your application already holds about somebody who signed up for it, confined to five tables, deletable when you say so.
Your visitors are not in it. Someone who browses and never signs up exists only in the anonymous ledger, under an identifier that stopped working the day they visited.
Revenue never appears on a public shared dashboard. A shared link shows traffic, never money. Publishing MRR to an unguessable-but-public URL is not something anybody should be one checkbox away from.
It works self-hosted. Revenue attribution is deliberately not tied to our billing: it is about whether you can connect your processor, not whether we can charge you.