PostHog Connector

Connect PostHog to Brevo through Tajo to sync product analytics data, user behavior events, and cohort memberships for data-driven marketing campaigns and personalized customer engagement.

Overview

PropertyValue
PlatformPostHog
CategoryProduct Analytics (Custom)
Setup ComplexityMedium
Official IntegrationNo
Data SyncedEvents, Persons, Feature Flags, Cohorts
Auth MethodPersonal API Key / Project Token

Features

  • Event sync - Forward PostHog analytics events to Brevo for behavioral targeting
  • Person profile sync - Sync PostHog person properties to Brevo contact attributes
  • Cohort-based segmentation - Map PostHog cohorts to Brevo contact lists
  • Feature flag sync - Segment contacts by enabled feature flags
  • Funnel data - Use conversion funnel data for targeted re-engagement
  • Session replay metadata - Enrich contacts with session engagement metrics

Prerequisites

Before you begin, ensure you have:

  1. A PostHog account (Cloud or self-hosted)
  2. A Personal API Key from PostHog Settings
  3. Your Project API Key (token) from Project Settings
  4. A Brevo account with API access
  5. A Tajo account with connector permissions

Authentication

Personal API Key (Private Endpoints)

Terminal window
# Generate at https://app.posthog.com/settings/user-api-keys
export POSTHOG_PERSONAL_API_KEY=phx_your_personal_api_key
export POSTHOG_PROJECT_TOKEN=phc_your_project_token
export POSTHOG_HOST=https://us.posthog.com # or https://eu.posthog.com
export TAJO_API_KEY=your_tajo_api_key
export BREVO_API_KEY=your_brevo_api_key
// Private API endpoints use Bearer authentication
const headers = {
'Authorization': `Bearer ${process.env.POSTHOG_PERSONAL_API_KEY}`,
'Content-Type': 'application/json'
};
// Public endpoints use the project token
const publicHeaders = {
'Content-Type': 'application/json'
};
// Token is passed in the request body for public endpoints

API Key Security

Personal API keys provide full account access. Never expose them in client-side code. Use the Project API Key (token) for public endpoints like event capture and feature flag evaluation.

Configuration

Basic Setup

connectors:
posthog:
enabled: true
host: "${POSTHOG_HOST}"
personal_api_key: "${POSTHOG_PERSONAL_API_KEY}"
project_token: "${POSTHOG_PROJECT_TOKEN}"
project_id: "12345"
sync:
persons: true
events: true
cohorts: true
feature_flags: true
schedule: "0 */3 * * *" # Every 3 hours
event_filters:
- "$pageview"
- "purchase_completed"
- "signup_completed"
- "feature_used"
lists:
all_users: 25
active_users: 26
power_users: 27

Field Mapping

field_mapping:
email: email
$name: FIRSTNAME
$browser: BROWSER
$os: OS
$initial_referrer: REFERRAL_SOURCE
total_events: EVENT_COUNT
last_seen: LAST_ACTIVE_DATE
signup_date: SIGNUP_DATE
plan: SUBSCRIPTION_PLAN
company: COMPANY
cohort_names: POSTHOG_COHORTS

API Endpoints

EndpointMethodDescription
{host}/api/projects/{id}/persons/GETList persons
{host}/api/projects/{id}/events/GETList events
{host}/api/projects/{id}/cohorts/GETList cohorts
{host}/api/projects/{id}/feature_flags/GETList feature flags
{host}/api/projects/{id}/feature_flags/evaluation/POSTEvaluate flags
{host}/api/projects/{id}/insights/GETList saved insights
{host}/api/projects/{id}/query/POSTRun HogQL queries
{host}/i/v0/ePOSTCapture events (public)
{host}/decide/?v=3POSTFeature flag decisions (public)

Code Examples

Initialize Connector

import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({
apiKey: process.env.TAJO_API_KEY,
brevoApiKey: process.env.BREVO_API_KEY
});
await tajo.connectors.connect('posthog', {
host: process.env.POSTHOG_HOST,
personalApiKey: process.env.POSTHOG_PERSONAL_API_KEY,
projectToken: process.env.POSTHOG_PROJECT_TOKEN,
projectId: '12345'
});

Sync Persons to Brevo

// Paginate through PostHog persons
let nextUrl = `${posthogHost}/api/projects/${projectId}/persons/?` +
new URLSearchParams({ limit: '100' });
while (nextUrl) {
const response = await fetch(nextUrl, {
headers: {
'Authorization': `Bearer ${process.env.POSTHOG_PERSONAL_API_KEY}`
}
});
const data = await response.json();
for (const person of data.results) {
const email = person.properties.$email || person.properties.email;
if (!email) continue;
await tajo.contacts.sync({
email,
attributes: {
FIRSTNAME: person.properties.$name || person.properties.name,
LAST_ACTIVE_DATE: person.properties.$last_seen,
SIGNUP_DATE: person.created_at,
EVENT_COUNT: person.properties.$event_count,
BROWSER: person.properties.$browser,
OS: person.properties.$os,
REFERRAL_SOURCE: person.properties.$initial_referrer
},
listIds: [25]
});
}
nextUrl = data.next;
}

