Track user behavior from first visit through signup and beyond.
Analytics
AscendKit Analytics captures the full user journey — from the first anonymous page visit through signup, onboarding, and beyond. No configuration required: install the SDK and analytics starts automatically.
How it works
Auto-collection (zero config)
When the AscendKit SDK is installed, it automatically collects:
- Pageviews — every page visit, including SPA route changes
- Device info — browser, OS, device type
- Geography — country, region, city (derived from IP — raw IP is never stored)
- Referrer & UTM — where the visitor came from, campaign parameters
- Session tracking — pageviews grouped into visits (30-minute inactivity timeout)
This happens for ALL visitors — including anonymous ones who haven't signed up yet.
Anonymous → Identified stitching
Every visitor gets a vis_ ID via a first-party cookie. When they sign up or log in, AscendKit automatically links their pre-signup browsing history to their user record:
- Visitor browses your site (tracked under
vis_ID) - Visitor signs up → AscendKit creates
usr_record - All pre-signup pageviews and sessions are retroactively linked
- First-touch attribution (source, campaign, landing page) is promoted to the user record
This happens automatically — no developer action required.
Privacy by default
- IP addresses are used for geo resolution, then immediately discarded — never stored
- First-party cookie only — no fingerprinting, no cross-device tracking
- Anonymous visitor data auto-purges after 90 days if never linked to a user
- No third-party scripts or data sharing
Client-side (React)
Track custom events from the browser. Works for both anonymous visitors and authenticated users. Browser context (userAgent, locale, screen size, referrer, URL) is captured automatically.
The same track() call works in two modes — the SDK picks the right one based on auth state:
Visitor tracking (pre-signup)
Before the user signs up or logs in, events track against an anonymous vis_ ID. Use these for lightweight surface interactions — the kind of things you'd see in web analytics:
import { useAnalytics } from "@ascendkit/nextjs";
// Landing page — visitor isn't signed in yet
function LandingPage() {
const { track } = useAnalytics();
return (
<>
<button onClick={() => track("cta_clicked", { location: "hero" })}>
Get Started
</button>
<button onClick={() => track("pricing_viewed", { plan: "pro" })}>
View Pricing
</button>
</>
);
}
// Docs page — still anonymous
function DocsSearch() {
const { track } = useAnalytics();
function onSearch(query: string) {
track("docs_searched", { query });
}
return <SearchInput onSearch={onSearch} />;
}
These events are stored with the visitor's vis_ ID. When the visitor signs up, they retroactively stitch to the usr_ record — so you can later see "this user searched for 'auth setup' in docs before signing up."
Pre-auth events feed the analytics dashboard, conversion paths, and page flow views in the portal.
Business event tracking (post-signup)
After the user is authenticated, events track against their usr_ ID. Use these for meaningful application milestones — the kind of things that trigger automations:
// User is signed in — usr_ ID attached automatically
function CheckoutButton() {
const { track, flush } = useAnalytics();
return (
<button
onClick={async () => {
track("checkout.completed", { total: 99.99, plan: "pro" });
await flush(); // ensure delivery before navigation
}}
>
Buy
</button>
);
}
function OnboardingStep({ step }: { step: number }) {
const { track } = useAnalytics();
useEffect(() => {
track("onboarding.step_completed", { step, stepName: "invite_team" });
}, []);
return <StepContent />;
}
Post-auth events feed journey transitions, engagement triggers, webhook dispatch, and funnel analysis — in addition to the analytics dashboard.
You don't choose a mode
The developer writes the same track() call regardless. The SDK handles routing:
| Before signup | After signup | |
|---|---|---|
| Identity attached | vis_ (cookie) | usr_ (session) |
| API endpoint | /v1/analytics/collect | /v1/events |
| Powers | Analytics dashboard, conversion paths | + Journeys, engagement, webhooks |
Events batch in memory and flush every 30 seconds, when the batch fills (10 events), or on page hide.
flush() is asynchronous and returns a Promise<void>, so await flush() when you need delivery to complete before continuing.
Event naming
The SDK automatically prepends app. to all tracked events. So track("checkout.completed") fires as app.checkout.completed in the AscendKit system. This prefix distinguishes your application events from built-in events (like user.created).
Server-side (Node.js)
Track events from your backend with trusted identity (secret key auth). Useful for events that happen outside the browser — payment processing, background jobs, admin actions.
import { Analytics } from "@ascendkit/nextjs/server";
const analytics = new Analytics();
analytics.track("usr_456", "checkout.completed", { total: 99.99 });
The constructor reads ASCENDKIT_SECRET_KEY and ASCENDKIT_ENV_KEY from your environment. If either is missing, it throws at initialization so you catch configuration issues immediately.
Events batch in memory and flush every 30 seconds, when the batch fills (10 events), or on shutdown(). Call analytics.shutdown() for graceful cleanup (e.g. in process.on("beforeExit")).
Server-side (Python)
from ascendkit import Analytics
analytics = Analytics()
analytics.track("usr_456", "checkout.completed", {"total": 99.99})
The constructor reads ASCENDKIT_SECRET_KEY from your environment. See Python SDK for full setup details.
Passing visitor context (Python)
If you have access to the visitor cookie from the client request, pass it to server-side tracking for identity linking:
analytics.track("usr_456", "checkout.completed", {"total": 99.99}, visitor_id="vis_abc123")
What's collected automatically vs. custom events
| Data | How it's collected |
|---|---|
| Pageviews, referrer, UTM | Automatic — no code needed |
| Device, browser, OS, geo | Automatic — derived from request |
| Sessions | Automatic — 30-min inactivity timeout |
| Identity stitching | Automatic — on signup/login |
| Custom events (button clicks, etc.) | .track() call |
How analytics connects to journeys
Events tracked via track() are available as journey transition triggers. For example:
- You call
track("completed_onboarding")in your app - AscendKit fires the event
app.completed_onboarding - Any journey transition with
--on app.completed_onboardingadvances the user
This means a single track() call simultaneously records an analytics event and drives journey automation. See User Journeys — Application events for details.
How analytics powers other services
Analytics data feeds into the rest of the AscendKit platform:
- Journeys: trigger automations based on acquisition source or pageview patterns
- Surveys: target surveys to users from specific campaigns
- User records: attribution data visible on every user profile
Built-in events
These events are tracked automatically by AscendKit — you do not need to call track() for them:
| Event | Description |
|---|---|
user.created | User signs up (any method) |
user.login | User logs in |
user.signout | User signs out |
user.waitlisted | User placed on waitlist |
user.waitlist_approved | User approved from waitlist |