Skip to content

Conversation

@ioannisj
Copy link
Collaborator

💡 Motivation and Context

Closes #155

Docs: PostHog/posthog.com#14482

Adds a beforeSend callback to PostHogConfig that lets you drop or modify events before they're sent to PostHog.

  • Added to capture(), screen() and captureException()
  • For $screen you can modify the screen name via the $screen_name property

Initially tried implementing this on the native side with method channels calling back to Dart in an attempt to also capture native initiated events, but hit timing issues since method channels are async but the beforeSend hook is called synchronously from native side. Also explored FFI but it added way too much complexity for the benefit.

For now, decided to keep it dart only so that it stays fast, synchronous and reliable. Should be good for the majority of the use cases.

Limitations in changelog

💚 How did you test it?

  • Manual testing + modified sample project

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

@ioannisj ioannisj requested a review from a team as a code owner January 20, 2026 21:25
@ioannisj ioannisj removed the request for review from a team January 20, 2026 21:26
Comment on lines +7 to +8
- Application lifecycle events (`Application Opened`, etc.)
- etc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

events captured by the captureApplicationLifecycleEvents config

- feat: add `beforeSend` callback to `PostHogConfig` for dropping or modifying events before they are sent to PostHog ([#255](https://github.com/PostHog/posthog-flutter/pull/255))
- **Limitation**:
- Does NOT intercept native-initiated events such as:
- Session replay events (`$snapshot`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, mention the sessionReplay flag


- feat: add `beforeSend` callback to `PostHogConfig` for dropping or modifying events before they are sent to PostHog ([#255](https://github.com/PostHog/posthog-flutter/pull/255))
- **Limitation**:
- Does NOT intercept native-initiated events such as:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should mention events captured by sendFeatureFlagEvents

/// };
/// ```
///
/// **Limitations:**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see comments in the changelog

/// Callback to intercept and modify events before they are sent to PostHog.
///
/// Return a possibly modified event to send it, or return `null` to drop it.
typedef BeforeSendCallback = PostHogEvent? Function(PostHogEvent event);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this type should be `FutureOr<PostHogEvent?> since people might need to use async methods to filter stuff

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this one since we've talked about eventually moving away from async method channels. This would complicate the capture pipeline potentially. Plus all the other sdks are sync hooks?

Copy link
Member

@marandaneto marandaneto Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, but right now even our sdk is async, so if you call isFeatureFlag something is async, which maybe its an use case to be used for filtering things, so we need to make it FutureOr which allows to make it async or not.
Ps I used many async methods in the past to filter out events.
I think when we redesign to be sync first, we'd figure this out differently.

/// Represents an event that can be modified or dropped by the [BeforeSendCallback].
///
/// This class is used in the beforeSend callback to allow modification of events before they are sent to PostHog.
class PostHogEvent {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least on the other SDKs, this event has a specific map for $set and $set_once
i think we should do the same
see https://github.com/PostHog/posthog-js/pull/2931/files#diff-5415311d4de5614e8deee6eddaa62716f3528992c20787a89433c2b99d2cdc9a capture event
not a must, just wanted to share this

/// **Note:**
/// - This callback runs synchronously on the Dart side
/// - Exceptions in the callback will cause the event to be sent unchanged
BeforeSendCallback? beforeSend;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the other SDKs we allow one function or a list of tunction, we dont support the list of functions here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good point

properties != null ? PropertyNormalizer.normalize(properties) : null;
final normalizedProperties = processedEvent.properties != null
? PropertyNormalizer.normalize(
processedEvent.properties!.cast<String, Object>())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never use !., fallback to empty array or check nullability

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a CLAUDE.md if needed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a null check right above but yes better avoid this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

before_send support

3 participants