Analytics & Reporting
NexoMailer Analytics is a high-performance persistence layer that turns raw tracking events into actionable insights. It stores everything in your own MongoDB, giving you 100% data ownership.
Installation
Install the Analytics module:
npm install @nexomailer/analytics(Alternatively, you can use pnpm add @nexomailer/analytics or yarn add @nexomailer/analytics).
🏗️ Unified Data Loop
The Analytics module automatically aggregates events from two sources:
- Engagement Events: Opens and Clicks captured by your Tracking Middleware.
- Infrastructure Events: Bounces and Deliveries captured via Provider Webhooks.
Setting up the MongoDB Connection
To use the Analytics module, simply provide your MongoDB URI during NexoMailer initialization. The connection is handled automatically.
import { NexoMailer } from '@nexomailer/core';
const mailer = new NexoMailer({
/* ... providers ... */
analytics: {
// Your standard MongoDB connection string
mongodbUri: 'mongodb://localhost:27017/nexomailer',
// (Optional) Tag records to isolate environments
environment: 'production',
// (Optional) Retain logs for a specific number of days before auto-deleting
retentionDays: 90
}
});
// Connects to the database and ensures all Mongoose indexes are built
await mailer.init();1. Accessing Your Data
Since NexoMailer is headless, we provide clean APIs to fetch your message history and statistics. You can use these functions to feed data into your own custom React or Vue dashboards.
Fetch Message List
Retrieve a paginated list of emails sent through the system.
const result = await mailer.analytics.getMessages({
page: 1, // The page number to retrieve
limit: 20, // Number of records per page
status: 'BOUNCED' // (Optional) Filter by status: SENT, DELIVERED, OPENED, CLICKED, BOUNCED
});
console.log(`Found ${result.total} bounced messages.`);
console.log(result.messages);
// Array of message summaries including recipient, subject, and statusGet Full Message Audit Trail
See every single interaction a user had with a specific email.
// Pass the exact message ID (returned when you call mailer.send)
const details = await mailer.analytics.getMessageDetails('msg_uuid_123');
console.log(`Current Status: ${details.status}`); // e.g., "CLICKED"
// The events array contains a chronological list of everything that happened
details.events.forEach(event => {
console.log(`[${event.timestamp}] ${event.type}: ${JSON.stringify(event.metadata)}`);
});
// Output:
// [2026-05-13T10:00:00Z] email.sent: { provider: 'resend' }
// [2026-05-13T10:05:00Z] email.opened: { ip: '192.168.1.1' }
// [2026-05-13T10:06:00Z] email.clicked: { url: 'https://nexodev.agency' }2. Global Aggregation (Reporting)
Generate high-level summaries for your custom dashboards.
const summary = await mailer.analytics.getSummary({
// Define the date range for your report
from: new Date('2026-05-01'),
to: new Date('2026-05-31'),
// (Optional) Filter by environment or projectId
environment: 'production'
});
console.log(`Total Sent: ${summary.total}`);
console.log(`Open Rate: ${summary.openRate}%`);
console.log(`Click Rate: ${summary.clickRate}%`);
console.log(`Total Bounces: ${summary.bounced}`);🛡️ Status Prioritization Logic
To maintain a clean state, the Analytics module uses a "Priority Ladder". A message's status only moves Up.
Priority Ladder:
SENT < DELIVERED < OPENED < CLICKED
[!TIP] Example: If a message is already marked as
CLICKED, and a tracking pixel sends a lateOPENEDevent, the status will not be downgraded. However, error states likeBOUNCEDorCOMPLAINEDwill always trigger an immediate update regardless of current status.
Build Your Own Dashboard
NexoMailer is designed to be the engine behind your dashboard. You can use our provided Schemas to build your own UI. All data is indexed by messageId, projectId, and recipient for sub-millisecond response times.