분석: 하나의 뷰
분석은 사용자 상태를 읽는 것입니다. 퍼널, 리텐션, 코호트는 엔진의 나머지가 작용하는 것과 동일한 실시간 투영에 대한 쿼리입니다.
At a glance
- Host
https://eu.api.prodantix.com- Ingest
POST /v1/eventsand its rules: Ingest API- Query
analyticsandeventsqueries: GraphQL reference
- 퍼널과 리텐션은 실시간 상태에서 계산되며, 야간 웨어하우스 롤업이 아닙니다
- 코호트는 한 번 정의하면 이벤트가 도착하는 대로 최신 상태로 유지됩니다
- SQL 왕복이 없음. 상태가 이미 질문에 맞게 형성되어 있습니다
작동 방식
Events land on the EU ingestion host, are buffered through Redpanda and written to ClickHouse. Queries read from ClickHouse, so a funnel over thirty days answers in the same shape whether it spans a thousand events or a billion.
202: acceptance for processing, not proof of storage. The Ingest API page carries the full contract.접근 위치
| Surface | Operation |
|---|---|
| REST | POST /v1/events · POST /v1/identify · POST /v1/group |
| GraphQL | runQuery · runFunnel · runRetention · runPaths · runStickiness · runLifecycle · events · dashboards, cohorts |
| MCP | prodantix.analytics.runQuery |
예시
curl -X POST "https://eu.api.prodantix.com/v1/events" \
-H "Authorization: Bearer $PRODANTIX_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [{
"distinct_id": "u_8f3a",
"event_id": "5f6b2c1e-8f4b-4c6e-9d2a-7b1e3c4d5a6f",
"event_name": "order.completed",
"properties": { "amount": 4200 },
"schema_version": 1,
"timestamp": "2026-08-31T12:00:00.000Z"
}],
"sent_at": "2026-08-31T12:00:01.000Z"
}'prodantix.capture('order.completed', {
properties: { amount: 4200 },
});await prodantix.capture(
'order.completed',
properties: {'amount': 4200},
);prodantix.capture(
"order.completed",
distinct_id="u_8f3a",
properties={"amount": 4200},
)Querying a trend
A trend takes one or more metrics, each its own event and measure, an optional formula per letter, up to three breakdowns and a comparison against an earlier window. A single metric skips the array: event, measure and, for one breakdown, breakdown stand in for metrics and breakdowns, and the two shapes never mix in the same query.
query RunQuery($projectId: String!, $query: MetricsQueryInput!) {
runQuery(projectId: $projectId, query: $query) {
series {
key
metric
breakdown
past
points {
time
value
}
}
}
}
# $query
{
"metrics": [
{ "event": "checkout.started", "measure": { "kind": "total" } },
{ "event": "checkout.completed", "measure": { "kind": "total" } }
],
"formulas": [{ "expression": "B / A * 100" }],
"breakdowns": [{ "property": "plan" }, { "column": "geo_country" }],
"compare": { "to": "previous_period" },
"dateRange": { "from": "2026-08-01T00:00:00Z", "to": "2026-09-01T00:00:00Z" },
"granularity": "day"
}Querying a funnel
query Funnel($projectId: String!, $query: JSON!) {
runFunnel(projectId: $projectId, query: $query) {
step
event
users
conversionFromPrevious
droppedOff
}
}
# $query
{
"steps": [{ "event": "signup.started" }, { "event": "signup.completed" }, { "event": "order.completed" }],
"conversionWindowSeconds": 2592000,
"dateRange": { "from": "2026-08-01T00:00:00Z", "to": "2026-09-01T00:00:00Z" }
}Paths, stickiness and lifecycle
Three more reports take the same shape: a JSON query the server validates against the report's own parser, and a list of rows back. Paths walk one to five steps after (or before) an anchor and rank the top three, five or ten events per step; stickiness counts a period's users by their active days; lifecycle sorts a period's users into new, returning, resurrecting and dormant.
query Paths($projectId: String!, $query: JSON!) {
runPaths(projectId: $projectId, query: $query) {
step
users
events { event users share }
otherEvents
otherUsers
droppedOff
}
}
# $query
{
"anchorEvent": "checkout.started",
"direction": "after",
"steps": 3,
"topN": 5,
"dateRange": { "from": "2026-08-01T00:00:00Z", "to": "2026-09-01T00:00:00Z" }
}query Stickiness($projectId: String!, $query: JSON!) {
runStickiness(projectId: $projectId, query: $query) {
period
users
days { daysActive users }
}
}
# $query
{
"event": "session.started",
"bucket": "week",
"dateRange": { "from": "2026-07-06T00:00:00Z", "to": "2026-09-01T00:00:00Z" }
}query Lifecycle($projectId: String!, $query: JSON!) {
runLifecycle(projectId: $projectId, query: $query) {
period
new
returning
resurrecting
dormant
}
}
# $query
{
"event": "session.started",
"bucket": "week",
"dateRange": { "from": "2026-07-27T00:00:00Z", "to": "2026-09-07T00:00:00Z" }
}