User identification

PennyLens.identify() is part of the SDK today, but it's currently a client-side, in-memory call only — the user ID and traits you pass aren't transmitted to PennyLens or attached to any event. Anonymous→known stitching, cross-device identity, and per-user journeys are on the roadmap, not live yet.

This page covers exactly what identify() does today, and the patterns that already work end-to-end without it.

What identify() does today

PennyLens.identify("user-7281", {
  email: "alex@example.com",
  plan: "pro",
});

Calling this stores the user ID and traits on the tracker instance for the current page load. It does not:

  • Attach the user ID or traits to any event sent to PennyLens
  • Retroactively re-attribute events captured earlier in the session
  • Persist across a page reload, a new tab, or a future session
  • Merge anonymous history across devices

It's safe to call today — nothing breaks — but treat it as a no-op for analytics purposes until server-side identity ships. This page will be rewritten when it does.

What works today instead

Every event is attributed to an anonymous, rotating visitor_id (stored in localStorage, never a cookie) and a session_id, automatically, with no identify() call required. Two patterns already work end-to-end on real data:

Reserved SaaS lifecycle events

track() calls using PennyLens's reserved event names drive real, aggregate detectors — activation gap, time-to-value, trial conversion, D7 retention, and churn risk — without any per-user identity:

pennylens.track("signup");
pennylens.track("first_action", { feature: "created_first_project" });
pennylens.track("core_feature_used", { feature: "invited_teammate" });

See SaaS events for the full reserved-event reference.

Order-webhook identity for e-commerce

For Shopify stores, connecting the order-creation webhook (see Shopify auto-detect) attaches a hashed customer identity to purchase events server-side — the reliable, working path for per-customer purchase attribution today, independent of client-side identify().

Traits (reserved for when server-side identity ships)

The second argument to identify() is a property bag. The SDK accepts and validates it, but nothing is currently stored or displayed in the dashboard from it.

| Convention | Example | Status | | --- | --- | --- | | email | "alex@example.com" | Accepted, not yet stored. | | name | "Alex Rivera" | Accepted, not yet stored. | | plan | "pro" | Accepted, not yet stored. | | created_at | ISO 8601 string | Accepted, not yet stored. |

Roadmap

Server-side identity — attaching identify() traits to events, retroactive session stitching, and cross-device merging — is on the PennyLens roadmap. Until then, build on the reserved-event patterns above; they're what the dashboard's SaaS and e-commerce detectors actually read.

Next steps