From 7c71063233185391dfddf283c30f73a6ca7d0cdc Mon Sep 17 00:00:00 2001
From: Manoel Aranda Neto
Date: Fri, 12 Jun 2026 11:40:55 +0200
Subject: [PATCH 1/5] docs: centralize SDK examples in official docs
---
BEFORE_SEND.md | 236 +-----------------
README.md | 19 +-
README_ANALYTICS.md | 12 +-
.../fastapi-exception-capture/USAGE.md | 18 --
4 files changed, 18 insertions(+), 267 deletions(-)
delete mode 100644 playgrounds/fastapi-exception-capture/USAGE.md
diff --git a/BEFORE_SEND.md b/BEFORE_SEND.md
index a3696d3d..5a7d6269 100644
--- a/BEFORE_SEND.md
+++ b/BEFORE_SEND.md
@@ -1,237 +1,5 @@
# Before Send Hook
-The `before_send` parameter allows you to modify or filter events before they are sent to PostHog. This is useful for:
+Please see the official [Python library docs](https://posthog.com/docs/libraries/python#filtering-or-modifying-events-before-sending).
-- **Privacy**: Removing or masking sensitive data (PII)
-- **Filtering**: Dropping unwanted events (test events, internal users, etc.)
-- **Enhancement**: Adding custom properties to all events
-- **Transformation**: Modifying event names or property formats
-
-## Basic Usage
-
-```python
-import posthog
-from typing import Optional, Dict, Any
-
-def my_before_send(event: Dict[str, Any]) -> Optional[Dict[str, Any]]:
- """
- Process event before sending to PostHog.
-
- Args:
- event: The event dictionary containing 'event', 'distinct_id', 'properties', etc.
-
- Returns:
- Modified event dictionary to send, or None to drop the event
- """
- # Your processing logic here
- return event
-
-# Initialize client with before_send hook
-client = posthog.Client(
- api_key="your-project-api-key",
- before_send=my_before_send
-)
-```
-
-## Common Use Cases
-
-### 1. Filter Out Events
-
-```python
-from typing import Optional, Any
-
-def filter_events_by_property_or_event_name(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- """Drop events from internal users or test environments."""
- properties = event.get("properties", {})
-
- # Choose some property from your events
- event_source = properties.get("event_source", "")
- if event_source.endswith("internal"):
- return None # Drop the event
-
- # Filter out test events
- if event.get("event") == "test_event":
- return None
-
- return event
-```
-
-### 2. Remove/Mask PII Data
-
-```python
-from typing import Optional, Any
-
-def scrub_pii(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- """Remove or mask personally identifiable information."""
- properties = event.get("properties", {})
-
- # Mask email but keep domain for analytics
- if "email" in properties:
- email = properties["email"]
- if "@" in email:
- domain = email.split("@")[1]
- properties["email"] = f"***@{domain}"
- else:
- properties["email"] = "***"
-
- # Remove sensitive fields entirely
- sensitive_fields = ["my_business_info", "secret_things"]
- for field in sensitive_fields:
- properties.pop(field, None)
-
- return event
-```
-
-### 3. Add Custom Properties
-
-```python
-from typing import Optional, Any
-
-from datetime import datetime
-from typing import Optional, Any
-
-def add_context(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- """Add custom properties to all events."""
- if "properties" not in event:
- event["properties"] = {}
-
- event["properties"].update({
- "app_version": "2.1.0",
- "environment": "production",
- "processed_at": datetime.now().isoformat()
- })
-
- return event
-```
-
-### 4. Transform Event Names
-
-```python
-from typing import Optional, Any
-
-def normalize_event_names(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- """Convert event names to a consistent format."""
- original_event = event.get("event")
- if original_event:
- # Convert to snake_case
- normalized = original_event.lower().replace(" ", "_").replace("-", "_")
- event["event"] = f"app_{normalized}"
-
- return event
-```
-
-### 5. Log and drop in "dev" mode
-
-When running in local dev often, you want to log but drop all events
-
-
-```python
-from typing import Optional, Any
-
-def log_and_drop_all(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- """Convert event names to a consistent format."""
- print(event)
-
- return None
-```
-
-### 6. Combined Processing
-
-```python
-from typing import Optional, Any
-
-def comprehensive_processor(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- """Apply multiple transformations in sequence."""
-
- # Step 1: Filter unwanted events
- if should_drop_event(event):
- return None
-
- # Step 2: Scrub PII
- event = scrub_pii(event)
-
- # Step 3: Add context
- event = add_context(event)
-
- # Step 4: Normalize names
- event = normalize_event_names(event)
-
- return event
-
-def should_drop_event(event: dict[str, Any]) -> bool:
- """Determine if event should be dropped."""
- # Your filtering logic
- return False
-```
-
-## Error Handling
-
-If your `before_send` function raises an exception, PostHog will:
-
-1. Log the error
-2. Continue with the original, unmodified event
-3. Not crash your application
-
-```python
-from typing import Optional, Any
-
-def risky_before_send(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- # If this raises an exception, the original event will be sent
- risky_operation()
- return event
-```
-
-## Complete Example
-
-```python
-import posthog
-from typing import Optional, Any
-import re
-
-def production_before_send(event: dict[str, Any]) -> Optional[dict[str, Any]]:
- try:
- properties = event.get("properties", {})
-
- # 1. Filter out bot traffic
- user_agent = properties.get("$user_agent", "")
- if re.search(r'bot|crawler|spider', user_agent, re.I):
- return None
-
- # 2. Filter out internal traffic
- ip = properties.get("$ip", "")
- if ip.startswith("192.168.") or ip.startswith("10."):
- return None
-
- # 3. Scrub email PII but keep domain
- if "email" in properties:
- email = properties["email"]
- if "@" in email:
- domain = email.split("@")[1]
- properties["email"] = f"***@{domain}"
-
- # 4. Add custom context
- properties.update({
- "app_version": "1.0.0",
- "build_number": "123"
- })
-
- # 5. Normalize event name
- if event.get("event"):
- event["event"] = event["event"].lower().replace(" ", "_")
-
- return event
-
- except Exception as e:
- # Log error but don't crash
- print(f"Error in before_send: {e}")
- return event # Return original event on error
-
-# Usage
-client = posthog.Client(
- api_key="your-api-key",
- before_send=production_before_send
-)
-
-# All events will now be processed by your before_send function
-client.capture("user_123", "Page View", {"url": "/home"})
-```
\ No newline at end of file
+SDK usage examples and code snippets live in the official documentation so they stay up to date.
diff --git a/README.md b/README.md
index db066c8a..c4db3ad9 100644
--- a/README.md
+++ b/README.md
@@ -10,16 +10,19 @@
-Please see the [Python integration docs](https://posthog.com/docs/integrations/python-integration) for details.
+Please see the main [PostHog docs](https://posthog.com/docs).
-## Python Version Support
+SDK usage examples and code snippets live in the official documentation so they stay up to date.
-| SDK Version | Python Versions Supported | Notes |
-| ------------- | ---------------------------- | -------------------------- |
-| 7.3.1+ | 3.10, 3.11, 3.12, 3.13, 3.14 | Added Python 3.14 support |
-| 7.0.0 - 7.0.1 | 3.10, 3.11, 3.12, 3.13 | Dropped Python 3.9 support |
-| 4.0.1 - 6.x | 3.9, 3.10, 3.11, 3.12, 3.13 | Python 3.9+ required |
+## Documentation
+
+- [Python library docs](https://posthog.com/docs/libraries/python)
+- [AI observability installation docs](https://posthog.com/docs/ai-observability/installation)
## Contributing
-See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, test, and development workflow instructions.
+See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and test instructions.
+
+## Releasing
+
+See [RELEASING.md](RELEASING.md).
diff --git a/README_ANALYTICS.md b/README_ANALYTICS.md
index ac20c308..790410c8 100644
--- a/README_ANALYTICS.md
+++ b/README_ANALYTICS.md
@@ -1,11 +1,9 @@
-# posthoganalytics
+# PostHog Python analytics
-> **Do not use this package.** Use [`posthog`](https://pypi.org/project/posthog/) instead.
+Please see the main [PostHog docs](https://posthog.com/docs).
-```bash
-pip install posthog
-```
+SDK usage examples and code snippets live in the official documentation so they stay up to date.
-This package exists solely for internal use by [posthog/posthog](https://github.com/posthog/posthog) to avoid import conflicts with the local `posthog` package in that repository. It is an automatically generated mirror of `posthog` — same code, same versions, just published under a different name.
+## Documentation
-If you are not working on the PostHog main repository, you should never need this package. All documentation, issues, and development happen in [`posthog-python`](https://github.com/posthog/posthog-python).
+- [Python library docs](https://posthog.com/docs/libraries/python)
diff --git a/playgrounds/fastapi-exception-capture/USAGE.md b/playgrounds/fastapi-exception-capture/USAGE.md
deleted file mode 100644
index 57171a67..00000000
--- a/playgrounds/fastapi-exception-capture/USAGE.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# FastAPI Exception Capture Usage
-
-Minimal reproduction of PostHog exception capture issue.
-
-## Quick Start
-
-```bash
-cd posthog-python/playgrounds/fastapi-exception-capture
-export POSTHOG_API_KEY="your_key"
-uv sync
-uv run python app.py
-```
-
-## Test
-
-```bash
-curl http://localhost:8000/test-exception
-```
From f2cd8a86702a90e2919b30e5160e5ab49d7b12ee Mon Sep 17 00:00:00 2001
From: Manoel Aranda Neto
Date: Fri, 12 Jun 2026 14:22:49 +0200
Subject: [PATCH 2/5] address pr review feedback
---
BEFORE_SEND.md | 5 -----
README.md | 19 ++++++++-----------
README_ANALYTICS.md | 12 +++++++-----
3 files changed, 15 insertions(+), 21 deletions(-)
delete mode 100644 BEFORE_SEND.md
diff --git a/BEFORE_SEND.md b/BEFORE_SEND.md
deleted file mode 100644
index 5a7d6269..00000000
--- a/BEFORE_SEND.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Before Send Hook
-
-Please see the official [Python library docs](https://posthog.com/docs/libraries/python#filtering-or-modifying-events-before-sending).
-
-SDK usage examples and code snippets live in the official documentation so they stay up to date.
diff --git a/README.md b/README.md
index c4db3ad9..db066c8a 100644
--- a/README.md
+++ b/README.md
@@ -10,19 +10,16 @@
-Please see the main [PostHog docs](https://posthog.com/docs).
+Please see the [Python integration docs](https://posthog.com/docs/integrations/python-integration) for details.
-SDK usage examples and code snippets live in the official documentation so they stay up to date.
+## Python Version Support
-## Documentation
-
-- [Python library docs](https://posthog.com/docs/libraries/python)
-- [AI observability installation docs](https://posthog.com/docs/ai-observability/installation)
+| SDK Version | Python Versions Supported | Notes |
+| ------------- | ---------------------------- | -------------------------- |
+| 7.3.1+ | 3.10, 3.11, 3.12, 3.13, 3.14 | Added Python 3.14 support |
+| 7.0.0 - 7.0.1 | 3.10, 3.11, 3.12, 3.13 | Dropped Python 3.9 support |
+| 4.0.1 - 6.x | 3.9, 3.10, 3.11, 3.12, 3.13 | Python 3.9+ required |
## Contributing
-See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and test instructions.
-
-## Releasing
-
-See [RELEASING.md](RELEASING.md).
+See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, test, and development workflow instructions.
diff --git a/README_ANALYTICS.md b/README_ANALYTICS.md
index 790410c8..ac20c308 100644
--- a/README_ANALYTICS.md
+++ b/README_ANALYTICS.md
@@ -1,9 +1,11 @@
-# PostHog Python analytics
+# posthoganalytics
-Please see the main [PostHog docs](https://posthog.com/docs).
+> **Do not use this package.** Use [`posthog`](https://pypi.org/project/posthog/) instead.
-SDK usage examples and code snippets live in the official documentation so they stay up to date.
+```bash
+pip install posthog
+```
-## Documentation
+This package exists solely for internal use by [posthog/posthog](https://github.com/posthog/posthog) to avoid import conflicts with the local `posthog` package in that repository. It is an automatically generated mirror of `posthog` — same code, same versions, just published under a different name.
-- [Python library docs](https://posthog.com/docs/libraries/python)
+If you are not working on the PostHog main repository, you should never need this package. All documentation, issues, and development happen in [`posthog-python`](https://github.com/posthog/posthog-python).
From f88b4800e7c6fd8554ca3551ab3d00d6233345b9 Mon Sep 17 00:00:00 2001
From: Manoel Aranda Neto
Date: Fri, 12 Jun 2026 14:23:18 +0200
Subject: [PATCH 3/5] restore fastapi playground usage docs
---
playgrounds/fastapi-exception-capture/USAGE.md | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 playgrounds/fastapi-exception-capture/USAGE.md
diff --git a/playgrounds/fastapi-exception-capture/USAGE.md b/playgrounds/fastapi-exception-capture/USAGE.md
new file mode 100644
index 00000000..57171a67
--- /dev/null
+++ b/playgrounds/fastapi-exception-capture/USAGE.md
@@ -0,0 +1,18 @@
+# FastAPI Exception Capture Usage
+
+Minimal reproduction of PostHog exception capture issue.
+
+## Quick Start
+
+```bash
+cd posthog-python/playgrounds/fastapi-exception-capture
+export POSTHOG_API_KEY="your_key"
+uv sync
+uv run python app.py
+```
+
+## Test
+
+```bash
+curl http://localhost:8000/test-exception
+```
From 2d707f9ce41b90999c5cccbd34951b35d0677646 Mon Sep 17 00:00:00 2001
From: Manoel Aranda Neto
Date: Fri, 12 Jun 2026 14:26:08 +0200
Subject: [PATCH 4/5] restore python support table in readme
---
README.md | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index db066c8a..2a6eeede 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,9 @@
-Please see the [Python integration docs](https://posthog.com/docs/integrations/python-integration) for details.
+Please see the main [PostHog docs](https://posthog.com/docs).
+
+SDK usage examples and code snippets live in the official documentation so they stay up to date.
## Python Version Support
@@ -20,6 +22,15 @@ Please see the [Python integration docs](https://posthog.com/docs/integrations/p
| 7.0.0 - 7.0.1 | 3.10, 3.11, 3.12, 3.13 | Dropped Python 3.9 support |
| 4.0.1 - 6.x | 3.9, 3.10, 3.11, 3.12, 3.13 | Python 3.9+ required |
+## Documentation
+
+- [Python library docs](https://posthog.com/docs/libraries/python)
+- [AI observability installation docs](https://posthog.com/docs/ai-observability/installation)
+
## Contributing
-See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, test, and development workflow instructions.
+See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup and test instructions.
+
+## Releasing
+
+See [RELEASING.md](RELEASING.md).
From a4080d5839280dd61b7a57aae98461d984176980 Mon Sep 17 00:00:00 2001
From: Manoel Aranda Neto
Date: Fri, 12 Jun 2026 14:27:31 +0200
Subject: [PATCH 5/5] update readme framework doc links
---
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 2a6eeede..e8e2f708 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,8 @@ SDK usage examples and code snippets live in the official documentation so they
## Documentation
- [Python library docs](https://posthog.com/docs/libraries/python)
-- [AI observability installation docs](https://posthog.com/docs/ai-observability/installation)
+- [Django framework docs](https://posthog.com/docs/libraries/django)
+- [Flask framework docs](https://posthog.com/docs/libraries/flask)
## Contributing