• Product
  • Pricing
  • Docs
  • Using PostHog
  • Community
  • Company
  • Login
  • Docs

  • Overview
    • Quickstart with PostHog Cloud
    • Overview
      • AWS
      • Azure
      • DigitalOcean
      • Google Cloud Platform
      • Hobby
      • Other platforms
      • Instance settings
      • Environment variables
      • Securing PostHog
      • Monitoring with Grafana
      • Running behind a proxy
      • Configuring email
      • Helm chart configuration
      • Deploying ClickHouse using Altinity.Cloud
      • Configuring Slack
      • Overview
        • Overview
        • Upgrade notes
        • Overview
        • 0001-events-sample-by
        • 0002_events_sample_by
        • 0003_fill_person_distinct_id2
        • ClickHouse
          • Backup
          • Kafka Engine
          • Resize disk
          • Restore
          • Vertical scaling
          • Horizontal scaling (Sharding & replication)
        • Kafka
          • Resize disk
          • Log retention
        • PostgreSQL
          • Resize disk
          • Troubleshooting long-running migrations
        • Plugin server
        • MinIO
        • Redis
        • Zookeeper
      • Disaster recovery
    • Troubleshooting and FAQs
    • Architecture
    • Managing hosting costs
    • EU-only hosting
    • Overview
    • Ingest live data
    • Ingest historical data
    • Identify users
    • User properties
    • Deploying a reverse proxy
    • Libraries
    • Badge
      • Snippet installation
      • Android
      • iOS
      • JavaScript
      • Flutter
      • React Native
      • Browser Extensions
      • Elixir
      • Go
      • Java
      • Node.js
      • PHP
      • Python
      • Ruby
      • Docusaurus v2
      • Gatsby
      • Google Tag Manager
      • Next.js
      • Nuxt.js
      • Retool
      • RudderStack
      • Segment
      • Sentry
      • Slack
      • Shopify
      • WordPress
      • Message formatting
      • Microsoft Teams
      • Slack
      • Discord
    • To another self-hosted instance
    • To PostHog from Amplitude
    • Between Cloud and self-hosted
    • Overview
    • Troubleshooting
      • Overview
      • Tutorial
      • TypeScript types
      • Developer reference
        • Amazon Kinesis Import
        • BitBucket Release Tracker
        • Braze Import
        • Event Replicator
        • GitHub Release Tracker
        • GitHub Star Sync
        • GitLab Release Tracker
        • Heartbeat
        • Ingestion Alert
        • Email Scoring
        • n8n Connector
        • Orbit Connector
        • Redshift Import
        • Segment Connector
        • Shopify Connector
        • Twitter Followers Tracker
        • Zendesk Connector
        • Airbyte Exporter
        • Amazon S3 Export
        • BigQuery Export
        • Customer.io Connector
        • Databricks Export
        • Engage Connector
        • GCP Pub/Sub Connector
        • Google Cloud Storage Export
        • Hubspot Connector
        • Intercom Connector
        • Migrator 3000
        • PagerDuty Connector
        • PostgreSQL Export
        • Redshift Export
        • RudderStack Export
        • Salesforce Connector
        • Sendgrid Connector
        • Sentry Connector
        • Snowflake Export
        • Twilio Connector
        • Variance Connector
        • Zapier Connector
        • Downsampler
        • Event Sequence Timer
        • First Time Event Tracker
        • Property Filter
        • Property Flattener
        • Schema Enforcer
        • Taxonomy Standardizer
        • Unduplicator
        • Automatic Cohort Creator
        • Currency Normalizer
        • GeoIP Enricher
        • Timestamp Parser
        • URL Normalizer
        • User Agent Populator
    • Overview
    • POST-only public endpoints
    • Actions
    • Annotations
    • Cohorts
    • Dashboards
    • Event definitions
    • Events
    • Experiments
    • Feature flags
    • Funnels
    • Groups
    • Groups types
    • Insights
    • Invites
    • Members
    • Persons
    • Plugin configs
    • Plugins
    • Projects
    • Property definitions
    • Session recordings
    • Trends
    • Users
    • Data model
    • Overview
    • GDPR guidance
    • HIPAA guidance
    • CCPA guidance
    • Data egress & compliance
    • Overview
    • Code of conduct
    • Recognizing contributions
  • Using PostHog

  • Table of contents
      • Dashboards
      • Funnels
      • Group Analytics
      • Insights
      • Lifecycle
      • Path analysis
      • Retention
      • Stickiness
      • Trends
      • Heatmaps
      • Session Recording
      • Correlation Analysis
      • Experimentation
      • Feature Flags
      • Actions
      • Annotations
      • Cohorts
      • Data Management
      • Events
      • Persons
      • Sessions
      • UTM segmentation
      • Team collaboration
      • Organizations & projects
      • Settings
      • SSO & SAML
      • Toolbar
      • Notifications & alerts
  • Tutorials
    • All tutorials
    • Actions
    • Apps
    • Cohorts
    • Dashboards
    • Feature flags
    • Funnels
    • Heatmaps
    • Path analysis
    • Retention
    • Session recording
    • Trends
  • Support
  • Docs

  • Overview
    • Quickstart with PostHog Cloud
    • Overview
      • AWS
      • Azure
      • DigitalOcean
      • Google Cloud Platform
      • Hobby
      • Other platforms
      • Instance settings
      • Environment variables
      • Securing PostHog
      • Monitoring with Grafana
      • Running behind a proxy
      • Configuring email
      • Helm chart configuration
      • Deploying ClickHouse using Altinity.Cloud
      • Configuring Slack
      • Overview
        • Overview
        • Upgrade notes
        • Overview
        • 0001-events-sample-by
        • 0002_events_sample_by
        • 0003_fill_person_distinct_id2
        • ClickHouse
          • Backup
          • Kafka Engine
          • Resize disk
          • Restore
          • Vertical scaling
          • Horizontal scaling (Sharding & replication)
        • Kafka
          • Resize disk
          • Log retention
        • PostgreSQL
          • Resize disk
          • Troubleshooting long-running migrations
        • Plugin server
        • MinIO
        • Redis
        • Zookeeper
      • Disaster recovery
    • Troubleshooting and FAQs
    • Architecture
    • Managing hosting costs
    • EU-only hosting
    • Overview
    • Ingest live data
    • Ingest historical data
    • Identify users
    • User properties
    • Deploying a reverse proxy
    • Libraries
    • Badge
      • Snippet installation
      • Android
      • iOS
      • JavaScript
      • Flutter
      • React Native
      • Browser Extensions
      • Elixir
      • Go
      • Java
      • Node.js
      • PHP
      • Python
      • Ruby
      • Docusaurus v2
      • Gatsby
      • Google Tag Manager
      • Next.js
      • Nuxt.js
      • Retool
      • RudderStack
      • Segment
      • Sentry
      • Slack
      • Shopify
      • WordPress
      • Message formatting
      • Microsoft Teams
      • Slack
      • Discord
    • To another self-hosted instance
    • To PostHog from Amplitude
    • Between Cloud and self-hosted
    • Overview
    • Troubleshooting
      • Overview
      • Tutorial
      • TypeScript types
      • Developer reference
        • Amazon Kinesis Import
        • BitBucket Release Tracker
        • Braze Import
        • Event Replicator
        • GitHub Release Tracker
        • GitHub Star Sync
        • GitLab Release Tracker
        • Heartbeat
        • Ingestion Alert
        • Email Scoring
        • n8n Connector
        • Orbit Connector
        • Redshift Import
        • Segment Connector
        • Shopify Connector
        • Twitter Followers Tracker
        • Zendesk Connector
        • Airbyte Exporter
        • Amazon S3 Export
        • BigQuery Export
        • Customer.io Connector
        • Databricks Export
        • Engage Connector
        • GCP Pub/Sub Connector
        • Google Cloud Storage Export
        • Hubspot Connector
        • Intercom Connector
        • Migrator 3000
        • PagerDuty Connector
        • PostgreSQL Export
        • Redshift Export
        • RudderStack Export
        • Salesforce Connector
        • Sendgrid Connector
        • Sentry Connector
        • Snowflake Export
        • Twilio Connector
        • Variance Connector
        • Zapier Connector
        • Downsampler
        • Event Sequence Timer
        • First Time Event Tracker
        • Property Filter
        • Property Flattener
        • Schema Enforcer
        • Taxonomy Standardizer
        • Unduplicator
        • Automatic Cohort Creator
        • Currency Normalizer
        • GeoIP Enricher
        • Timestamp Parser
        • URL Normalizer
        • User Agent Populator
    • Overview
    • POST-only public endpoints
    • Actions
    • Annotations
    • Cohorts
    • Dashboards
    • Event definitions
    • Events
    • Experiments
    • Feature flags
    • Funnels
    • Groups
    • Groups types
    • Insights
    • Invites
    • Members
    • Persons
    • Plugin configs
    • Plugins
    • Projects
    • Property definitions
    • Session recordings
    • Trends
    • Users
    • Data model
    • Overview
    • GDPR guidance
    • HIPAA guidance
    • CCPA guidance
    • Data egress & compliance
    • Overview
    • Code of conduct
    • Recognizing contributions
  • Using PostHog

  • Table of contents
      • Dashboards
      • Funnels
      • Group Analytics
      • Insights
      • Lifecycle
      • Path analysis
      • Retention
      • Stickiness
      • Trends
      • Heatmaps
      • Session Recording
      • Correlation Analysis
      • Experimentation
      • Feature Flags
      • Actions
      • Annotations
      • Cohorts
      • Data Management
      • Events
      • Persons
      • Sessions
      • UTM segmentation
      • Team collaboration
      • Organizations & projects
      • Settings
      • SSO & SAML
      • Toolbar
      • Notifications & alerts
  • Tutorials
    • All tutorials
    • Actions
    • Apps
    • Cohorts
    • Dashboards
    • Feature flags
    • Funnels
    • Heatmaps
    • Path analysis
    • Retention
    • Session recording
    • Trends
  • Support
  • Docs
  • Integrate PostHog
  • Client libraries
  • React Native

React Native library

Last updated: Aug 04, 2022

On this page

  • Installation
  • Configuration
  • Usage
  • Autocapture
  • Identify
  • Capture
  • Setting user properties via an event
  • $set
  • $set_once
  • Super Properties
  • Removing stored Super Properties
  • Flush
  • Reset
  • Opt in/out
  • Feature Flags
  • Group analytics
  • Sending screen views
  • Upgrading from V1 to V2
Which features are available in this library?
  • AvailableEvent capture
  • AvailableAutocapture
  • AvailableUser identification
  • Not availableSession recording
  • AvailableFeature flags
  • AvailableGroup analytics

Purely built for React Native, this library allows you to integrate PostHog with your React Native project. For React Native projects built with Expo, there are no mobile native dependencies outside of supported Expo packages.

Installation

In your React Native or Expo project add the posthog-react-native package to your project as well as the required peer dependencies.

# React Native
yarn add posthog-react-native expo-file-system expo-application expo-device expo-localization
# Expo
expo install posthog-react-native expo-file-system expo-application expo-device expo-localization

Configuration

The recommended flow for sertting up PostHog React Native is to use the PostHogProvider which utilises the Context API to pass posthog around as well as enabling autocapture and ensuring that the queue is flushed at the right time:

// App.(js|ts)
import PostHog, { usePostHog } from 'posthog-react-native'
...
export function MyApp() {
return (
<PostHogProvider apiKey="<ph_project_api_key>" options={{
// PostHog API host (https://app.posthog.com by default)
host: '<ph_instance_address>',
}}>
<MyComponent />
</PostHogProvider>
)
}
// The rest of this documentation assumes you are using the `PostHogProvider`
// and as such can utilise the `usePostHog` hook as follows:
const MyComponent = () => {
const posthog = usePostHog()
useEffect(() => {
posthog.capture("MyComponent loaded", { foo: "bar" })
}, [])
}

