Skip to content

Find a component

Loading the directory…

↑ ↓ to select · Enter to open · Esc to closeBrowse all →
Contributor login

Analytics Vllnt

Generic, configurable analytics component for Bijection — any event, any dimension, any domain; rollup-on-write with funnels, retention, uniques

Bijection source
git clone https://github.com/bijectionhq/analytics-vllnt.git
cd analytics-vllnt
git checkout d545d7c7238f2318b5d163cea8709645b90a6ef1
cd packages/convex-analytics

Bijection repository access is required. Request access.

Description

Generic, configurable analytics component for Bijection — any event, any dimension, any domain; rollup-on-write with funnels, retention, uniques

Explore the package README for API concepts, configuration, and examples. Check the Bijection source for adaptation-specific setup.

Available to evaluate

Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.

Getting started

  1. Get the source at the revision above and read its package documentation.
  2. Check the required Bijection SDK version, dependencies, and external service credentials.
  3. Follow the package setup instructions and the guide to using components.
  4. Exercise the component in your deployment according to your project’s verification rules.

Open source

Maintained source: bijectionhq/analytics-vllnt. Based on vllnt/convex-analytics. License: MIT. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

Generic, configurable analytics component for Convex — any event, any dimension, any domain; rollup-on-write with funnels, retention, uniques

Explore the demo ↗

Upstream overview

From the upstream package documentation.

@vllnt/convex-analytics stores events and exposes analytical queries inside your Convex backend. Event names, subject references, properties, and dimensions are supplied by your application rather than imposed by a web-only schema.

Track typed event properties and choose the dimensions to aggregate. Query metrics, breakdowns, timeseries, funnels, retention, or raw events. Rollups support aggregate reads; an optional web preset adds web-specific helpers and an optional React entry supports reactive displays.

The host defines event meaning, identity, consent, and access rules. Sampling, retention, and selected dimensions affect interpretation and coverage. This component does not automatically instrument every client or establish causation from a funnel; validate the events your product sends.

Maintained by bntvllnt at VLLNT. Find the author on GitHub and X.

Use cases

From the upstream package documentation.

  • SaaS onboarding: follow the steps between signup and first useful action.
  • Mobile products: compare activity and return behavior across features.
  • Games and learning: analyze session events, completion steps, and repeat usage.
  • AI applications: measure feature adoption or host-reported task outcomes by model or workflow dimension.

How it works

From the upstream package documentation.

Track typed event properties and choose the dimensions to aggregate. Query metrics, breakdowns, timeseries, funnels, retention, or raw events. Rollups support aggregate reads; an optional web preset adds web-specific helpers and an optional React entry supports reactive displays.

The host defines event meaning, identity, consent, and access rules. Sampling, retention, and selected dimensions affect interpretation and coverage. This component does not automatically instrument every client or establish causation from a funnel; validate the events your product sends.

Upstream package FAQ

How does @vllnt/convex-analytics keep aggregate reads fast as event volume grows?

@vllnt/convex-analytics uses a rollup-on-write strategy: every call to analytics.track() immediately increments counters per dimension value and time bucket, backed by @convex-dev/aggregate and @convex-dev/sharded-counter. The metric(), top(), and timeseries() queries read those pre-aggregated counters, so their cost is O(1) regardless of how many raw events have been ingested.

What analytics queries does @vllnt/convex-analytics support?

@vllnt/convex-analytics provides metric (total count over a range), top (dimension breakdowns), timeseries (bucketed counts), uniques (DAU/WAU/MAU), funnel (ordered step conversion by subjectRef), retention (cohort return rates), distribution (histogram of a numeric measure), and list (paginated raw events). metric, top, and timeseries read pre-aggregated rollups kept forever; funnel, retention, and distribution read TTL-pruned raw events via indexes.

Can I use @vllnt/convex-analytics for non-web use cases like mobile or backend product events?

The core of @vllnt/convex-analytics is domain-neutral and has no hardcoded web fields. You declare your own prop keys as dimensions, pass an optional propsValidator to type them at the boundary, and the component rolls up on whatever keys you specify. Web-specific dimensions and helpers are isolated in the opt-in @vllnt/convex-analytics/web preset.

How does @vllnt/convex-analytics handle auth and multi-tenancy?

