Add the identify call
Connect anonymous behavior to real named users, plans, emails, and MRR.
Step 2
The identify() call
The script tag tracks anonymous clicks. The identify() call connects those clicks to real users like Febin Joseph on the Growth plan paying $49/month.
DropFix.identify('your-user-id', {
name: 'Febin Joseph',
email: 'Febin@example.com',
plan: 'growth',
mrr: 49,
signup_date: '2025-06-01',
trial_ends: '2025-06-22',
})Use your internal user's ID
The first argument must be your own stable user ID from your database of a specific user. Do not use an email address as the ID because emails can change.Where to call identify() — read this carefully
Put identify() in your root layout or auth provider. Do NOT put it inside the submit handler of your login form. This is the single most common DropFix install mistake, and it silently breaks tracking for every existing logged-in user.
Where you put identify()
Root layout / auth provider (correct)
What happens
Runs on every page load. Existing logged-in users are identified automatically the next time they visit. New tabs and refreshes work too.
Where you put identify()
Login form submit handler (wrong)
What happens
Only runs when a user explicitly logs in. Anyone already logged in when you ship will stay anonymous until they log out and back in.
| Where you put identify() | What happens |
|---|---|
| Root layout / auth provider (correct) | Runs on every page load. Existing logged-in users are identified automatically the next time they visit. New tabs and refreshes work too. |
| Login form submit handler (wrong) | Only runs when a user explicitly logs in. Anyone already logged in when you ship will stay anonymous until they log out and back in. |
Why this matters
Most of your users are already logged in when you install DropFix. If identify() is wired only to your login flow, none of them will appear as identified users — your dashboard will show events but no health scores, no signals, no win-back drafts. The fix is to put identify() somewhere that runs on every mount of your auth provider.Quick check
Open your app in a private/incognito window. Log in. Then open a fresh tab in the same private window and visit your app. If DropFix.identify() is wired correctly, that fresh tab should identify the user on load — without you doing anything. If it doesn't, your identify() is in the wrong place.Where to add it by framework
Framework
React / Next.js App Router
Where to add identify()
In root layout.tsx — useEffect watching user.id. Runs on every page load.
Framework
Next.js Pages Router
Where to add identify()
In pages/_app.tsx — useEffect watching the session. Runs on every page load.
Framework
Vue 3
Where to add identify()
In App.vue (or your auth store boot) — watch with { immediate: true } on user ID.
Framework
Svelte / SvelteKit
Where to add identify()
In +layout.svelte — reactive $: block tied to your user store, runs on every layout mount.
Framework
Angular
Where to add identify()
In your root AppComponent (or AuthService init), subscribe to your user observable. NOT only in the login() method.
Framework
Plain JavaScript
Where to add identify()
On every page load, after your auth check returns the user — not only after the login API call.
| Framework | Where to add identify() |
|---|---|
| React / Next.js App Router | In root layout.tsx — useEffect watching user.id. Runs on every page load. |
| Next.js Pages Router | In pages/_app.tsx — useEffect watching the session. Runs on every page load. |
| Vue 3 | In App.vue (or your auth store boot) — watch with { immediate: true } on user ID. |
| Svelte / SvelteKit | In +layout.svelte — reactive $: block tied to your user store, runs on every layout mount. |
| Angular | In your root AppComponent (or AuthService init), subscribe to your user observable. NOT only in the login() method. |
| Plain JavaScript | On every page load, after your auth check returns the user — not only after the login API call. |
Pattern, not location
Whatever framework you use, the rule is the same: identify() must run on every page load when a user is already authenticated, not only when they actively log in.Complete copy-paste examples
// IMPORTANT: put this in your ROOT LAYOUT or AUTH PROVIDER,
// NOT inside your login form's submit handler.
//
// Why? This effect runs on every page load. So when an
// already-logged-in user revisits your app (or opens a new
// tab), identify() fires automatically — they don't need to
// re-login. If you only call identify() on login submit, your
// existing users stay invisible to DropFix until they log out
// and log back in.
useEffect(() => {
if (!user) return
DropFix.identify(user.id, {
name: user.name,
email: user.email,
plan: user.plan || 'free',
mrr: user.mrr || 0,
signup_date: user.createdAt,
trial_ends: user.trialEndsAt || null,
})
}, [user?.id])// IMPORTANT: place this in App.vue (root) or your auth store
// boot logic — NOT inside your login form's submit handler.
//
// The "immediate: true" flag is critical: it makes the watcher
// fire on mount, so already-logged-in users get identified on
// every page load. Without it, existing users would not be
// tracked until they log out and back in.
watch(() => authStore.user?.id, (userId) => {
if (!userId) return
window.DropFix?.identify(userId, {
name: authStore.user.name,
email: authStore.user.email,
plan: authStore.user.plan,
mrr: authStore.user.mrr || 0,
signup_date: authStore.user.createdAt,
})
}, { immediate: true })Call reset() on logout
When a user logs out, call DropFix.reset() first. If you skip this, the next user on the same device can have activity mixed with the previous user.
// In your logout handler, call reset() first.
async function handleLogout() {
DropFix.reset()
await yourNormalLogout()
}What the fields mean
Field
user ID
Required?
Required
What to put here
Your internal user ID from your database. Same ID every time.
Field
name
Required?
Recommended
What to put here
User's full name. Used in email drafts, such as 'Hi Febin,'.
Field
Required?
Recommended
What to put here
User's email. Hashed before storage and never stored as plain text.
Field
plan
Required?
Recommended
What to put here
Their plan name as a string, such as trial, free, growth, or scale.
Field
mrr
Required?
Recommended
What to put here
Monthly revenue from this user in USD. Use 0 for free users.
Field
signup_date
Required?
Recommended
What to put here
ISO date when they signed up. Used for baseline building and trial tracking.
Field
trial_ends
Required?
Trial users only
What to put here
ISO date when their trial expires. Required for trial lifecycle automation.
| Field | Required? | What to put here |
|---|---|---|
| user ID | Required | Your internal user ID from your database. Same ID every time. |
| name | Recommended | User's full name. Used in email drafts, such as 'Hi Febin,'. |
| Recommended | User's email. Hashed before storage and never stored as plain text. | |
| plan | Recommended | Their plan name as a string, such as trial, free, growth, or scale. |
| mrr | Recommended | Monthly revenue from this user in USD. Use 0 for free users. |
| signup_date | Recommended | ISO date when they signed up. Used for baseline building and trial tracking. |
| trial_ends | Trial users only | ISO date when their trial expires. Required for trial lifecycle automation. |
Success check
After adding identify(), log in as a real user. Within 60 seconds, that user's name should appear in the dashboard with plan and MRR.