How to create backend events with PostHog

Stefan SkorpenStefan Skorpen
4 min read

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:

  1. Authentication Events
await client.capture({
    distinctId: 'user_123',
    event: 'login_attempted',
    properties: {
        method: 'password',
        success: true,
        userAgent: req.headers['user-agent'],
        ipAddress: req.ip
    }
})
  1. Background Job Events
await client.capture({
    distinctId: 'system',
    event: 'scheduled_job_completed',
    properties: {
        jobName: 'daily_report_generation',
        durationSeconds: 145,
        recordsProcessed: 1000,
        success: true
    }
})
  1. 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.

0
Subscribe to my newsletter

Read articles from Stefan Skorpen directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Stefan Skorpen
Stefan Skorpen