Setup
Three steps. The first two show you the journey; the third adds payments.
1. The snippet
On your website and in your app, in the <head>. Your key is on the Setup page of the dashboard.
<script src="https://userjourney.dev/uj.js" data-key="pk_…" defer></script>
Page views in single-page apps are picked up from route changes. Visitors are counted without cookies or local storage.
2. Identify
After sign-up and on every page load while someone is signed in. The first call is their sign-up, credited to the visit that brought them that day or the day before.
uj.identify(user.id, { email: user.email, name: user.name })
Call uj.reset() when they sign out.
Onboarding and activation
Pages under /onboarding/<step>, /setup/<step>, /welcome/<step> or /get-started/<step> count as steps on their own. Otherwise, one line per step:
uj.step("connect_repo") uj.activated() // optional: their "aha" moment uj.track("invited_team") // optional: anything else for their timeline
By default someone is activated when they finish your onboarding steps. You can choose a page or an event instead in Setup.
3. Paddle and Stripe
In the dashboard, paste an API key: userjourney creates the webhook in your account and forgets the key. Or add the webhook by hand and paste its signing secret.
Customers are matched by email. To be exact even when someone pays with another address, pass their id at checkout:
// Paddle Paddle.Checkout.open({ items: [{ priceId: "pri_…" }], customData: { uj_id: uj.id() } }) // Stripe Checkout client_reference_id: uj.id()
From your backend
The same events with your secret key, for steps that happen on the server. Never put the secret key in the browser.
curl https://userjourney.dev/api/v1/server \ -H "Authorization: Bearer sk_…" \ -d '{"u":"user-42","e":[{"t":"step","n":"first_import"}]}'
Stages
Signed up → Onboarding → Activated → Trial → Paying. People who stop before activating move to Stuck (24 h without progress by default). Paying customers who stop coming move to At risk (7 days); cancellations and long absences are Churned. Payments always win: someone who pays is paying, whatever they clicked.
Privacy
Anonymous visitors are counted with a hash of a salt that changes every day, the site, the IP address and the browser. The hash is deleted after two days and never stored with anything about the person; no cookies or device storage are used, so no consent banner is needed for it. Signed-in users are your customers: you send us their id and, if you choose, their email and name, to show you their journey and send the emails you turned on. Data is kept 400 days. Every playbook email has a one-click unsubscribe.