@vllnt/convex-analytics is auth-agnostic: the host application gates access and passes opaque subjectRef and sessionRef values into track(). Tables are sandboxed so the host reaches them only through exported functions. Multi-tenancy is handled with the scope config option, which partitions one tenant's data from another without any additional schema work.

What happens to raw events over time and can rollup data be lost?

Raw events are pruned after a configurable retentionDays period (default 90 days), enforced by a cron configured via analytics.configure(). Rollup counters for metric(), top(), and timeseries() are kept indefinitely and are not affected by raw event pruning. Queries like funnel() and retention() that rely on raw events are bounded by the retention window.

Use with agents and CLI

Give your coding agent the component’s source identity and setup guidance.

agent-prompt.md
Help me integrate Analytics Vllnt with Bijection.

Read: https://bijection.com/components/analytics-vllnt/SKILL.md

Check SDK compatibility and dependency availability.
Follow this project's execution and verification rules.

Upstream README.md

View repository ↗

Documentation from vllnt/convex-analytics, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

@vllnt/convex-analytics

A generic, configurable, embedded analytics component for Convex — any event, any dimension, any domain — with rollup-on-write so reads stay O(1).

import { AnalyticsClient } from "@vllnt/convex-analytics";
import { components } from "./_generated/api";

const analytics = new AnalyticsClient(components.analytics, {
  dimensions: ["plan", "country"], // prop keys to roll up on
});

await analytics.track(ctx, "signup", { subjectRef: userId, props: { plan: "pro", country: "FR" } });
const byPlan = await analytics.top(ctx, "signup", "plan"); // [{ value: "pro", count: 1 }]

Features

  • Generic events — free-string event name, opaque subjectRef / sessionRef, host-typed props.
  • Host-declared dimensions — you pass the prop keys to roll up on; nothing is hardcoded.
  • Rollup-on-write — counts are incremented as events land, so metric / top / timeseries read in O(1) (backed by @convex-dev/aggregate + @convex-dev/sharded-counter).
  • Rich verb set — metric, top, timeseries, uniques, funnel, retention, distribution, plus paginated raw list.
  • Configurable — scope, dimensions, granularities, retentionDays, sampleRate, propsValidator; sensible defaults, zero config required.
  • Per-session rate limiting + dedupe + sampling built into track.
  • Opt-in web preset — @vllnt/convex-analytics/web adds web dimensions + UA/geo helpers when you want them.
  • Optional React hooks — @vllnt/convex-analytics/react for reactive aggregate reads.
  • Zero hardcoded domain — no v.any(), no baked-in web fields; the host owns meaning and auth.

Generic core vs web preset

The core is domain-neutral: it knows nothing about web, mobile, or any vertical. Web analytics — pageview dimensions (path, referrer, device, browser, os, country, UTM) plus parseUserAgent / geoFromHeaders / trackPageview helpers — lives in the opt-in @vllnt/convex-analytics/web preset. You turn it on by passing webDimensions to the client's dimensions config; otherwise the core ships no web fields. See docs/web-preset.md.

Installation

npm install @vllnt/convex-analytics

Usage

// convex/convex.config.ts
import { defineApp } from "convex/server";
import analytics from "@vllnt/convex-analytics/convex.config";

const app = defineApp();
app.use(analytics);
export default app;
// convex/analytics.ts — track + read, server-side
import { AnalyticsClient } from "@vllnt/convex-analytics";
import { components } from "./_generated/api";

type MyProps = { plan?: string; country?: string };

const analytics = new AnalyticsClient<MyProps>(components.analytics, {
  dimensions: ["plan", "country"],
  granularities: ["day"],
});

await analytics.track(ctx, "signup", { subjectRef: userId, props: { plan: "pro" } });
const total = await analytics.metric(ctx, "signup");

Config

Passed to the AnalyticsClient constructor. All optional — the defaults work with zero config.

OptionTypeDefaultPurpose
scopestring"default"Multi-tenant partition; isolates one tenant's data.
dimensionsstring[][]Prop keys to roll up on (drives rollup-on-write). Empty = count by event name only.
granularities("minute" | "hour" | "day")[]["day"]Rollup bucket sizes (minute for short live windows).
retentionDaysnumber90Raw-event TTL in days (rollups are kept forever). Applied via configure.
sampleRatenumber1Fraction 0..1 of events to keep at ingest.
sessionIdleMsnumber1800000Idle timeout before a session is closed. Applied via configure.
propsValidatorConvex validatortyped scalar recordOptional host validator narrowing props at the boundary.

