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
- JavaScript SDK — full method reference
- SaaS events — the
track()-based flow that works today - Privacy Policy — how identifiers are stored and deleted