Configuration
Plugin options, environment variables, and auto-detection behavior.
Configure the analytics plugin through environment variables, a plugin config file, or both.
Environment variables
The simplest way to configure the plugin. Add these to your .env file:
Google Analytics
GOOGLE_ANALYTICS_MEASURE_ID="G-XXXXXXXXX"
GOOGLE_ANALYTICS_SECRET="your-api-secret"| Variable | Required | Description |
|---|---|---|
GOOGLE_ANALYTICS_MEASURE_ID | Yes | GA4 Measurement ID (starts with G-) |
GOOGLE_ANALYTICS_SECRET | Yes | Measurement Protocol API Secret |
Plausible
PLAUSIBLE_DOMAIN="example.com"| Variable | Required | Description |
|---|---|---|
PLAUSIBLE_DOMAIN | Yes | Site domain registered in Plausible |
Plugin options
Create a config file for advanced setup. The only option is engine, which overrides auto-detection entirely.
export default {
engine: undefined // Optional: custom BaseEngine instance
}export default {
engine: undefined // Optional: custom BaseEngine instance
}Prop
Type
Examples
Use Google Analytics with explicit credentials:
import { GoogleAnalytics } from '@robojs/analytics'
export default {
engine: new GoogleAnalytics({
measureId: 'G-XXXXXXXXX',
token: 'your-api-secret'
})
}import { GoogleAnalytics } from '@robojs/analytics'
export default {
engine: new GoogleAnalytics({
measureId: 'G-XXXXXXXXX',
token: 'your-api-secret'
})
}Use Plausible with explicit domain:
import { PlausibleAnalytics } from '@robojs/analytics'
export default {
engine: new PlausibleAnalytics('example.com')
}import { PlausibleAnalytics } from '@robojs/analytics'
export default {
engine: new PlausibleAnalytics('example.com')
}Use multiple services:
import { GoogleAnalytics, PlausibleAnalytics, ManyEngines } from '@robojs/analytics'
export default {
engine: new ManyEngines(
new GoogleAnalytics(),
new PlausibleAnalytics()
)
}import { GoogleAnalytics, PlausibleAnalytics, ManyEngines } from '@robojs/analytics'
export default {
engine: new ManyEngines(
new GoogleAnalytics(),
new PlausibleAnalytics()
)
}When using ManyEngines in the config file, engine constructors still fall back to environment variables for their credentials.
Auto-detection
When no engine is set in the config, the plugin reads environment variables at startup and creates the appropriate engine automatically.
| Environment variables present | Engine created |
|---|---|
GOOGLE_ANALYTICS_MEASURE_ID + PLAUSIBLE_DOMAIN | ManyEngines(GoogleAnalytics, PlausibleAnalytics) |
GOOGLE_ANALYTICS_MEASURE_ID only | GoogleAnalytics |
PLAUSIBLE_DOMAIN only | PlausibleAnalytics |
| Neither | No engine. Warning logged. |
This detection runs in the plugin's start lifecycle hook (src/robo/start.ts). If a custom engine is provided in the config, auto-detection is skipped entirely.
Setting both Google Analytics and Plausible environment variables automatically sends events to both services. No ManyEngines config needed.
Initialization lifecycle
The plugin initializes during the Robo start lifecycle hook (src/robo/start.ts):
Check for custom engine
If engine is set in plugin options, use it directly. Skip to step 3.
Auto-detect from environment
Check for GOOGLE_ANALYTICS_MEASURE_ID and PLAUSIBLE_DOMAIN. Create the appropriate engine(s) or log a warning if neither is set.
Freeze and activate
The engine is frozen with Object.freeze() and stored in the Analytics singleton. Analytics.isReady() now returns true.
After initialization, the Analytics object and its engine are immutable. They cannot be changed at runtime.
Seed files
When installed with npx robo add @robojs/analytics, the plugin seeds three files into your project:
| Seed file | Target path | Purpose |
|---|---|---|
track-commands.ts | src/middleware/track-commands.ts | Middleware that tracks every slash command automatically |
test-analytics.ts | src/commands/test-analytics.ts | Test command to verify analytics integration |
guildCreate.ts | src/events/guildCreate.ts | Tracks server_join when the bot joins a new server |
Command tracking middleware
The seeded middleware intercepts all slash commands and sends an event:
import { Analytics } from '@robojs/analytics'
import type { ChatInputCommandInteraction } from 'discord.js'
import type { MiddlewareData } from '@robojs/discordjs'
export default async (data: MiddlewareData) => {
const { payload, record } = data
if (record.type === 'command') {
const interaction = payload[0] as ChatInputCommandInteraction
const name = record.key.replaceAll('/', '_').replaceAll('-', '_')
Analytics.event(name, {
data: { type: 'slash_command' },
sessionId: interaction.channelId ?? interaction.guildId,
userId: interaction.user?.id
})
}
}import { Analytics } from '@robojs/analytics'
export default async (data) => {
const { payload, record } = data
if (record.type === 'command') {
const interaction = payload[0]
const name = record.key.replaceAll('/', '_').replaceAll('-', '_')
Analytics.event(name, {
data: { type: 'slash_command' },
sessionId: interaction.channelId ?? interaction.guildId,
userId: interaction.user?.id
})
}
}Command names are normalized: /moderation/ban becomes moderation_ban. This fires for every slash command without requiring per-command tracking code.
Server join tracking
The seeded event handler requires the Guilds intent:
import { Analytics } from '@robojs/analytics'
import type { Guild } from 'discord.js'
export default (guild: Guild) => {
Analytics.event('server_join', {
data: { name: guild.name, type: 'event' },
sessionId: guild.id
})
}import { Analytics } from '@robojs/analytics'
export default (guild) => {
Analytics.event('server_join', {
data: { name: guild.name, type: 'event' },
sessionId: guild.id
})
}Enable the intent in your Discord plugin config if you want this tracking:
export default {
clientOptions: {
intents: ['Guilds']
}
}export default {
clientOptions: {
intents: ['Guilds']
}
}