Skip to content

feat(workflows): add push subscription functionality#545

Open
havenbarnes wants to merge 27 commits intomainfrom
add-push-notifications
Open

feat(workflows): add push subscription functionality#545
havenbarnes wants to merge 27 commits intomainfrom
add-push-notifications

Conversation

@havenbarnes
Copy link
Copy Markdown

@havenbarnes havenbarnes commented Mar 31, 2026

💡 Motivation and Context

This will need to be merged after the posthog PR stack PostHog/posthog#53276 and documentation updates:

PostHog/posthog#44444

We're adding push notification channel to workflows, and SDKs need to send us their device tokens to fulfill the push subscription on our end

💚 How did you test it?

Tested everything end to end locally, hitting APNS sandbox on physical device

image

Added tests for new logic

📝 Checklist

If releasing new changes

  • Ran pnpm changeset to generate a changeset file
  • Added the release label to the PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 31, 2026

posthog-ios Compliance Report

Date: 2026-04-28 23:05:58 UTC
Duration: 2010ms

⚠️ Some Tests Failed

0/1 tests passed, 1 failed


Feature_Flags Tests

⚠️ 0/1 tests passed, 1 failed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 224ms

Failures

request_payload.request_with_person_properties_device_id

404, message='Not Found', url='http://host.docker.internal:8080/get_feature_flag'

@havenbarnes havenbarnes marked this pull request as ready for review April 3, 2026 21:14
@havenbarnes havenbarnes requested a review from a team as a code owner April 3, 2026 21:14
@havenbarnes havenbarnes requested a review from a team April 3, 2026 21:14
Copy link
Copy Markdown
Contributor

@ioannisj ioannisj left a comment

Choose a reason for hiding this comment

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

A few comments from a first pass

Comment thread PostHog/PostHogSDK.swift Outdated
Comment thread PostHog/PostHogSDK.swift Outdated
Comment thread PostHog/PostHogConfig.swift Outdated
/// Requires `enableSwizzling` to be `true`.
///
/// Default: true
@objc public var capturePushNotificationSubscriptions: Bool = true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This also silently handles registering push notification token through app delegate swizzling. Should we split these into two different config options?

I also feel we should give users who opt out of this config a manual way to handle this by adding public APIs so they can just forward delegate calls to this SDK (from UNUserNotificationCenterDelegate events and UIApplicationDelegate)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This also silently handles registering push notification token through app delegate swizzling. Should we split these into two different config options?

You know best here - sounds like there should be an explicit / non-swizzled version? I only opted for this as it felt the most frictionless and I noticed there were other swizzling-required SDK features.

I also feel we should give users who opt out of this config a manual way to handle this by adding public APIs so they can just forward delegate calls to this SDK (from UNUserNotificationCenterDelegate events and UIApplicationDelegate)

Certainly a good idea. I can add this on our side

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You know best here - sounds like there should be an explicit / non-swizzled version? I only opted for this as it felt the most frictionless and I noticed there were other swizzling-required SDK features.

I would have a non-swizzled path as well and maybe even flip the default to false here. App delegate is the entry point for apps, and if something goes wrong with swizzling here (esp with custom classes) we'd be breaking the whole app. @turnipdabeets wdyt?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed, if we offer this it should be opt-in and maybe 2 separate versions/configs for users who can't swizzle.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i'd lean to make it as automagically as possible but also give a manual API (opt out by default)
thes less users have to do, the more automatic stuff works the better
swizzle is dangerous, but if done right its super useful
session replay and autocapture only works with swizzle and people use it just fine, except a few folks that prefer to disable everything, we should just respect the config if people disable this config or disable swizzle for everything

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm okay with that. Only reason I pushed back a bit here is that this is not using the regular swizzling path which we know works and used by other integrations, but we now handle and need to worry about optional methods from the concrete delegate class (with swizzleAddingIfNeeded())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