Alternatively you can simply create a global instance of PostHog with your API Key and any options. This allows you to use PostHog outside of the PostHogProvider but limits the functionality of PostHog (such as autocapture).

// posthog.js
import PostHog from 'posthog-react-native'
export const posthog = new PostHog("<ph_project_api_key>", {
// PostHog API host (https://app.posthog.com by default)
host: '<ph_instance_address>',
})
// app.js
import posthog from './posthog'
posthog.identify("example@posthog.com")
// You can even use this instance with the PostHogProvider
export function MyApp() {
return (
<PostHogProvider client={posthog}>
{/* Your app code */}
</PostHogProvider>
)
}

For most people, the default configuration options will work great but if you need to you can further customise how PostHog will work.

export const posthog = new PostHog("<ph_project_api_key>", {
// PostHog API host
host?: string = "https://app.posthog.com",
// The number of events to queue before sending to Posthog (flushing)
flushAt?: number = 20,
// The interval in milliseconds between periodic flushes
flushInterval?: number = 10000
// If set to false, tracking will be disabled until `optIn` is called
enable?: boolean = true,
// Whether to track that `getFeatureFlag` was called (used by Expriements)
sendFeatureFlagEvent?: boolean = true,
// Whether to load feature flags when initialised or not
preloadFeatureFlags?: boolean = true,
// How many times we will retry HTTP requests
fetchRetryCount?: number = 3,
// The delay between HTTP request retries
fetchRetryDelay?: number = 3000,
// For Session Analysis how long before we expire a session
sessionExpirationTimeSeconds?: number = 1800 // 30 mins
// Whether to post events to PostHog in JSON or compressed format
captureMode?: 'json' | 'form'
})

