Help Center

Data Connectors Posthog

PostHog Connector Setup Guide

This guide explains how to connect PostHog to Strand so events can be queried in place without copying raw data.

What this connector does

The PostHog connector lets Strand:

  • query PostHog events directly via the HogQL Query API,
  • map the PostHog events table to a Strand event schema,
  • auto-discover event names and property keys from your project, and
  • link each event back to a Strand account by domain or external ID.

Read-only and on-demand: Strand does not copy raw events into its database. Each report or signal triggers a fresh HogQL query against your PostHog project at run time.

Before you start

Make sure you have:

  • Admin or Owner access in your Strand organization (required to add/edit connectors).
  • A PostHog project you can authorize (PostHog Cloud or self-hosted).
  • The Project ID for that project.
  • A Personal API key with at least the query:read scope so HogQL queries succeed.

Where to find each value in PostHog

  • Host: the base URL of your PostHog instance.
    • PostHog Cloud (US): https://us.i.posthog.com
    • PostHog Cloud (EU): https://eu.i.posthog.com
    • Self-hosted: your own PostHog URL
  • Project ID: in PostHog, open Settings -> Project -> General. The numeric ID is shown near the top of the project settings.
  • Personal API key: in PostHog, open the user menu in the bottom-left and go to Account settings -> Personal API keys -> Create personal API key.
    • Give it a clear label, for example Strand.
    • Restrict scope to Read on Query (query:read) at minimum. Add project:read if you want a smoother test connection experience.
    • Limit the key to the project(s) you want Strand to read from.
    • Copy the generated phx_... value immediately. PostHog only shows it once.

Step 1: Connect (host, project, API key)

Open: Settings -> Connectors -> PostHog

  1. PostHog Host — paste your PostHog base URL (for example https://eu.i.posthog.com). Do not include a trailing slash or any path.
  2. Project ID — paste the numeric project ID.
  3. API Token — paste the personal API key (starts with phx_). Secrets are encrypted at rest.
  4. Click Test Connection — Strand runs a trivial SELECT 1 HogQL query against your project to confirm the host, project, and token are valid.
  5. Click Save.

Notes:

  • If the test fails, PostHog usually returns a clear error in the toast (for example invalid token, project not found, or insufficient scopes). Fix the cause and test again.
  • Only Admins and Owners can create or change the connector. Members can still see the connection status.

Step 2: Events

PostHog stores all events in a single events table, so this connector only supports the single-table layout. Once connected, open the Events step.

1) Scan the source

The Source table or view defaults to events. In almost all cases you should keep this value.

Click Scan Table. Strand runs two HogQL queries to learn your project:

  1. Top event names by volume (limit 20) — used to populate Known events.
  2. A 100-row sample to discover non-internal property keys (PostHog system properties starting with $ are excluded).

After the scan, you’ll see:

  • Time column = timestamp
  • Event name column = event
  • User ID column = distinct_id
  • Properties column = properties
  • A pre-filled list of Property mappings, each mapped to the HogQL expression properties['<key>'].

You can rerun Scan Table any time to refresh available events and property keys (for example after you ship new events in your product).

2) Account / domain source

This step decides how each event row links back to a Strand account.

Pick one of:

  • Company domain — the extracted value is treated as a company domain.
  • External ID — the extracted value is treated as an external customer ID and matched against externalCustomerId on the account.

Then choose the source of that value:

  • Column / property picker (default): pick from any discovered property or person field.
    • If a property like company_domain, account_domain, or org_domain was detected, Strand pre-selects it automatically.
    • If only an email property is available (for example email or person.properties.email), Strand will offer Extract domain from email, which wraps it with the HogQL expression:
      arrayElement(splitByString('@', coalesce(<email source>, '')), 2)
  • Use custom expression: for advanced cases, switch to expression mode and write HogQL directly. For example, to read a property from a Group:
    groups.0.properties.domain

Best practice: use the same matching style here as in your Accounts sync (HubSpot/Stripe/BigQuery), so events line up with the right accounts.

3) Property mappings

The mappings tell Strand how to reach each event property in HogQL. Defaults look like:

KeyExpression
planproperties['plan']
featureproperties['feature']
seats_usedproperties['seats_used']

You can:

  • Edit an expression in place — useful for casting, for example toInt(properties['seats_used']).
  • Add a new property by typing its key into the Add new property field. Strand fills the default expression properties.<key>; adjust as needed (most commonly properties['<key>']).
  • Remove a property you don’t want exposed.

4) Save

Click Save. The schema is stored on the connector and used the next time a metric, signal, or report runs.

HogQL tips

PostHog uses HogQL (a SQL-like dialect over ClickHouse). A few things that show up often when working with the PostHog connector:

  • Property access: properties['key'] is safer than properties.key for keys with dots, dashes, or spaces.
  • Person properties: read directly with person.properties.email (or any other person property). These are joined automatically by HogQL.
  • Email → domain: arrayElement(splitByString('@', coalesce(<email>, '')), 2).
  • Casting: toInt, toFloat, toDateTime etc. when a property is stored as a string but you need it as a number/date.

Validation rules you may hit

  • Host must be a full URL including scheme (https://...) and no path.
  • Project ID and API Token are both required to test or save the connection.
  • The connector requires an Account source before you can save the event schema. If you pick Company domain but no column/expression is set, save will fail with a clear error.
  • The Personal API key must include the query:read scope. Without it the test query is rejected by PostHog.

Troubleshooting

  • Test connection fails with 401/403: the API key is missing the query:read scope or is scoped to a different project. Generate a new key, restrict it to the right project, and include query:read.
  • Test connection fails with 404: the Project ID is wrong, or the host doesn’t match the region the project lives in (US vs EU).
  • Scan returns no events: the project has no events yet, or the API key only has access to a different project. Check the project in PostHog and confirm events are arriving.
  • Properties are missing after Scan: PostHog system properties (those starting with $ such as $current_url) are filtered out by design. Only custom properties appear.
  • Events don’t match accounts: check the Account / domain source.
    • Verify the property exists on the events that should match (run a quick SELECT properties FROM events LIMIT 5 in PostHog to confirm).
    • If using Extract domain from email, free email domains (gmail.com, outlook.com, …) won’t match a B2B company account.
  • Save is blocked with “no account source”: open the Account / domain source card and either pick a column or enter a custom expression.
  • I rotated the PostHog key: open the PostHog connector in Strand, re-enter the new token, click Save. The old encrypted value is replaced.