Auth0
Conversion tracking is available on the Business plan and above .
In conversion tracking, a lead event is an
action that signals interest in your product:
- signing up for an account;
- booking a demo;
- joining a mailing list.
The lead event establishes the customer’s identity and the link they came from: every later action (a purchase, a plan upgrade) is attributed to that same link.
In this guide, we will be focusing on tracking new user sign-ups for a SaaS application that uses Auth0 for user authentication.
Prerequisites
First, enable conversion tracking for your links — without it a click is never linked to the lead and sale events that follow.
You can skip this step for partner program links: RevRoute enables conversion tracking on them automatically.
For the whole workspace. Open Settings → Analytics and turn on the Conversion tracking switch in the page header — it controls the workspace-level setting. Every link created from that point on has conversion tracking enabled.
For a single link. Open the
link builder and turn
on the Conversion tracking switch — inside the builder it is also bound to
the C keyboard shortcut.
Via the API. Pass trackConversion: true when creating or updating a link
(it defaults to false):
curl -X POST "https://api.revroute.ru/links" \
-H "Authorization: Bearer rr_xxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"trackConversion": true
}'Then install the RevRoute client-side script on your site — it records the click and stores its ID, which is what lead events are attached to.
The RevRoute client-side script is served from our domain — there are no npm
packages to install. It picks up the rr_id query parameter, stores it in a
first-party rr_id cookie on your domain (90 days) and uses it to attribute
future conversions to the original link.
Add the tag to the <head> section of every page on your site:
<script defer src="https://app.revroute.ru/analytics/script.js"></script>In Next.js (App Router), use next/script in the root layout:
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
<Script defer src="https://app.revroute.ru/analytics/script.js" />
</html>
);
}You can verify the installation in two ways:
- Open the browser console and type
_revRouteAnalytics— if the script is installed, the object shows up in the console. - Add the
?rr_id=testquery parameter to your site URL and check that therr_idcookie is set in your browser.
If neither works, make sure that:
- the script tag sits in the
<head>section of the page; - any CDN cache in front of your site has been purged.
The server-side client
The examples below use the TypeScript SDK from the dub npm package. Always
pass the RevRoute API serverURL to the client — without it the SDK will not
talk to our API.
npm install dubimport { Dub } from "dub";
export const revroute = new Dub({
token: process.env.REVROUTE_API_KEY, // secret rr_* key from your workspace settings
serverURL: "https://api.revroute.ru", // required: the RevRoute API address
});Keep the secret key (rr_*) in environment variables and never expose it to
the browser. Create one under API keys .
The SDK is optional: /track/lead and /track/sale are plain HTTPS endpoints
you can call from any language.
Configure Auth0
Next, configure Auth0 to track lead conversion events.
Here’s how it works in a nutshell:
- In the sign in
afterCallbackfunction, check if the user is a new sign up. - If the user is a new sign up, check if the
rr_idcookie is present. - If the
rr_idcookie is present, send a lead event to RevRoute usingrevroute.track.lead - Delete the
rr_idcookie.
import { handleAuth, handleCallback, type Session } from "@auth0/nextjs-auth0";
import { cookies } from "next/headers";
import { revroute } from "@/lib/revroute";
const afterCallback = async (req: Request, session: Session) => {
const userExists = await getUser(session.user.email);
if (!userExists) {
createUser(session.user);
// check if rr_id cookie is present
const clickId = cookies().get("rr_id")?.value;
if (clickId) {
// send lead event to RevRoute
await revroute.track.lead({
clickId,
eventName: "Sign Up",
customerExternalId: session.user.id,
customerName: session.user.name,
customerEmail: session.user.email,
customerAvatar: session.user.image,
});
// delete the rr_id cookie
cookies().set("rr_id", "", {
expires: new Date(0),
});
}
return session;
}
};
export default handleAuth({
callback: handleCallback({ afterCallback }),
});Request fields for POST /track/lead:
| Field | Required | Description |
|---|---|---|
clickId | Yes | ID of the click the lead is attributed to. Read it from the rr_id cookie. For a deferred lead an empty string is allowed — the click is then taken from the customer found by customerExternalId. |
eventName | Yes | Name of the event (e.g. Sign up). It also ties the lead to a later sale through leadEventName in /track/sale. |
customerExternalId | Yes | The customer’s ID in your system. All future events for this customer are attributed through it. |
discountCode | No | The partner’s discount code, for customers who arrive without clicking a link. If both clickId and discountCode are sent, clickId wins. |
customerName | No | Customer name. If omitted, a random one is generated. |
customerEmail | No | Customer email. |
customerAvatar | No | Customer avatar URL. |
mode | No | async (default) — don’t block the request; wait — block until the event is recorded; deferred — defer lead creation to a later request. |
eventQuantity | No | Numeric value of the event (e.g. seats provisioned in a trial): the lead is counted that many times. |
metadata | No | Arbitrary event data, up to 10,000 characters when stringified. |
Where to see conversions
Once everything is set up, tracked conversions show up in your workspace analytics in three views:
- Time series — clicks, leads and sales over time: Analytics .
- Funnel — conversion and drop-off at every step (clicks → leads → sales): Analytics in funnel mode .
- Events stream — every conversion event across all links in the workspace, in real time: Events .