Skip to content

Clerk and other auth providers

Whoever creates the accounts, your site identifies and tracks where it learns that an account exists. This guide says where, for your own server’s accounts and for a provider such as Clerk, Auth0 or Supabase, then the optional webhook and two pitfalls. It builds on Track conversions, which gives the HTTP events API’s request.

Choose where to record the sign-up

  • Where your server creates its own record of the account, such as its user row after sign-up in Laravel, Rails, Django or WordPress: identify, then track there, through the HTTP events API, as Track conversions shows.
  • With no such place, as with a provider alone: from your server, at the new user’s first signed-in page load. Nothing is set up at the provider, but a user who never loads a signed-in page is missed.
  • Also in the provider’s user-created webhook, if you want every sign-up: it needs its endpoint added in the provider’s dashboard. Both paths use the id signup:<user id>, so a sign-up that both record counts once.

Whichever you choose, identify at every sign-in too, so that the person’s other devices link to the account.

Record the sign-up at the first signed-in page load

Where a page your server renders knows the signed-in user, it reads the user, from the provider, and the user’s creation time:

  1. At each sign-in and signed-in page load, your server posts an identity link from the request’s rc_vid cookie to the user’s id.
  2. The first time it shows a user created in the last seven days, it also tracks signup, with the id signup:<user id> and the user’s creation time as occurred_at. A user created in the week before the install is recorded at their next signed-in page load, dated when they signed up; an older user signed up before RoutingCat, and records no sign-up.

Read the user on the server, never from what the browser says, so a browser can only report its own user. Send the time as RFC 3339, or as Unix seconds: a provider that gives Unix milliseconds, as Clerk does, needs them converted, since a plain number is read as seconds. The id keeps one sign-up per user, however many browsers and page loads report it.

A static site whose sign-in runs in the browser, with no server of its own, identifies with the browser entry’s routingcat.identify() at each sign-in, and records the sign-up from the provider’s webhook, on a backend.

Add the user-created webhook

Optional. A webhook carries no visitor cookie, so the sign-up passes the visitor id to the provider, in the metadata it lets a sign-up set: with Clerk, unsafeMetadata, the only metadata Clerk lets a sign-up set; with Supabase, signUp’s options.data. OAuth sign-ups have no such field, so they rely on the first-load recording.

On the provider’s user-created event, your webhook posts an identity link with that visitor id, then tracks signup under the same id as the first-load recording, signup:<user id>, dated when the provider created the user. Add the endpoint in the provider’s dashboard, and verify each delivery with the provider’s signing secret before you post it.

Avoid two pitfalls

  • Verification on another device. When email verification finishes on another device, identify at account creation, on the first device: that browser is the visitor who saw your pages.
  • Callbacks posted from another site, such as Sign in with Apple’s form_post, arrive without RoutingCat’s cookies, which are SameSite=Lax, so an identity link there has no visitor id. Identify at the next page load instead. status reports such calls as identify without a visitor id.

Next