Creator Session Metrics
Aggregate session metrics for the authenticated creator's bio page — total sessions, bounce rate, average session duration, average pages per session.
GET /api/v1/creators/analytics/sessions — 🔑 Bearer · Rate limit: 60 req / minute
Four headline session metrics. Use this for the dashboard "engagement" tile — bounces, attention time, and how many pages a typical visitor opens.
bounceRate is integer percentage. Math.round((bounced / total) * 100) — 0 decimals. A session is bounced until its second pageview lands (the POST /pageview atomic UPDATE flips the flag) — single-pageview visits are bounces.
avgDuration excludes zero-duration sessions. The aggregate filters where: { duration: { gt: 0 } } — sessions that never received a heartbeat or pageleave (so still have duration = 0) are dropped before averaging. This biases the number upward vs a naïve AVG(duration). Don't multiply avgDuration * totalSessions to get total time.
pagesPerSession is rounded to 1 decimal. Math.round(avg * 10) / 10 — 2.5, not 2.51. avgDuration is rounded to whole seconds (Math.round(avg)).
Request
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
days | integer | 30 | Lookback window. Capped at 365. |
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | ✓ | JwtAuthGuard. |
Response
200 OK — ApiResponseOf<CreatorSessionsDto>
{
"success": true,
"data": {
"totalSessions": 1800,
"bounceRate": 42,
"avgDuration": 145,
"pagesPerSession": 1.8
}
}| Field | Type | Notes |
|---|---|---|
totalSessions | number | All sessions in the window for this bio page. |
bounceRate | number | Whole-number percentage of totalSessions that ended with bounced = true (i.e. had only one pageview). |
avgDuration | number | Average session duration in seconds, rounded to integer, only over sessions with duration > 0. 0 when no qualifying sessions. |
pagesPerSession | number | Average pageViews per session across all sessions, rounded to 1 decimal. 0 when no sessions. |
Errors
Same as overview.
Side effects
JwtAuthGuard+ThrottleGuard.getBioPageId(userId).- Four parallel queries against the Analytics DB:
count({ where: { bioPageId, startedAt: { gte: since } } })→total.count({ where: { bioPageId, startedAt: { gte: since }, bounced: true } })→bounced.aggregate({ where: { bioPageId, startedAt: { gte: since }, duration: { gt: 0 } }, _avg: { duration } })→avgDur.aggregate({ where: { bioPageId, startedAt: { gte: since } }, _avg: { pageViews } })→avgPv.
- Compute the four metrics, round per the rules above, return.
Code samples
curl 'https://api.bio.re/api/v1/creators/analytics/sessions?days=30' \
-H "Authorization: Bearer $ACCESS_TOKEN"type SessionMetrics = {
totalSessions: number;
bounceRate: number;
avgDuration: number;
pagesPerSession: number;
};
async function getSessions(accessToken: string, days = 30): Promise<SessionMetrics> {
const res = await fetch(
`https://api.bio.re/api/v1/creators/analytics/sessions?days=${days}`,
{ headers: { Authorization: `Bearer ${accessToken}` } },
);
const json = await res.json();
if (!res.ok || !json.success) throw new Error(json?.error?.message ?? 'Failed');
return json.data;
}Try it
Authorization
bearer In: header
Query Parameters
Response Body
application/json
application/json
application/json
curl -X GET "https://loading/api/v1/creators/analytics/sessions"{
"success": true,
"data": {
"totalSessions": 1800,
"bounceRate": 42.5,
"avgDuration": 145,
"pagesPerSession": 1.8
}
}{
"success": false,
"error": {
"code": "AUTH_UNAUTHORIZED",
"message": "Invalid credentials",
"i18nKey": "auth.login.invalid_credentials",
"i18nVars": {
"field": "email"
},
"details": [
{
"message": "email must be an email"
}
],
"correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}{
"success": false,
"error": {
"code": "AUTH_UNAUTHORIZED",
"message": "Invalid credentials",
"i18nKey": "auth.login.invalid_credentials",
"i18nVars": {
"field": "email"
},
"details": [
{
"message": "email must be an email"
}
],
"correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/analytics/creator-analytics.controller.ts | 141–163 (sessions) |
| DTO (response) | apps/api-core/src/modules/analytics/dto/analytics-client-response.dto.ts | 159–171 (CreatorSessionsDto) |
| Prisma model | packages/prisma-analytics/prisma/schema.prisma | AnalyticsSession.bounced / duration / pageViews (lines 54–57), index @@index([bounced, startedAt]) (92) |
Creator Daily Trend
Per-day views and clicks for the creator's bio page. Bucketed via Postgres date_trunc('day', enteredAt). Days with no traffic are absent — fill gaps client-side.
Creator Link Performance
Per-link click counts and CTR for the creator's bio page. Cross-DB join — clicks come from Analytics DB, link metadata (title + URL) is fetched from main DB by id.