Usage

Autocapture

Autocapture tracks these events:

  • Application Opened - once when the App is opened from a closed state
  • Application Became Active - when the App comes to the foreground (e.g. from the app switcher)
  • Application Backgrounded - when the App is sent to the background by the user
  • Keyboard Shown - when the keyboard appears for user input
  • Keyboard Hidden - when the keyboard is dismissed from user input
  • $screen - when the user navigates (if using @react-navigation/native)
  • $autocapture - touch events when the user interacts with the screen

With Autocapture, all touch events for children of PosthogProvider will be tracked, capturing a snapshot of the view hierarchy at that point. This allows you to create Insights in PostHog without having to add many custom events.

PostHog will try to generate a sensible name for the touched element based on the React component displayName or name but you can force this to something reliable (and also clearly marked for posthog tracking) using the ph-label prop.

<View ph-label="my-special-label"></View>

If there are elements you don't want to be captured, you can add the ph-no-capture property like so. If this property is found anywhere in the view hierarchy, the entire touch event is ignored.

<View ph-no-capture>Sensitive view here</View>

Basic usage:

// App.(js|ts)
import PostHog from 'posthog-react-native'
import {NavigationContainer} from '@react-navigation/native';
export function App() {
return (
<NavigationContainer>
<PostHogProvider apiKey="<ph_project_api_key>" autocapture>
{/* Rest of app */}
</PostHogProvider>
</NavigationContainer>
)
}

You can tweak how autocapture works by passing custom options.