scope, dimensions, granularities, and sampleRate apply per call from the client. retentionDays, sampleRate, and sessionIdleMs are persisted for the prune/close-sessions crons by calling analytics.configure(ctx, { ... }) once.

API

VerbKindPurpose
track(ctx, name, opts)mutationIngest an event; rollup-on-write + raw event + counter. Returns "tracked" | "dropped" | "duplicate".
metric(ctx, name, opts)queryTotal count over a range, optionally filtered by a dimension value.
top(ctx, name, dimension, opts)queryTop values of a dimension (breakdown).
timeseries(ctx, name, opts)queryBucketed counts over a range.
uniques(ctx, opts)queryDAU / WAU / MAU from subjects.
funnel(ctx, steps, opts)queryOrdered step conversion, keyed by subjectRef.
retention(ctx, opts)queryCohort return rates by first-seen period.
distribution(ctx, name, measure, opts)queryHistogram of a numeric measure over declared buckets + overflow (with count / sum).
list(ctx, name, paginationOpts, opts)queryPaginated raw events, newest first.
configure(ctx, opts)mutationPersist cron-relevant config (retention / sampling / idle).

Full reference: docs/client-sdk.md. REST surface: docs/api-reference.md.

What it serves

The Convex-native, authoritative in-app aggregate layer — predefined-dimension rollups served reactively in O(1). It complements a product-analytics warehouse; it doesn't replace one. Declare the dimensions and measures you'll query and the rollups answer instantly; ad-hoc or retroactive questions over non-declared dimensions, or beyond the raw-event retention window, are an export concern. metric / top / timeseries read pre-aggregated rollups (kept forever); funnel / retention / distribution read raw events in range (index-backed, bounded, TTL-pruned).

Web preset

import { AnalyticsClient } from "@vllnt/convex-analytics";
import { webDimensions, trackPageview } from "@vllnt/convex-analytics/web";

const analytics = new AnalyticsClient(components.analytics, { dimensions: webDimensions });

await trackPageview(analytics, ctx, {
  path: "/pricing",
  ua: request.headers.get("user-agent") ?? undefined,
  headers: request.headers,
});

webDimensions opts the rollups into path / referrer / device / browser / os / country / UTM; parseUserAgent and geoFromHeaders build those props from a request. See docs/web-preset.md.

React

import { useMetric, useTop } from "@vllnt/convex-analytics/react";
import { api } from "../convex/_generated/api";

const signups = useMetric(api.analytics.metric, { name: "signup" });
const byPlan = useTop(api.analytics.top, { name: "signup", dimension: "plan" });

Thin reactive wrappers over the host's re-exported query refs (metric, top, timeseries, uniques). react + convex are optional peer deps; backend-only consumers pull no React.

MCP (Claude Code)

claude mcp add convex-analytics-mcp \
  --env CONVEX_URL=https://your-deployment.convex.cloud \
  --env ANALYTICS_API_KEY=your-key

7 tools: track, get_metric, get_top, get_timeseries, get_uniques, detect_anomalies, query_analytics (NL router). See docs/mcp-tools.md.

Security

  • Auth-agnostic mount — the host gates access and passes opaque subjectRef / sessionRef in.
  • Tables are sandboxed; the host reaches them only through the exported functions.
  • REST endpoints require an x-api-key header, compared timing-safe.

See docs/architecture.md.

Testing

pnpm test
import analyticsTest from "@vllnt/convex-analytics/test";
import { convexTest } from "convex-test";

const t = convexTest(hostSchema, hostModules);
analyticsTest.register(t);

Documentation

Schema · Client SDK · REST API · Web Preset · Multi-Product · Architecture · MCP Tools. For AI agents: llms.txt · llms-full.txt.

Contributing

See CONTRIBUTING.md.

Author

Built by bntvllnt · bntvllnt.com · X @bntvllnt

Part of the @vllnt Convex component fleet — vllnt.com

If this is useful, sponsor the work.

License

MIT — see LICENSE.

Keywords