Copy as markdown[View .md](https://docs.funnelfizz.com/concepts/tracking "View the raw markdown for this page")[Open in Claude](https://claude.ai/new?q=Read%20https%3A%2F%2Fdocs.funnelfizz.com%2Fconcepts%2Ftracking.md%20and%20help%20me%20with%20this%20FunnelFizz%20topic%3A%20Tracking%20%26%20identity "Open this page in Claude with context")[Open in ChatGPT](https://chat.openai.com/?q=Read%20https%3A%2F%2Fdocs.funnelfizz.com%2Fconcepts%2Ftracking.md%20and%20help%20me%20with%20this%20FunnelFizz%20topic%3A%20Tracking%20%26%20identity "Open this page in ChatGPT with context")

# Tracking & identity

For the snippet itself and how to install it, see [Getting Started → Install tracking](https://docs.funnelfizz.com/getting-started/install-tracking.md). This page is the model, how an anonymous pageview becomes a named, paying customer.

## The three identifiers[​](#the-three-identifiers "Direct link to The three identifiers")

FunnelFizz stitches three IDs together into one profile:

| ID                                | Source                                              | Lifetime              |
| --------------------------------- | --------------------------------------------------- | --------------------- |
| **Visitor ID** (`_fn_vid` cookie) | Tracker, on first pageview                          | 365 days, per browser |
| **User ID**                       | Your code, via `funnelfizz('identify', { userId })` | Permanent             |
| **Stripe customer ID** (`cus_…`)  | Stripe, on checkout                                 | Permanent             |

The point: a session that started anonymous on mobile gets tied to the desktop purchase three weeks later, automatically.

## How the stitch works[​](#how-the-stitch-works "Direct link to How the stitch works")

```
Day 1   Anonymous pageview      → vid_abc (new cookie)

Day 2   funnelfizz('identify',   → links vid_abc ↔ user_789

        { userId: 'user_789' })

Day 3   Stripe checkout          → matches email → links user_789 ↔ cus_xyz

Day 30  Same user, new device    → vid_new (different cookie)

        Logs in → identify       → links vid_new ↔ user_789

                                   Both vids now roll up to one profile
```

Reverse-stitching is intentional, events from before `identify` get re-attributed to the user once the link is established.

## The `identify` call[​](#the-identify-call "Direct link to the-identify-call")

The single most important call in your code:

```
funnelfizz('identify', {

  userId: 'user_789',          // userId or email — at least one is required

  email: 'sam@example.com',    // strongly recommended (drives cross-device merge)

  plan: 'pro',                 // optional custom traits

});
```

Email is the strongest merge key — when the same email appears on two visitor IDs (e.g. Chrome on desktop + Safari on phone), they merge into one profile. `userId` is also a merge key but is workspace-scoped and won't merge across devices unless your app sets it consistently.

Where to put it: right after signup, on every page after login (idempotent), and after any auth state change. Don't pass passwords, tokens, or any sensitive data.

We do **not** guess that two anonymous visitors on different devices are the same person. Without `identify`, anonymous sessions stay separate. Cross-device guessing without identity signals is how creepy tracking happens.

## Cross-subdomain identity[​](#cross-subdomain-identity "Direct link to Cross-subdomain identity")

For flat 2-label apex domains (`example.com`, `acme.io`, `mybiz.dev`), the snippet **auto-detects the apex and sets `_fn_vid` at the apex** — `app.example.com`, `docs.example.com`, etc. all share the same visitor cookie automatically.

For multi-label TLDs (`example.co.uk`, `mysite.com.au`) the auto-detect cannot tell where the apex ends, so it stays host-only. Set `data-cookie-domain` explicitly:

```
<script

  src="https://funnelfizz.com/track.js?t=YOUR_TOKEN"

  data-cookie-domain=".example.co.uk"

  async

></script>
```

If you want subdomains tracked **separately**, opt out of auto-detect with `data-cookie-domain="host"` — each origin gets its own visitor ID.

## Email handoff[​](#email-handoff "Direct link to Email handoff")

Tracked links in FunnelFizz emails carry a signed profile token (`?fn_ph=…`) so a click from a recipient's inbox stitches their profile to the visitor cookie on the landing page, even on a brand-new device. The script strips the token via `history.replaceState` so it doesn't leak.

## Journey events[​](#journey-events "Direct link to Journey events")

Every stage entry and conversion writes one journey event. FunnelFizz dedupes duplicates automatically, so retrying the same stage-entry call is safe.

## Profile journey view[​](#profile-journey-view "Direct link to Profile journey view")

On any profile's detail page:

```
2026-04-01 12:04  pageview          /                Reddit

2026-04-02 09:22  identify          user_789         sam@example.com

2026-04-05 14:10  stripe_checkout   cus_xyz → Pro    $9/mo trial

2026-04-12 22:30  subscription_active                paid

2026-05-12 22:30  subscription_canceled              churned
```

The dashboard shows aggregates. The journey is the raw trace.

## Privacy[​](#privacy "Direct link to Privacy")

* No third-party tracking. FunnelFizz never sells data.
* `navigator.doNotTrack` is honored, DNT visitors send nothing.
* Profile tokens in URLs are HMAC-signed server-side.
* For GDPR/CCPA, defer the snippet until your CMP grants "analytics" consent.

Full policy at [funnelfizz.com/privacy](https://funnelfizz.com/privacy).