<PostHogProvider apiKey="<ph_project_api_key>" autocapture={{
captureTouches: true, // If you don't want to capture touch events set this to false
ignoreLabels: [], // Any labels here will be ignored from the stack in touch events
customLabelProp: "ph-label",
noCaptureProp: "ph-no-capture",
navigation: {
// By default only the Screen name is tracked but it is possible to track the
// params or modify the name by intercepting theautocapture like so
routeToName: (name, params) => {
if (params.id) return `${name}/${params.id}`
return name
},
routeToParams: (name, params) => {
if (name === "SensitiveScreen) return undefined
return params
},
}
}}>
...
</PostHogProvider>

Identify

We highly recommend reading our section on Identifying users to better understand how to correctly use this method.

When you start tracking events with PostHog, each user gets an anonymous ID that is used to identify them in the system. In order to link this anonymous user with someone from your database, use the identify call.

Identify lets you add metadata on your users so you can more easily identify who they are in PostHog, and even do things like segment users by these properties.

An identify call requires:

  • distinctId which uniquely identifies your user in your database
  • userProperties with a dictionary with key: value pairs
posthog.identify('distinctID', {
email: 'user@posthog.com',
name: 'My Name'
})

The most obvious place to make this call is whenever a user signs up, or when they update their information.

When you call identify, all previously tracked anonymous events will be linked to the user.

Capture

Capture allows you to capture anything a user does within your system, which you can later use in PostHog to find patterns in usage, work out which features to improve or where people are giving up.

A capture call requires:

  • event to specify the event name
    • We recommend naming events with "[noun][verb]", such as movie played or movie updated, in order to easily identify what your events mean later on (we know this from experience).

Optionally you can submit:

  • properties, which is an object with any information you'd like to add

For example:

posthog.capture('Button B Clicked', {
color: "blue",
icon: "new2-final"
})

Setting user properties via an event

When capturing an event, you can pass a property called $set as an event property, and specify its value to be an object with properties to be set on the user that will be associated with the user who triggered the event.

$set

Example

posthog.capture('some event', { $set: { userProperty: 'value' } })

Usage

When capturing an event, you can pass a property called $set as an event property, and specify its value to be an object with properties to be set on the user that will be associated with the user who triggered the event.

$set_once

Example

posthog.capture('some event', { $set_once: { userProperty: 'value' } })

Usage

$set_once works just like $set, except that it will only set the property if the user doesn't already have that property set.

Super Properties

Super Properties are properties associated with events that are set once and then sent with every capture call, be it a $screen, an autocaptured touch, or anything else.

They are set using posthog.register, which takes a properties object as a parameter, and they persist across sessions.

For example, take a look at the following call:

posthog.register({
'icecream pref': 'vanilla',
team_id: 22,
})

The call above ensures that every event sent by the user will include "icecream pref": "vanilla" and "team_id": 22. This way, if you filtered events by property using icecream_pref = vanilla, it would display all events captured on that user after the posthog.register call, since they all include the specified Super Property.

However, please note that this does not store properties against the User, only against their events. To store properties against the User object, you should use posthog.identify. More information on this can be found on the Sending User Information section.

Removing stored Super Properties

Super Properties are persisted across sessions so you have to explicitly remove them if they are no longer relevant. In order to stop sending a Super Property with events, you can use posthog.unregister, like so:

posthog.unregister('icecream pref'),

This will remove the Super Property and subsequent events will not include it.

If you are doing this as part of a user logging out you can instead simply use posthog.reset which takes care of clearing all stored Super Properties and more.

Flush

You can set the number of events in the configuration that should queue before flushing. Setting this to 1 will send events immediately and will use more battery. This is set to 20 by default.

You can also configure the flush interval. By default we flush all events after 30 seconds, no matter how many events have gathered.

You can also manually flush the queue, like so:

posthog.flush()
// or using async/await
await posthog.flushAsync()

Reset

To reset the user's ID and anonymous ID, call reset. Usually you would do this right after the user logs out.

posthog.reset()

Opt in/out

By default, PostHog has tracking enabled unless it is forcefully disabled by default using the option { enable: false }.

You can give your users the option to opt in or out by calling the relevant methods. Once these have been called they are persisted and will be respected until optIn/Out is called again or the reset function is called.

To Opt in/out of tracking, use the following calls.

posthog.optIn() // opt in
posthog.optOut() // opt out

If you still wish capture these events but want to create a distinction between users and team in PostHog, you should look into Cohorts.

Feature Flags

Feature Flags can be loaded directly or via a helpful hook

import { useFeatureFlag } from "posthog-react-native"
const MyComponent = () => {
const showFlaggedFeature = useFeatureFlag("my-flag-id")
const multiVariantFeature = useFeatureFlag("my-multivariant-feature-flag-id")
if (showFlaggedFeature === undefined) {
// the response is undefined if the flags are being loaded
return null
}
return showFlaggedFeature ? (
<Text>Testing feature 😄</Text>
) : (
<Text>Not Testing feature 😢</Text>
)
}

Alternatively you can call load the feature flags directly:

// Defaults to undefined if not loaded yet or if there was a problem loading
posthog.getFeatureFlag("my-flag")
// Provide an optional default if the flags are not loaded
posthog.getFeatureFlag("my-flag", false)
// Multi variant feature flags are returned as a string
posthog.getFeatureFlag("my-multivariant-flag", "control")

PostHog will load feature flags when instantiated and will refresh whenever other methods are called that could affect the flag such as .group(). If you have the need to forcefully trigger the refresh however you can use reloadFeatureFlagsAsync

posthog.reloadFeatureFlagsAsync()
.then(refreshedFlags => console.log(refreshedFlags))

Group analytics

PostHog 1.31.0 introduced support for group analytics, which allows you to associate users and events with larger groups (teams, organizations, etc.).

Note: This is a paid feature and is not available on the open-source or free cloud plan. Learn more here.

  • Make a group active and update properties
posthog.group('company', 'id:5', {
company_name: 'Awesome Inc.',
employees: 11,
})
  • Make a group active without updating properties
posthog.group('company', 'id:77')

Once a group has been made active, all subsequent events that are sent using the client will be associated with that group automatically.

Sending screen views

With the PostHogProvider, screen tracking is automatically captured if the autocapture property is used. Currently only @react-navigation/native is supported by autocapture and it is important that the PostHogProvider is configured as a child of the NavigationContainer as below:

See autocapture for configuration.

If you want to manually send a new screen capture event, use the screen function. This function requires a name. You may also pass in an optional properties object.

posthog.screen('Dashboard', {
background: 'blue',
hero: 'superhog',
})

Upgrading from V1 to V2

V1 of this library utilised the underlying posthog-ios and posthog-android SDKs to do most of the work. Since the new version is written entirely in JS, using only Expo supported libraries, there are some changes to the way PostHog is configured as well as actually calling PostHog.

For iOS, the new React Native SDK will attempt to migrate the previously peristed data which should result in no unexpected changes to tracked data.

For Android, it is unfortunately not possible for persisted Android data to be loaded which means stored information such as the randomly generated anonymousId or the distinctId set by posthog.identify will not be present. For identified users, the simple workaround is to ensure that identify is called at least once when the app loads. For anonymous users there is unfortunately no straightforward workaround they will show up as new anonymous users in PostHog.

// DEPRECATED V1 Setup
import PostHog from 'posthog-react-native'
await PostHog.setup('phc_ChmcdLbC770zgl23gp3Lax6SERzC2szOUxtp0Uy4nTf', {
host: 'https://app.posthog.com',
captureApplicationLifecycleEvents: false, // Replaced by `PostHogProvider`
captureDeepLinks: false, // No longer supported
recordScreenViews: false, // Replaced by `PostHogProvider` supporting @react-navigation/native
flushInterval: 30, // Stays the same
flushAt: 20, // Stays the same
android: {...}, // No longer needed
iOS: {...}, // No longer needed
})
PostHog.capture("foo")
// V2 Setup difference
import PostHog from 'posthog-react-native'
const posthog = new PostHog('phc_ChmcdLbC770zgl23gp3Lax6SERzC2szOUxtp0Uy4nTf', {
host: 'https://app.posthog.com',
// Add any other options here.
})
// Use created instance rather than the PostHog class
posthog.capture("foo")

Questions?

Was this page useful?

Next article

Product analytics for browser extensions

Do you have a Firefox or Chrome browser plugin with a user interface and want to understand how it's being used? PostHog is the perfect way to do just that. Setup for Firefox & Chrome plugins Installing PostHog inside your plugin Open the HTML file used in your default_popup and add the PostHog array.js script. To do this you'll need to either: Copy the latest version of array.js from: https://app.posthog.com/static/array.js and import it locally using <script src="array.js" /> before…

Read next article

Authors

  • Eli Kinsey
    Eli Kinsey
  • Ben White
    Ben White
  • pjhul
    pjhul

Share

Jump to:

  • Installation
  • Configuration
  • Usage
  • Autocapture
  • Identify
  • Capture
  • Super Properties
  • Flush
  • Reset
  • Opt in/out
  • Feature Flags
  • Group analytics
  • Sending screen views
  • Upgrading from V1 to V2
  • Questions?
  • Edit this page
  • Raise an issue
  • Toggle content width
  • Toggle dark mode
  • About
  • Blog
  • Newsletter
  • Careers
  • Support
  • Contact sales

Product OS suite

Product overview

Analytics
  • Funnels
  • Trends
  • Paths

Pricing

Features
  • Session recording
  • Feature flags
  • Experimentation
  • Heatmaps

Customers

Platform
  • Correlation analysis
  • Collaboration
  • Apps

Community

Discussion
  • Questions?
  • Slack
  • Issues
  • Contact sales
Get involved
  • Roadmap
  • Contributors
  • Merch
  • PostHog FM
  • Marketplace

Docs

Getting started
  • PostHog Cloud
  • Self-hosted
  • Compare options
  • Tutorials
  • PostHog on GitHub
Install & integrate
  • Installation
  • Docs
  • API
  • Apps
User guides
  • Cohorts
  • Funnels
  • Sessions
  • Data
  • Events

Company

About
  • Our story
  • Team
  • Handbook
  • Investors
  • Careers
Resources
  • FAQ
  • Ask a question
  • Blog
  • Press
  • Merch
  • YouTube
© 2022 PostHog, Inc.
  • Code of conduct
  • Privacy
  • Terms