@rachelallyson/stratum-posthog-js
v1.0.8
Published
A PostHog plugin for Stratum Observability that enables seamless integration between your application's observability events and PostHog analytics.
Downloads
39
Readme
Stratum PostHog Plugin
A PostHog plugin for Stratum Observability that enables seamless integration between your application's observability events and PostHog analytics.
Features
- ✅ Event Publishing: Send Stratum events to PostHog with full type safety
- ✅ User Identification Event Types: Handle user identification through flexible event types
- ✅ Flexible Event Naming: Name your events anything you want while using PostHog identification
- ✅ Browser Support: Full browser integration with PostHog JS SDK
- ✅ Type Safety: Complete TypeScript support with generics
- ✅ Flexible Configuration: Support for both configuration-based and pre-initialized PostHog instances
- ✅ Stratum Integration: Properly registered event types with Stratum framework
Installation
npm install @rachelallyson/stratum-posthog-jsQuick Start
1. Basic Setup
import { PosthogService, PosthogPlugin, PosthogEventTypes } from '@rachelallyson/stratum-posthog-js';
// Define your event catalog using Stratum's standard pattern
const catalog = {
BUTTON_CLICK: {
id: "BUTTON_CLICK",
description: "User clicked a button",
eventType: PosthogEventTypes.CAPTURE,
properties: {
button_name: "string",
page: "string",
},
},
USER_LOGIN: {
id: "USER_LOGIN",
description: "User logged in",
eventType: PosthogEventTypes.CAPTURE,
properties: {
login_method: "string",
user_id: "string",
},
},
// User identification events - name them anything you want!
USER_SIGNED_IN: {
id: "USER_SIGNED_IN",
description: "User signed in and identified with PostHog",
eventType: PosthogEventTypes.IDENTIFY,
properties: {
distinct_id: "string",
person_properties: "object",
anonymous_id: "string",
},
},
USER_SIGNED_OUT: {
id: "USER_SIGNED_OUT",
description: "User signed out and reset PostHog",
eventType: PosthogEventTypes.RESET,
properties: {
previous_distinct_id: "string",
reset_device_id: "string",
},
},
USER_LINKED: {
id: "USER_LINKED",
description: "User linked with another ID",
eventType: PosthogEventTypes.ALIAS,
properties: {
distinct_id: "string",
alias: "string",
},
},
// Alternative naming examples
CUSTOMER_ONBOARDED: {
id: "CUSTOMER_ONBOARDED",
description: "Customer completed onboarding",
eventType: PosthogEventTypes.IDENTIFY,
properties: {
distinct_id: "string",
person_properties: "object",
anonymous_id: "string",
},
},
SESSION_ENDED: {
id: "SESSION_ENDED",
description: "User session ended",
eventType: PosthogEventTypes.RESET,
properties: {
previous_distinct_id: "string",
reset_device_id: "string",
},
},
ACCOUNT_MERGED: {
id: "ACCOUNT_MERGED",
description: "User accounts merged",
eventType: PosthogEventTypes.ALIAS,
properties: {
distinct_id: "string",
alias: "string",
},
},
};
// Create the service
const service = new PosthogService({
catalog: { items: catalog },
plugins: [
PosthogPlugin({
POSTHOG_KEY: "your-posthog-key",
config: {
api_host: "https://your-posthog-host.com",
autocapture: true,
},
}),
],
productName: "my-app",
productVersion: "1.0.0",
});2. Publishing Events
// Publish a regular event with properties
await service.publish("BUTTON_CLICK", {
pluginData: {
PosthogPlugin: {
properties: {
button_name: "submit",
page: "checkout",
},
},
},
});
// Publish a simple event without properties
await service.publish("PAGE_VIEW", {
pluginData: {
PosthogPlugin: {
properties: {},
},
},
});
// Or even simpler - the plugin will work with empty properties
await service.publish("PAGE_VIEW", {
pluginData: {
PosthogPlugin: {},
},
});User Identification (Event Types)
Following Stratum's principle that "Events are first-class citizens," user identification is handled through event types rather than specific event names. This gives you complete flexibility in naming your events!
Available Event Types
PosthogEventTypes.IDENTIFY- Calls PostHog'sidentify()methodPosthogEventTypes.RESET- Calls PostHog'sreset()methodPosthogEventTypes.ALIAS- Calls PostHog'salias()method
Identifying Users
When a user logs in, publish an event with the IDENTIFY event type:
// Get the current anonymous ID before identification
const anonymousId = service.getDistinctId();
// Identify the user using any event name you want!
await service.publish("USER_SIGNED_IN", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: "user123",
person_properties: {
email: "[email protected]",
name: "John Doe",
subscription_tier: "premium",
first_login_at: new Date().toISOString(),
},
anonymous_id: anonymousId || "",
},
},
},
});
// Or use a different event name
await service.publish("CUSTOMER_ONBOARDED", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: "user123",
person_properties: {
email: "[email protected]",
onboarding_step: "completed",
},
anonymous_id: anonymousId || "",
},
},
},
});User Logout (Reset)
When a user logs out, publish an event with the RESET event type:
// Reset user using any event name you want!
await service.publish("USER_SIGNED_OUT", {
pluginData: {
PosthogPlugin: {
properties: {
previous_distinct_id: "user123",
reset_device_id: "false", // or "true" to reset device ID
},
},
},
});
// Or use a different event name
await service.publish("SESSION_ENDED", {
pluginData: {
PosthogPlugin: {
properties: {
previous_distinct_id: "user123",
reset_device_id: "false",
},
},
},
});User Aliasing
Use an event with the ALIAS event type to link multiple distinct IDs to the same user:
// Alias a user using any event name you want!
await service.publish("USER_LINKED", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: "frontend_user_123",
alias: "backend_user_456",
},
},
},
});
// Or use a different event name
await service.publish("ACCOUNT_MERGED", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: "account_123",
alias: "account_456",
},
},
},
});Getting Current User ID
// Get the current distinct ID (anonymous or identified)
const distinctId = service.getDistinctId();
console.log("Current user ID:", distinctId);Complete User Management Example
class UserManager {
constructor(private service: PosthogService) {}
async login(userId: string, userData: any) {
// Get current anonymous ID
const anonymousId = this.service.getDistinctId();
// Identify the user - name the event anything you want!
await this.service.publish("USER_SIGNED_IN", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: userId,
person_properties: {
email: userData.email,
name: userData.name,
login_method: "email",
first_login_at: new Date().toISOString(),
},
anonymous_id: anonymousId || "",
},
},
},
});
// Track login event
await this.service.publish("USER_LOGIN", {
pluginData: {
PosthogPlugin: {
properties: {
login_method: "email",
user_id: userId,
},
},
},
});
}
async logout(userId: string) {
// Track logout event
await this.service.publish("USER_LOGOUT", {
pluginData: {
PosthogPlugin: {
properties: {
user_id: userId,
session_duration: "30 minutes",
},
},
},
});
// Reset PostHog user - name the event anything you want!
await this.service.publish("USER_SIGNED_OUT", {
pluginData: {
PosthogPlugin: {
properties: {
previous_distinct_id: userId,
reset_device_id: "false",
},
},
},
});
}
async updateUserProperties(userId: string, properties: any) {
// Update user properties - name the event anything you want!
await this.service.publish("USER_SIGNED_IN", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: userId,
person_properties: properties,
anonymous_id: "", // Empty string for no change
},
},
},
});
// Track property update event
await this.service.publish("USER_PROPERTIES_UPDATED", {
pluginData: {
PosthogPlugin: {
properties: {
user_id: userId,
updated_properties: properties,
},
},
},
});
}
}Configuration Options
Basic Configuration
PosthogPlugin({
POSTHOG_KEY: "your-posthog-key",
config: {
api_host: "https://your-posthog-host.com",
autocapture: true,
capture_pageview: true,
disable_session_recording: false,
persistence: 'localStorage',
},
})Using Pre-initialized PostHog Instance
import posthog from 'posthog-js';
// Initialize PostHog elsewhere in your app
const posthogInstance = posthog.init("your-posthog-key", {
api_host: "https://your-posthog-host.com",
autocapture: true,
});
// Use the pre-initialized instance
PosthogPlugin({
posthogInstance: posthogInstance,
})Configuration Options Reference
| Option | Type | Description |
|--------|------|-------------|
| POSTHOG_KEY | string | Your PostHog project API key |
| POSTHOG_HOST | string | Legacy support for PostHog host URL |
| config | PosthogConfig | PostHog configuration options |
| posthogInstance | PostHog | Pre-initialized PostHog instance |
| DEBUG | boolean | Enable debug logging |
Best Practices
1. Use Event Types for User Identification
Use the appropriate event types instead of relying on specific event names:
// ✅ Good: Use event types
{
id: "USER_SIGNED_IN",
eventType: PosthogEventTypes.IDENTIFY,
properties: { /* ... */ }
}
// ❌ Bad: Don't rely on event names
// The plugin will call PostHog methods based on eventType, not event name2. Name Events Meaningfully
Since you can name events anything you want, use descriptive names that make sense for your business:
// Good: Business-specific event names
CUSTOMER_ONBOARDED: {
id: "CUSTOMER_ONBOARDED",
eventType: PosthogEventTypes.IDENTIFY,
// ...
},
ACCOUNT_MERGED: {
id: "ACCOUNT_MERGED",
eventType: PosthogEventTypes.ALIAS,
// ...
},
SESSION_EXPIRED: {
id: "SESSION_EXPIRED",
eventType: PosthogEventTypes.RESET,
// ...
}3. Use Unique Distinct IDs
Ensure each user has a unique distinct ID to avoid data merging:
// Good: Use database user ID
await service.publish("USER_SIGNED_IN", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: user.databaseId,
person_properties: userProperties,
anonymous_id: anonymousId,
},
},
},
});4. Always Reset on Logout
Even if users don't share computers, always publish a reset event on logout:
async function handleLogout() {
// Track logout event
await service.publish("USER_LOGOUT", { /* ... */ });
// Reset PostHog user
await service.publish("USER_SIGNED_OUT", { /* ... */ });
}5. Set Person Properties During Identification
Pass all available person properties during identification to keep user profiles up to date:
await service.publish("USER_SIGNED_IN", {
pluginData: {
PosthogPlugin: {
properties: {
distinct_id: user.id,
person_properties: {
email: user.email,
name: user.name,
subscription_tier: user.subscription,
signup_date: user.createdAt,
last_login: new Date().toISOString(),
},
anonymous_id: anonymousId,
},
},
},
});6. Use Flexible Plugin Data
The PostHOG plugin is designed to be flexible and user-friendly. You can send events with or without properties:
// With rich properties
await service.publish("BUTTON_CLICK", {
pluginData: {
PosthogPlugin: {
properties: {
button_name: "submit",
page: "checkout",
user_type: "premium"
},
},
},
});
// With minimal properties
await service.publish("PAGE_VIEW", {
pluginData: {
PosthogPlugin: {
properties: {},
},
},
});
// Or even simpler - the plugin works with minimal configuration
await service.publish("PAGE_VIEW", {
pluginData: {
PosthogPlugin: {},
},
});All events are sent to PostHOG regardless of whether plugin data is provided, making the plugin easy to use in various scenarios.
6. Handle Anonymous Users
Anonymous users can still generate events before identification:
// This works even for anonymous users
await service.publish("PAGE_VIEW", {
pluginData: {
PosthogPlugin: {
properties: {
page: "home",
referrer: document.referrer,
},
},
},
});API Reference
PosthogService Methods
| Method | Description |
|--------|-------------|
| publish(eventId, options?) | Publish an event to PostHog |
| getDistinctId() | Get the current user's distinct ID |
| isPostHogAvailable() | Check if PostHog is available and initialized |
Event Types
| Event Type | Description | PostHog Method Called |
|------------|-------------|----------------------|
| PosthogEventTypes.IDENTIFY | Identify a user with PostHog | posthog.identify() |
| PosthogEventTypes.RESET | Reset the current user (logout) | posthog.reset() |
| PosthogEventTypes.ALIAS | Alias a user (link multiple IDs) | posthog.alias() |
| PosthogEventTypes.CAPTURE | Regular PostHog event | posthog.capture() |
| PosthogEventTypes.ERROR | Error event | posthog.capture("$exception") |
Required Properties by Event Type
IDENTIFY Events
{
distinct_id: "string",
person_properties: "object",
anonymous_id: "string",
}RESET Events
{
previous_distinct_id: "string",
reset_device_id: "string",
}ALIAS Events
{
distinct_id: "string",
alias: "string",
}Types
interface PosthogPluginOptions {
POSTHOG_KEY?: string;
POSTHOG_HOST?: string;
config?: PosthogConfig;
posthogInstance?: PostHog;
DEBUG?: boolean;
}Examples
See the src/example/ directory for complete working examples including:
- Basic event publishing
- User identification workflow using event types
- Flexible event naming examples
- Login/logout management
- User property updates
- User aliasing
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
Apache-2.0