yep fair point, so it has to be tested that it does not break, whats the common use cases for swizzling breaking apps?
iOS version? OS (eg ipad vs ios vs macos)? runtime config or something?
figure out and test those use cases
i also think that its quite common to swizzle this code path to make notifications setup automatic, i've seen a few examples on the internet, so i think its common and it should be safe enough, even firebase mentions swizzle a few times which is the main notifications provider for apple if not using APN directly

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We had a similar discussion when deeplinks were implemented on UIKit. I'm okay testing this out as true by default, then we can come back and make deeplinks automagic as well since swizzling app delegate will be there

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Ok, following this thread and (i think) the consensus i've made two changes:

  • Set capturePushNotificationSubscriptions: Bool = false to default, will make sure this is called out in my documentation PR
  • Added a non-swizzling codepath for setting up push subscriptions.

LMK if I misinterpreted or anything else is needed here

Comment thread PostHog/PushNotifications/PostHogPushNotificationIntegration.swift
@github-actions
Copy link
Copy Markdown
Contributor

This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the stale label – otherwise this will be closed in another week.

@github-actions github-actions Bot added the stale label Apr 15, 2026
@havenbarnes havenbarnes requested a review from ioannisj April 21, 2026 16:46
Copy link
Copy Markdown
Contributor

@ioannisj ioannisj left a comment

Choose a reason for hiding this comment

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

We recently refactored PostHogIntegration protocol, so probably that's why CI is failing, should be a quick fix. Todo here I think is exposing manual methods for token registration and have token autodetection with swizzling as an opt-in?

Comment thread PostHog/PostHogSDK.swift Outdated
Comment thread PostHog/PostHogSDK.swift Outdated
/// When a push notification is sent from PostHog, the device token is used to deliver the notification to the correct device.
///
/// - Parameter deviceToken: The device token received from the system.
@objc public func handlePushNotificationDeviceToken(_ deviceToken: Data) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is the deviceToken really a Data? Shouldn't it be a String or something? where do people read this from?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Depends where it comes from, if they use the swizzled codepath it will be Data. I'll converge this to string to make it more straightforward

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

yeah then the swizzling path should do the casting
the public API is gonna be user-friendlier with a String instead

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure I completely agree here since the delegate method is called with Data. So simplest api would be people just forward this call to the sdk?

Copy link
Copy Markdown
Member

@marandaneto marandaneto Apr 23, 2026

Choose a reason for hiding this comment

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

https://firebase.google.com/docs/cloud-messaging/ios/get-started#disable-swizzling
i think it depends on what we are collecting here, APN tokens or fcmToken (firebase cloud messaging)?
i understood that Data was only for the swizzling use case, so its automatic, type does not matter
the manual API should have the type that the provider is using, if that is Data, then Data it should be

https://github.com/firebase/firebase-ios-sdk/blob/90c17718b5126b6d95e24c019f10a9fc6a62c54f/FirebaseMessaging/Sources/FIRMessaging.m#L427-L429 here is Data
the firebase link has fcmToken as String

so we just need to figure out what we need and what is its type and that should be the type in the public API

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah good point on fcm vs apns tokens. Logic says that we'll need a way to distinguish BE side on this since delivery method will differ? So probably two different public api methods I would say. Swizzling here seems to cover the apns token. For FCM I assume we'll need to stick to manual wiring. Either way, we'd need to know if this is FCM or APNS when delivering the token

Copy link
Copy Markdown
Author

@havenbarnes havenbarnes Apr 23, 2026

Choose a reason for hiding this comment

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

AFAIK, the device tokens format should be the same regardless of delivery platform; FCM ultimately delivers via APNS anyway.

We're not bringing in any FCM-related logic into the SDK - all of the platform differences for delivery happen on the backend here

So I don't think we need to care about anything on the SDK side other than delivering this device token

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the question was more about the datatype really

Comment thread PostHog/PostHogConfig.swift
@ioannisj ioannisj removed the stale label Apr 22, 2026
Comment thread PostHog/PostHogSDK.swift
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

This PR hasn't seen activity in a week! Should it be merged, closed, or further worked on? If you want to keep it open, post a comment or remove the stale label – otherwise this will be closed in another week.

@github-actions github-actions Bot added the stale label May 7, 2026
@marandaneto
Copy link
Copy Markdown
Member

@ioannisj @turnipdabeets i think this is done, but just need to test/fix conflicts
i think @havenbarnes already left so should we pick this up? can you check with his former team? also for android btw

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants