Skip to content

PostHog

PostHog is used for product analytics, feature flags, funnels, A/B testing, and session recordings.

AppIntegrated
UK
DE

PostHog can be integrated via JavaScript Web SDK. An overview of the integration methods can be found via the links below:

An overview of the debugging tools can be found via the links below:

Before integrating PostHog, note the following:

  • Feature flags may require early initialization.
  • The provider only loads the PostHog SDK in the browser after the configured consent requirements are met.
  • The PostHog project API key is safe to expose in client bundles, but it should still be configured as a public build variable.

The @releafuk/analytics package provides a custom PostHog plugin through the postHogProvider() factory function. PostHog is integrated through the posthog-js browser SDK.

The postHogProvider() factory accepts the config parameter that should satisfy the PostHogConfig type:

import type { PostHogConfig as PackagePostHogConfig } from "posthog-js";
type PostHogConfig = {
apiKey: string;
enabled?: boolean;
postHogConfig?: Partial<PackagePostHogConfig>;
};
OptionRequiredDefaultDescription
apiKeyYes-PostHog project API key
enabledNotrueControls whether the provider loads and initializes PostHog. Use false to keep the provider registered but disabled for an environment.
postHogConfigNoSee belowPostHog initialization configuration

The postHogConfig object is passed to the PostHog posthog.init() call during provider initialization. See the PostHog documentation for the JavaScript Web SDK configuration. postHogProvider() factory provides a default set of configuration rules:

OptionDefaultDescription
api_hosthttps://eu.posthog.comURL of the PostHog instance.
defaults2026-05-30Configuration defaults for breaking changes.
capture_pageviewhistory_changeEnables PostHog automatic page-view capture based on path changes by listening to the browser’s history API.
person_profilesidentified_onlyAnonymous events are captured by default. PostHog only captures identified events for users where person profiles have already been created.

The capture_pageview option determines how page views are handled:

  • capture_pageview: "history_change" uses PostHog automatic page-view tracking for browser navigation changes. The custom PostHog page() implementation does not send another event when analytics.page() is called.
  • capture_pageview: false disables automatic page views. The custom PostHog page() implementation runs when analytics.page() is called and sends a $pageview event.

Use capture_pageview: false when the application controls navigation or needs to send page views manually. Disabling the automatic page view avoids duplicate $pageview events.

postHogProvider({
apiKey: import.meta.env.PUBLIC_POSTHOG_API_KEY,
postHogConfig: {
api_host: "https://eu.posthog.com",
capture_pageview: false,
},
});

Define PostHog event parameters under the postHog provider key, then register postHogProvider() when creating the analytics service:

import {
createAnalyticsService,
createEvent,
createEventDefinition,
createEventRegistry,
postHogProvider,
} from "@releafuk/analytics";
const navigationItemClicked = createEvent<
{
item: string;
location: "header" | "footer";
},
"NavigationItemClicked"
>({
name: "NavigationItemClicked",
});
const events = createEventRegistry().register(
createEventDefinition(navigationItemClicked, {
providers: {
postHog: (data) => ({
event: "Navigation item clicked",
params: {
item: data.item,
location: data.location,
},
}),
},
}),
);
export const analytics = createAnalyticsService({
app: "releaf",
events,
providers: [
postHogProvider({
apiKey: import.meta.env.PUBLIC_POSTHOG_API_KEY,
postHogConfig: {
person_profiles: "always",
},
}),
],
consent: {
default: {
analytics: "denied",
advertising: "denied",
functionality: "denied",
adUserData: "denied",
adPersonalization: "denied",
},
},
});
await analytics.init();

It is recommended to use a [object] [verb] format for the event names, where [object] is the entity that the behavior relates to, and [verb] is the behavior itself. For example, project created, user signed up, or invite sent.

Identify users after authentication or profile loading:

await analytics.identify({
userId: user.id,
traits: {
email: user.email,
plan: user.plan,
},
});

Access the underlying PostHog client when a feature requires SDK-specific APIs, such as feature flags:

const postHogProviderInstance = postHogProvider({
apiKey: import.meta.env.PUBLIC_POSTHOG_API_KEY,
});
export const analytics = createAnalyticsService({
// ...
providers: [postHogProviderInstance],
});
const postHog = postHogProviderInstance.getClient?.();
if (postHog?.isFeatureEnabled("new-checkout")) {
// Do something
}