> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nekt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PostHog as a data source

> Bring data from PostHog to Nekt.

PostHog is a product analytics platform for tracking user behavior, product usage, and event-level activity. The Nekt PostHog connector extracts project metadata and event data into your Catalog so you can analyze product engagement at scale.

<img width="200" src="https://mintcdn.com/nekt/qNX7k_BCmHZOh4kd/assets/logo/logo-posthog.png?fit=max&auto=format&n=qNX7k_BCmHZOh4kd&q=85&s=13150b1663cc4c6dd458de8bf99d63c2" data-path="assets/logo/logo-posthog.png" />

## Configuring PostHog as a Source

In the [Sources](https://app.nekt.ai/sources) tab, click on the "Add source" button located on the top right of your screen. Then, select the **PostHog** option from the list of connectors.

Click **Next** and you'll be prompted to add your access.

### 1. Add account access

The following configurations are available:

* **Personal API key**: Personal API key used to authenticate against the PostHog API. See the [official PostHog API docs](https://posthog.com/docs/api).
* **Base URL**: API base URL for your PostHog region or self-hosted environment.
  * US Cloud: `https://us.posthog.com`
  * EU Cloud: `https://eu.posthog.com`
  * Self-hosted: your own PostHog domain
* **Start date**: Earliest date from which events are synced (e.g., `YYYY-MM-DD`). This date acts as a strict lower bound for your data: even if you choose a **FULL\_TABLE** sync type, the connector will honor this configured start date as the starting boundary (using it as the `after` parameter), ensuring you don't inadvertently pull the entire workspace history.

<Warning>Event payloads can be large. Choosing a very old start date may significantly increase the first sync duration.</Warning>

Once you're done, click **Next**.

### 2. Select streams

Choose which data streams you want to sync. For faster extractions, select only the streams relevant to your analysis.

> Tip: In addition to the `projects` stream, the connector creates one dynamic event stream per PostHog project using the pattern `{organization_slug}_events_{project_name}`.

Select the streams and click **Next**.

### 3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired layer where the data will be placed, a folder to organize it inside the layer, a name for each table, and the type of sync.

* **Layer**: Choose the layer where extracted PostHog tables will be created.
* **Folder**: Optionally group all PostHog tables inside a folder.
* **Table name**: A default name is suggested, but you can customize it and optionally apply a prefix.
* **Sync Type**: Choose between **INCREMENTAL** and **FULL\_TABLE**.
  * **Incremental**: Recommended for event streams, using `timestamp` as the replication key.
  * **Full table**: Suitable for `projects` metadata refreshes.

Once you are done configuring, click **Next**.

### 4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters.

To define your [Trigger](https://docs.nekt.com/runs/scheduling-and-triggers), consider how often your product analytics data should be refreshed.

Optionally, you can define:

* **Delta Log Retention**: How long Nekt keeps previous table states. See [Resource control](https://docs.nekt.com/get-started/core-concepts/resource-control).
* **Additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync)**: Periodic full syncs to complement incremental runs.

When you are ready, click **Next** to finalize the setup.

### 5. Check your new source

You can view your new source on the [Sources](https://app.nekt.ai/sources) page. If needed, manually trigger the extraction by clicking on the arrow button. Once a run completes successfully, your data appears in the Catalog.

<Warning>You need at least one successful source run to see the tables in your [Catalog](https://app.nekt.ai/catalog).</Warning>

# Streams and Fields

Below you'll find the available PostHog streams and their core fields.

<AccordionGroup>
  <Accordion title="Projects">
    Project metadata for each organization available to the API token.

    **Key fields:**

    * `id` - Project identifier (primary key)
    * `uuid` - Project UUID
    * `organization` - Organization identifier linked to the project
    * `name` - Project name
    * `api_token` - Project ingestion token
    * `timezone` - Project default timezone
    * `is_demo` - Indicates whether the project is a demo project
    * `ingested_event` - Indicates whether at least one event has been ingested
    * `completed_snippet_onboarding` - Onboarding status for snippet setup
    * `has_completed_onboarding_for.feature_flags` - Feature flags onboarding status
    * `access_control` - Access-control enablement flag

    **Notes:**

    * Stream name: `projects`
    * Primary key: `id`
    * Replication: full-table style (no replication key)
  </Accordion>

  <Accordion title="Events (dynamic per project)">
    Event-level analytics data from each PostHog project. The connector dynamically creates one stream per project discovered during catalog discovery.

    **Dynamic stream naming:**

    * `{organization_slug}_events_{project_name}` (slugified with underscores)

    **Key fields:**

    * `id` - Event identifier
    * `distinct_id` - User or actor distinct identifier
    * `event` - Event name
    * `timestamp` - Event timestamp (replication key)
    * `properties` - Array of key/value event properties
    * `person.is_identified` - Whether associated person is identified
    * `person.distinct_ids` - Associated person distinct IDs
    * `person.properties.email` - Associated person email (when available)
    * `elements` - Captured element metadata
    * `elements_chain` - Serialized captured element chain

    **Notes:**

    * Primary keys: `id`, `distinct_id`
    * Replication key: `timestamp`
    * Incremental sync uses `start_date` for the first run, then continues from saved state
  </Accordion>
</AccordionGroup>

# Data Model

The connector follows an organization/project-based model:

```mermaid theme={null}
graph TD;
    Projects["projects"];
    Events["{organization_slug}_events_{project_name}"];

    Projects -- "project id / project scope" --> Events;
```

# Use Cases for Data Analysis

This section includes practical SQL examples you can run in [Explorer](https://app.nekt.ai/explorer).

### 1. Event volume by day

Measure daily event volume to track product activity trends.

<Accordion title="SQL query">
  <Tabs>
    <Tab title="AWS">
      ```sql theme={null}
      SELECT
         DATE(CAST(timestamp AS timestamp)) AS event_date,
         event,
         COUNT(*) AS total_events,
         COUNT(DISTINCT distinct_id) AS unique_users
      FROM
         nekt_raw.posthog_org_events_project
      GROUP BY
         1,
         2
      ORDER BY
         event_date DESC,
         total_events DESC;
      ```
    </Tab>

    <Tab title="GCP">
      ```sql theme={null}
      SELECT
         DATE(TIMESTAMP(timestamp)) AS event_date,
         event,
         COUNT(*) AS total_events,
         COUNT(DISTINCT distinct_id) AS unique_users
      FROM
         `nekt_raw.posthog_org_events_project`
      GROUP BY
         1,
         2
      ORDER BY
         event_date DESC,
         total_events DESC;
      ```
    </Tab>
  </Tabs>
</Accordion>

### 2. Top users by event activity (last 30 days)

Identify the most active users based on tracked events.

<Accordion title="SQL query">
  <Tabs>
    <Tab title="AWS">
      ```sql theme={null}
      SELECT
         distinct_id,
         COUNT(*) AS event_count,
         MIN(CAST(timestamp AS timestamp)) AS first_event_at,
         MAX(CAST(timestamp AS timestamp)) AS last_event_at
      FROM
         nekt_raw.posthog_org_events_project
      WHERE
         CAST(timestamp AS timestamp) >= current_timestamp - interval '30' day
      GROUP BY
         1
      ORDER BY
         event_count DESC
      LIMIT 100;
      ```
    </Tab>

    <Tab title="GCP">
      ```sql theme={null}
      SELECT
         distinct_id,
         COUNT(*) AS event_count,
         MIN(TIMESTAMP(timestamp)) AS first_event_at,
         MAX(TIMESTAMP(timestamp)) AS last_event_at
      FROM
         `nekt_raw.posthog_org_events_project`
      WHERE
         TIMESTAMP(timestamp) >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
      GROUP BY
         1
      ORDER BY
         event_count DESC
      LIMIT 100;
      ```
    </Tab>
  </Tabs>
</Accordion>

# Implementation Notes

### Data Sync Behavior

* **Full Table Syncs and Start Date**: The connector explicitly enforces the configured **Start date** even during `FULL_TABLE` syncs. When starting a full refresh where no prior extraction state is present, the API request falls back to the configured start date as the absolute lower boundary. This prevents the connector from ignoring bounds and inadvertently pulling the entire history of your PostHog workspace.
* **Pagination and Limits**: The `events` stream requests are paginated in batches of 1000 items and bounded by dynamic timestamp values to ensure reliable extraction without triggering API timeouts.

## Skills for agents

<Snippet file="agent-skills-intro.mdx" />

<Card title="Download PostHog skills file" icon="wand-magic-sparkles" href="/sources/posthog.md">
  PostHog connector documentation as plain markdown, for use in AI agent contexts.
</Card>
