Analytics
Adapter-based analytics for Payload v3, with a self-hosted engine, dashboard widgets and per-document stats.
@10x-media/analytics puts web analytics inside the Payload admin. One adapter contract covers a self-hosted native engine and the major providers (GA4, Plausible, Umami, PostHog), so the same view, dashboard widgets and per-document stat fields work wherever the numbers come from, and switching providers is a config change.
import { analytics, analyticsDefaultWidgets } from '@10x-media/analytics'
import { native } from '@10x-media/analytics/adapters/native'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { buildConfig } from 'payload'
export default buildConfig({
db: mongooseAdapter({ url: process.env.DATABASE_URL ?? '' }),
secret: process.env.PAYLOAD_SECRET ?? '',
admin: {
dashboard: { widgets: [], defaultLayout: [...analyticsDefaultWidgets()] },
},
plugins: [
analytics({
adapters: [native()],
// Required, and your decision: 'off' captures at once, 'all' holds every capture slot
// until your consent manager calls setGate (see Consent), so it counts nothing without one.
capture: { gate: 'off' },
collections: {
pages: { path: (doc) => (typeof doc.slug === 'string' ? `/${doc.slug}` : null) },
},
}),
],
})What it is, and what it is not
It is:
- An adapter layer. Every surface reads through one adapter contract with a capabilities model: run the native engine, a provider, or several at once, and every surface hides what the active source cannot answer.
- A self-hosted engine. The native engine stores analytics in your own Payload database, on MongoDB, Postgres or SQLite: raw hits counted into exact daily totals, 30-minute visits with bounce rate and time per visit, geo resolution, bot filtering, and daily visitor salts deleted within days. It sets no cookie.
- A capture pipeline. A dependency-free browser tracker, a first-party proxy so a vendor's own SDK loads through your origin (GA4's tag excepted, which loads from Google), goals and revenue from markup, form submissions and server code, and a signed exclusion link that keeps staff out of the numbers.
- Admin surfaces. The analytics view at
/admin/analytics, whose whole state is in its URL; dashboard widgets on Payload's Modular Dashboard; and display fields that put a document's own numbers on your collections. Nothing is injected into your schema. - An API. An authenticated query endpoint over any configured source, with cached reads served stale while they refresh, and an opt-in sync tier that copies vendor numbers into a collection.
It is not:
- A consent manager. The plugin stores no consent state and decides nothing about consent. Whether a site may measure before a visitor answers, and under which category, is the site operator's decision, made in a consent manager such as c15t. What the plugin gives that manager is a gate in front of each capture slot, which it opens and closes with
setGate. - A tag manager. It boots the tracker of the vendors it has adapters for, and nothing else.
- A legal assessment. Privacy states what a stored hit holds and how long it is kept; whether an install needs a notice or a legal basis is yours to decide.
When to use it
Use the native engine when you want analytics without a third-party service: no cookies, data in your own database, no account to manage. Use a provider adapter when the numbers already live in GA4, Plausible, Umami or PostHog and you want them next to the content they describe. Mixing works too: several adapters can be registered and chosen per widget or field, and on a multi-tenant install each tenant can bring its own.
Requirements
| Payload | ^3.83.0, with @payloadcms/next and @payloadcms/ui at the same range |
| Next.js | ^15.2.9 or ^16.2.6 |
| React | 19 |
| Node.js | 22.18 or later |
@10x-media/fields | required peer: the providers collection seals its keys with its encrypted fields |
| Optional peers | @google-analytics/data (GA4) and maxmind (MaxMind geo lookup) |
| Native engine | MongoDB 5.0, Postgres 12 or SQLite 3.35 or later, SQLite on a database file; not Cloudflare D1, and not MongoDB-compatible services such as Amazon DocumentDB, Azure Cosmos DB or Firestore |
Dashboard widgets use Payload's Modular Dashboard, an experimental Payload feature, so they are marked @beta here too (Stability).
Where to go next
- Install it and see numbers: Quick start.
- Learn the ideas the rest of these pages use: Concepts.
- Wire your consent manager to the gate: Consent.
- Look up an option, an endpoint or an export: Options, Endpoints, Entry points.
- Coming from an earlier beta: Upgrading.