How to create backend events with PostHog
It's important to keep track of events in your webapp so you can see what features are used and how they are used. While frontend event tracking is common, capturing backend events can provide deeper insights into your application's behavior, performance, and user patterns. With PostHog, it's quite easy to create events in your backend.
Setting Up PostHog
First, install the PostHog Node.js library:
npm install posthog-node
# or
yarn add posthog-node
Initializing PostHog
Initialize PostHog with your project API key:
const { PostHog } = require('posthog-node')
const client = new PostHog(
'phc_YOUR_API_KEY',
{
host: 'https://app.posthog.com' // Optional: Use your self-hosted instance URL if applicable
}
)
Capturing Basic Events
The simplest way to capture an event is using the capture
method:
client.capture({
distinctId: 'user_123',
event: 'subscription_created',
properties: {
planType: 'premium',
billingInterval: 'monthly',
amount: 29.99
}
})
Best Practices for Backend Events
1. Consistent Event Naming
Use a consistent naming convention for your events. A common pattern is:
Noun_Verb for state changes:
subscription_created
,payment_failed
Verb_Noun for actions:
generate_report
,send_notification
2. Rich Properties
Include relevant properties that will be useful for analysis:
client.capture({
distinctId: 'user_123',
event: 'api_request_completed',
properties: {
endpoint: '/api/v1/users',
method: 'POST',
responseTimeMs: 235,
statusCode: 200,
userAgent: req.headers['user-agent'],
ipAddress: req.ip
}
})
3. Batch Processing
For high-volume events, use batch capturing to improve performance:
const events = [
{
distinctId: 'user_123',
event: 'item_purchased',
properties: { itemId: '456', price: 29.99 }
},
{
distinctId: 'user_123',
event: 'checkout_completed',
properties: { total: 29.99, itemsCount: 1 }
}
]
await client.batchCapture(events)
Advanced Features
1. Feature Flags
You can evaluate feature flags in your backend code:
const flagEnabled = await client.isFeatureEnabled('new_billing_flow', 'user_123')
if (flagEnabled) {
// Roll out new billing logic
}
2. Group Analytics
Track events at an organization level:
// Identify a group
await client.groupIdentify({
groupType: 'company',
groupKey: 'company_123',
properties: {
name: 'Acme Corp',
industry: 'Technology',
employeeCount: 500
}
})
// Capture event with group information
await client.capture({
distinctId: 'user_123',
event: 'project_created',
properties: { projectName: 'New Project' },
groups: { company: 'company_123' }
})
3. Error Handling
Implement robust error handling to prevent event capture failures from affecting your application:
try {
await client.capture({
distinctId: 'user_123',
event: 'important_action',
properties: { key: 'value' }
})
} catch (error) {
console.error('Failed to capture PostHog event:', error)
// Consider adding to a retry queue
}
Common Patterns and Use Cases
Here are some typical backend events you might want to track:
- Authentication Events
await client.capture({
distinctId: 'user_123',
event: 'login_attempted',
properties: {
method: 'password',
success: true,
userAgent: req.headers['user-agent'],
ipAddress: req.ip
}
})
- Background Job Events
await client.capture({
distinctId: 'system',
event: 'scheduled_job_completed',
properties: {
jobName: 'daily_report_generation',
durationSeconds: 145,
recordsProcessed: 1000,
success: true
}
})
- API Usage Events
await client.capture({
distinctId: 'user_123',
event: 'api_key_generated',
properties: {
keyType: 'read_only',
expirationDays: 30,
permissions: ['read_users', 'read_projects']
}
})
Shutdown
When your application is shutting down, make sure to close the PostHog client to ensure all events are sent:
await client.shutdown()
Using with Express.js
Here's an example of integrating PostHog with an Express.js middleware:
const express = require('express')
const app = express()
// Middleware to track API requests
app.use(async (req, res, next) => {
const startTime = Date.now()
// Continue with the request
next()
// After the request is completed
res.on('finish', async () => {
try {
await client.capture({
distinctId: req.user?.id || 'anonymous',
event: 'api_request',
properties: {
path: req.path,
method: req.method,
statusCode: res.statusCode,
duration: Date.now() - startTime,
userAgent: req.headers['user-agent']
}
})
} catch (error) {
console.error('Failed to capture API request event:', error)
}
})
})
Conclusion
Backend event tracking with PostHog in Node.js provides valuable insights into your application's behavior and usage patterns. By following these best practices and patterns, you can build a robust event tracking system that helps you make data-driven decisions about your product.
Remember to:
Use consistent naming conventions
Include relevant properties with each event
Handle errors gracefully
Use batch processing for high-volume events
Properly shut down the client when your application terminates
Leverage advanced features like feature flags and group analytics when appropriate
For more information, check out the PostHog Node.js documentation for detailed API references and additional features.
Subscribe to my newsletter
Read articles from Stefan Skorpen directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by