Аналитика: представление
Аналитика: это чтение состояния пользователя. Воронки, удержание и когорты: это запросы к той же живой проекции, на которую действует остальная часть движка.
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" }
}