feat: add push notification support - #511
Merged
Merged
Conversation
…t the macOS token guards
…oute owner detaches
… blank appId as absent on iOS
Contributor
🦔 ReviewHog reviewed this pull requestFound 0 must fix, 1 should fix, 0 consider. Published 1 finding (view the review). |
Contributor
posthog-flutter Compliance ReportDate: 2026-08-04 13:01:48 UTC ✅ All Tests Passed!45/45 tests passed Capture Tests✅ 29/29 tests passed View Details
Feature_Flags Tests✅ 16/16 tests passed View Details
|
Contributor
|
ReviewHog Alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏 |
Contributor
There was a problem hiding this comment.
ReviewHog Report
Feature
Issues: 1 issue
Files (10)
posthog_flutter/darwin/posthog_flutter/Sources/posthog_flutter/PosthogFlutterPlugin.swiftposthog_flutter/darwin/posthog_flutter.podspecposthog_flutter/darwin/posthog_flutter/Package.swiftexample/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedexample/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolvedexample/macos/Runner.xcodeproj/project.pbxprojexample/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedexample/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcschemeexample/macos/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved.changeset/fancy-owls-eat.md
What were the main changes
- Adds registerPushNotificationToken (iOS-only), unregisterPushNotificationToken and capturePushNotificationOpened (subtitle iOS-only) bridging to posthog-ios
- Implements the same multi-engine pushIdentityProvider mint-route pattern as Android: candidate list, setup-time anchor, promotion on detach, fast decline when unowned
- Reads CAPTURE_PUSH_NOTIFICATION_SUBSCRIPTIONS / CAPTURE_PUSH_NOTIFICATION_OPENED Info.plist keys for the AUTO_INIT opt-out path
- Bumps native posthog-ios floor to 3.69.0 in podspec, Package.swift, and example Package.resolved pins
- macOS example project: adds FlutterGeneratedPluginSwiftPackage SPM dependency and a pre-build 'prepare Flutter framework' script action needed to consume the bumped SDK
- Adds the changeset documenting the minor release and its default-on behavior/opt-out keys
Prompt To Fix All With AI### Issue 1
example/macos/Runner.xcodeproj/project.pbxproj:257-259
**CocoaPods build requires SPM package**
When the macOS CocoaPods variant runs, the Runner target still resolves `FlutterGeneratedPluginSwiftPackage`, although Flutter only generates that package when Swift Package Manager integration is enabled, causing package resolution to fail before compilation.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "refactor: type the push method-call maps..." | Re-trigger Greptile |
marandaneto
reviewed
Aug 4, 2026
marandaneto
approved these changes
Aug 4, 2026
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Motivation and Context
PostHog Workflows can send push notifications, and both native SDKs already ship the full feature (posthog-ios 3.69.0 via PostHog/posthog-ios#729, #735 and #743, posthog-android 3.58.0 via PostHog/posthog-android#642 and #667). Flutter apps can't reach any of it: the plugin never forwarded the push config flags and the manual APIs weren't bridged.
Ports it as a config + API bridge. The native SDKs own the whole subscription state machine (retry with backoff, durable pending records, 401 re-mint, re-registration on
identify/reset, opt-out gating); nothing is reimplemented in Dart.What's new:
PostHogConfiggainscapturePushNotificationSubscriptionsandcapturePushNotificationOpened(both defaulttrue, matching the natives) plus apushIdentityProviderhook for projects that require identity verification.registerPushNotificationToken,unregisterPushNotificationTokenandcapturePushNotificationOpened. These are more load-bearing on Flutter than on native:firebase_messagingapps handle push in Dart, so live token refresh and warm-start taps are only reachable through them.toMap()sendspushIdentityProviderEnabledand native callspushIdentityProviderback over the channel when it needs a token. With multiple Flutter engines, the engine that installed a provider owns the mint route; when it detaches, a surviving provider-enabled engine gets promoted.com.posthog.posthog.CAPTURE_PUSH_NOTIFICATION_SUBSCRIPTIONS/com.posthog.posthog.CAPTURE_PUSH_NOTIFICATION_OPENEDkeys (Info.plist on iOS, AndroidManifest<meta-data>on Android). The provider hook isn't available there, since the native SDK is set up before any Dart runs.Package.swiftto3.69.0, gradle to[3.58.0,4.0.0). Web is a no-op (posthog-js has no push feature).Platform divergences are kept exactly as the natives define them:
subtitleis iOS-only (the Android bridge drops it), a nullappIdfalls back to the bundle id on iOS and to the FirebaseprojectId(via reflection, no Firebase dependency added) on Android, and register/unregister no-op on macOS while opened capture works there.One trap for the docs: iOS registers the raw APNs token, Android the FCM token.
FirebaseMessaging.instance.onTokenRefreshyields FCM tokens on both platforms, so wiring it must be guarded withPlatform.isAndroidor it overwrites the correct APNs token on iOS and silently breaks iOS delivery. The fullfirebase_messagingwiring guide is a follow-up to posthog.com docs.Out of scope: notification rendering, channels and permission prompting stay with the host app, and no Firebase/APNs credentials were added to
example/.💚 How did you test it?
flutter test(265 tests): the argument maps for the three APIs (includingappIdomitted when null), thepushIdentityProviderround-trip driven by an inboundMethodCall, a throwing provider returningnull, and config serialization../gradlew :posthog_flutter:testDebugUnitTest: config-flag plumbing, the FirebaseprojectIdfallback,subtitlebeing dropped, and the multi-engine mint-route ownership cases (anchoring, no steal on secondary setup, promotion on detach).make checkFormatDart analyzeDart formatKotlin formatSwift;api/posthog_flutter.api.jsonregenerated and gated bycheckApiDartin CI.darwin/, so the iOS bridge itself is covered by review only. The wire contract (POST /api/push_subscriptions/body, retry, 401 re-mint) lives in the native SDKs and is covered by their suites; I didn't re-verify it end to end from Flutter.📝 Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
DRI: @ioannisj
Autonomy: Human-driven (agent-assisted)