Sync Cohorts as Brevo Lists

// Get PostHog cohorts and sync members to Brevo lists
const cohortsResponse = await fetch(
`${posthogHost}/api/projects/${projectId}/cohorts/`,
{
headers: {
'Authorization': `Bearer ${process.env.POSTHOG_PERSONAL_API_KEY}`
}
}
);
const { results: cohorts } = await cohortsResponse.json();
for (const cohort of cohorts) {
// Get persons in this cohort
const personsResponse = await fetch(
`${posthogHost}/api/projects/${projectId}/cohorts/${cohort.id}/persons/`,
{
headers: {
'Authorization': `Bearer ${process.env.POSTHOG_PERSONAL_API_KEY}`
}
}
);
const { results: persons } = await personsResponse.json();
for (const person of persons) {
const email = person.properties.$email || person.properties.email;
if (email) {
await tajo.contacts.update(email, {
attributes: {
POSTHOG_COHORTS: cohort.name
}
});
}
}
}

Run HogQL Queries for Analytics

// Use HogQL to query analytics data
const queryResponse = await fetch(
`${posthogHost}/api/projects/${projectId}/query/`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.POSTHOG_PERSONAL_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: {
kind: 'HogQLQuery',
query: `
SELECT
properties.$email AS email,
count() AS event_count,
max(timestamp) AS last_event
FROM events
WHERE event = 'purchase_completed'
AND timestamp > now() - interval 30 day
GROUP BY email
HAVING event_count > 3
ORDER BY event_count DESC
LIMIT 1000
`
}
})
}
);
const queryResult = await queryResponse.json();
for (const row of queryResult.results) {
await tajo.contacts.update(row[0], {
attributes: {
PURCHASE_COUNT_30D: row[1],
LAST_PURCHASE: row[2]
}
});
}

Rate Limits

Endpoint CategoryLimitNotes
Analytics endpoints240/min, 1,200/hrGET persons, events, insights
Query endpoint2,400/hrHogQL and custom queries
Feature flag evaluation600/minLocal evaluation endpoint
CRUD endpoints480/min, 4,800/hrCreate, update, delete operations
Public endpoints (capture)UnlimitedEvent capture, flag decisions

Batch Exports

For large-scale event data exports, use PostHog’s batch exports feature instead of the API. Batch exports support S3, BigQuery, Snowflake, and other destinations.

Troubleshooting

IssueCauseSolution
401 UnauthorizedInvalid API keyVerify Personal API Key in settings
400 Invalid projectWrong project IDCheck project ID in PostHog URL
Empty persons listNo identified usersEnsure posthog.identify() is called
Missing propertiesProperties not setVerify $set calls in client SDK
Rate limit 429Too many requestsImplement backoff, check rate limit headers

Debug Mode

connectors:
posthog:
debug: true
log_level: verbose
log_queries: true
log_sync: true

Best Practices

  1. Identify users - Always call posthog.identify() with email to enable person sync
  2. Use cohorts for segmentation - Leverage PostHog’s behavioral cohorts for Brevo lists
  3. Batch API requests - Use pagination and batch processing for large datasets
  4. Use HogQL for complex queries - Extract custom analytics with SQL-like queries
  5. Set up batch exports - For large data volumes, prefer batch exports over API polling
  6. Filter relevant events - Sync only marketing-relevant events to reduce noise

Security

  • Personal API Key - Scoped Bearer token authentication
  • Project token - Public token for client-side operations only
  • HTTPS only - All endpoints require TLS encryption
  • IP allowlisting - Available for self-hosted instances
  • Key scoping - Create API keys with specific permission scopes
  • GitHub secret scanning - PostHog partners with GitHub for leaked key detection

Open-Source Implementation Map

No official open-source repository was found in the current Tajo connector catalog for PostHog. Keep this page focused on the verified public API contract and vendor documentation until an official schema, SDK, MCP server, or public integration repository is available.

Tajo Revamp Checklist

  • Verify authentication and scope requirements against the vendor documentation before each connector release.
  • Document primary sync objects, external IDs, pagination strategy, and rate limits explicitly.
  • Add smoke tests from public API examples rather than undocumented behavior.
  • Capture webhook signature verification and replay protection when the vendor supports webhooks.
  • Record gaps where no official public repository or schema exists so future maintainers know what still needs source-backed validation.

Subscribe to updates

developer-docs

Drop your email or phone number — we'll send you what matters next.

auto-detect
AI Assistant

Hi! Ask me anything about the docs.