통계 콘텐츠 세션 원장 추가

This commit is contained in:
2026-07-29 14:48:14 +09:00
parent 1a5a1542b7
commit 4e7e12d8fe
15 changed files with 481 additions and 47 deletions

View File

@@ -7,6 +7,7 @@ import {
} from '../../lib/analytics.js'
import { getPageBySlug, getPostBySlug } from '../repositories/content-repository.js'
import {
createContentSessionHashFromEvent,
createSessionHashFromEvent,
recordAnalyticsHeartbeat
} from '../repositories/analytics-repository.js'
@@ -18,6 +19,7 @@ const heartbeatInputSchema = z.object({
postSlug: z.string().trim().max(200).optional().default(''),
pageSlug: z.string().trim().max(200).optional().default(''),
clientSessionId: z.string().trim().min(8).max(120),
contentSessionId: z.string().trim().max(120).optional().default(''),
durationSeconds: z.number().int().min(0).max(1800),
maxScrollRatio: z.number().min(0).max(1)
})
@@ -78,10 +80,14 @@ export const handleAnalyticsHeartbeat = async (event) => {
}
const sessionHash = createSessionHashFromEvent(event, body.clientSessionId)
const contentSessionHash = body.contentSessionId
? createContentSessionHashFromEvent(event, body.contentSessionId)
: ''
await recordAnalyticsHeartbeat({
event,
sessionHash,
contentSessionHash,
path: body.path,
postId,
postSlug,

View File

@@ -11,6 +11,8 @@ import {
} from '../../lib/analytics-traffic.js'
import { getPageBySlug, getPostBySlug } from '../repositories/content-repository.js'
import {
createContentSessionHashFromEvent,
createSessionHashFromEvent,
createVisitorHashFromEvent,
recordAnalyticsPageview
} from '../repositories/analytics-repository.js'
@@ -21,6 +23,8 @@ const pageviewInputSchema = z.object({
path: z.string().trim().min(1).max(500),
postSlug: z.string().trim().max(200).optional().default(''),
pageSlug: z.string().trim().max(200).optional().default(''),
clientSessionId: z.string().trim().max(120).optional().default(''),
contentSessionId: z.string().trim().max(120).optional().default(''),
referrer: z.string().trim().max(1000).optional().default(''),
currentUrl: z.string().trim().max(1000).optional().default(''),
read: z.boolean().optional().default(false)
@@ -82,6 +86,12 @@ export const handleAnalyticsPageview = async (event) => {
}
const visitorHash = createVisitorHashFromEvent(event)
const sessionHash = body.clientSessionId
? createSessionHashFromEvent(event, body.clientSessionId)
: ''
const contentSessionHash = body.contentSessionId
? createContentSessionHashFromEvent(event, body.contentSessionId)
: ''
const isReadEvent = Boolean(body.read)
const traffic = {
...classifyAnalyticsTrafficSource({
@@ -93,6 +103,9 @@ export const handleAnalyticsPageview = async (event) => {
await recordAnalyticsPageview({
visitorHash,
sessionHash,
contentSessionHash,
path: body.path,
postId,
pageId,
traffic,