Closed Joels-code closed 1 year ago
Sorry to hear you're having issues with opened
metrics tracking. Let me see if I can help!
From reviewing the React Native SDK docs for push metrics setup, could you share what method you have decided to go with for installing opened
push metrics? Javascript functions? Native iOS? Are you using another library for handling push notifications such as expo-notifications
or fcm
?
My guess is that there is a missing step with installing the SDK in your app or the SDK is not integrated with a 3rd party library correctly. Hearing more information in regards to how you have setup the SDK in your app would help determine this. Could you, please, review the React Native SDK docs for push metrics setup and share code snippets from your app that correspond to what is in the docs?
We may ask for code snippets or reviewing the campaign that you linked in the issue. A public GitHub issue may not be the best place to discuss that so at some point we may need to transition over to sending an email to win@customer.io
to further help you out.
We have gone with neither method. The React Native SDK docs for push metrics says
the SDK automatically tracks opened and delivered events for push notifications originating from Customer.io
So I did not think that there were additional steps to track the opened metric.
Is this a mistake in the documentation?
:facepalm: Sorry about that. You are correct. My eyes glanced over the 'Did you already set up rich push?' section for some reason. My apologies.
opened
metrics could be automatically setup after following the push setup instructions, yes. Here are some more details instructions that could help to debug this issue.
opened
metrics in iOS are recorded by 1 specific call to the SDK. Here is a screenshot of that function:
Note: Adding this function to your app is part of the push setup instructions that you referred to.
If you are not seeing opened
metrics get recorded but you are seeing delivered
metrics getting recorded, my guess is that function in the screenshot above is not being called.
There are 2 common reasons for this function not being called:
AppDelegate
is missing or not correct. See screenshot below to confirm that this function exists inside of your AppDelegate
file and that the function is calling the pnHandlerObj
object.
In order for this function in your AppDelegate
to be called, you also need to make sure to include this in your AppDelegate
:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
}
expo-notifications
, then those SDKs can interfere with the Customer.io SDK. Only 1 SDK can handle when a push notification gets clicked. You may have a SDK that is overriding the Customer.io SDK for handling a push notification getting clicked. If that is the case, you will want to use one of the javascript functions in the React Native SDK when the other SDK tells you that the push was clicked. We include in our docs a code sample for expo-notifications
if that's helpful for you. I hope this helps! Ask if you have more questions.
@levibostian Thankyou so much for your help and detailed response.
The issue was that we were using react-native-push-notifications to handle fcm notifications, which is mentioned in the docs but I got confused by the "automatic" functionality mentioned lol. So adding the javascript function to track opened metrics to our notification handler did the trick for iOS devices, but it isn't working on Android for some reason. Below is how we handle a notification being opened in the index.js file of our rn project.
onNotification: function (notification) {
const { data, userInteraction, finish } = notification;
if (userInteraction) {
const event = {
url: data?.uri || data.mobile_app_url || data?.link || data?.CIO?.push?.link,
type: data?.type,
content_type: data?.content_type,
content_id: data?.content_id,
threadTitle: data?.threadTitle,
threadId: parseInt(data?.threadId, 10),
commentId: parseInt(data?.commentId, 10),
};
CustomerIO.pushMessaging().trackNotificationResponseReceived(data); // Added this today, works on iOS, doesn't on Android
handleOpenUrl(event);
} else if (IS_IOS) {
showNotification(notification);
}
if (IS_IOS) {
finish(PushNotificationIOS?.FetchResult?.NoData);
} else {
finish();
}
}
I checked the android logs, and the TrackPushMetric event is never called when I open the notification. It works on iOS, so I am not sure whats going on here!
I appreciate your quick responses!
Unrelated request below...
While I have you here, what do you think of adding priority options to the push notification payloads? Currently, push notifications on Android don't get through to the user if the app is closed (not in background). Adding android priority to the message payload like so
{
"message": {
"data": {
"body": "",
"title": ""
},
"notification": {
"body": ""
},
"android":{
"priority": "high"
}
}
}
allows us to deliver messages to users who have the app closed. I'm wondering if the Customer IO team could add an option to the Push notification composer to include message priority in the payload? https://firebase.google.com/docs/cloud-messaging/concept-options#setting-the-priority-of-a-message
Yay! Glad you are starting to see some success.
Thanks for all of the details about your interpretation of our docs and the code snippets. I'll make some changes to our docs around "automatic" to try and avoid this confusion for others.
CustomerIO.pushMessaging().trackNotificationResponseReceived(data); // Added this today, works on iOS, doesn't on Android
This function call is purposely ignored on Android at the moment because Android opened
metrics behaves differently then on iOS. On Android, opened
metrics should be tracked without needing a CustomerIO.pushMessaging().trackNotificationResponseReceived
call. Send some details on behavior you're seeing on Android if you're not seeing opened
metrics being reported automatically.
I greatly appreciate you sharing your request for Android notification priority.
I added a note to our internal feature request ticket that you asked about this. Unfortunately, with feature requests, I do not have a timeline that I can share with you on when we can have this delivered. We have had this feature requested before so our team is aware of it.
Thanks again for sharing that with us.
@levibostian Thankyou! I appreciate you intaking my request :)
Regarding the opened
metrics on Android, I have found that the opened
metric isn't tracked if the notification is a localNotification
. To clarify my findings:
App is in closed state -> fcm backgroundHandler -> Android OS handles notification -> push opened
metrics are tracked
App is in a background state -> fcm backgroundHandler -> Android OS handles notification -> push opened
metrics are tracked
App is in a foreground state -> fcm onMessage -> We display a localNotification -> push opened
metrics are NOT tracked
Below is our code for handling notifications when the app is in the foreground:
PushNotification.configure({
requestPermissions: false,
popInitialNotification: true,
permissions: { alert: true, sound: true },
onNotification: function (notification) {
const { data, userInteraction, finish } = notification;
if (userInteraction) {
const event = {
url: data?.uri || data.mobile_app_url || data?.link || data?.CIO?.push?.link,
type: data?.type,
content_type: data?.content_type,
content_id: data?.content_id,
threadTitle: data?.threadTitle,
threadId: parseInt(data?.threadId, 10),
commentId: parseInt(data?.commentId, 10),
};
if (IS_IOS) {
CustomerIO.pushMessaging().trackNotificationResponseReceived(data);
}
handleOpenUrl(event);
} else if (IS_IOS) {
showNotification(notification);
}
if (IS_IOS) {
finish(PushNotificationIOS?.FetchResult?.NoData);
} else {
finish();
}
},
});
messaging().setBackgroundMessageHandler(async notification => {
// Andorid system handles push notification if there is a notification key in payload.
// This prevents a double push notification when the app is in a background state.
if (!IS_IOS && 'notification' in notification) {
return;
}
showNotification(notification);
});
messaging().onMessage(notification => {
showNotification({
message: notification.notification?.body,
title: notification.notification?.title,
data: notification.data,
});
});
showNotification = notification => {
const notif = IS_IOS
? {
message: notification?.message,
title: notification?.title,
picture: notification?.data?.CIO?.push?.image,
data: notification?.data,
}
: {
message: notification?.data?.body || notification?.message,
title: notification?.title || notification?.data?.title,
picture: notification?.data?.image,
data: notification?.data,
};
PushNotification.localNotification({
smallIcon: 'ic_notification',
color: MUSORA_BLACK,
channelId: 'musora-app-channel',
message: notif.message,
title: notif.title,
picture: notif.picture,
data: notif.data,
userInfo: notif.data,
});
};
To reiterate, push notification opened metrics are not tracked when the notification is handled by messaging().onMessage()
and only on Android. Would you happen to have any insight as to why this is? Can we change our code to get this working?
I appreciate your consistent cooperation in trying to get this figured out!
P.S. - For some reason I was able to receive push notifications today when in a closed state, where as yesterday I got nothing. Strange!
Could you explain localNotification
better for me? By local
I think you're suggesting that your app is composing and displaying a notification in the Android system tray, not a push composed by Customer.io (a remote
push notification, not local)?
You should be seeing opened
metrics be reported for push notifications sent by Customer.io no matter if your app is in foreground or background. So, I think that perhaps local
notifications is the reason for you not seeing opened
metrics?
@levibostian I believe a local notification is just a push configured from the user's device instead of received remotely. We have to display a local notification when the app is in the foreground due to how FCM works. There are some details regarding this in the Firebase push messaging docs. See "Notifications" and "Foreground state messages".
The above also explains why I could receive push notifications today when the app was closed while I couldn't yesterday; it is because if we add custom data to the push notification, the payload changes to data
only instead of a notification
payload, and today I tested without anything in the custom data field.
There are also details on when onMessage and setBackgroundMessageHandler are used, if that helps.
I believe this issue would be resolved if Android devices did not ignore trackNotificationResponseReceived,
but I do not know if that would cause other issues lol.
Ah, yes. Thanks for reminding me about this edge case Firebase has.
I am reaching out to a teammate for more help on this scenario. I'll respond when I hear back. Thanks for your patience and cooperation.
Thanks again for working with us in detail with this issue. After talking with my teammates, we believe that we have a solution to share with you. We also have some ideas for how we may be able to improve the SDK for edge cases such as this one. Your details helped us in a major way, thank you!
As we have discussed, you are using messaging().onMessage()
in your app already. The Customer.io SDK has a companion function that is designed to work with that function. See this example:
messaging().onMessage(async remoteMessage => {
let handled = await CustomerIO.pushMessaging().onMessageReceived(remoteMessage)
if (!handled) {
// The push was not sent by Customer.io.
// If your app can receive push notifications from more then Customer.io, your app should process `remoteMessage` in this function.
}
});
CustomerIO.pushMessaging().onMessageReceived()
's job is to:
I suggest giving that function a try in your app. I hope it helps!
Thankyou @levibostian!
That function did the trick!
There is still the issue of rich push notifications not being displayed on Android when the app is in the quit state, but in all other app states, our opened metrics are now being tracked!
I appreciate your help and patience.
Yay! Glad to hear it. Thanks again for all the details to help get this resolved for you quickly.
As for, "push notifications not being displayed on Android when the app is in the quit state", I have mentioned your request in our internal feature request ticket. Our team will prioritize it from there.
Have an awesome rest of your week.
SDK version: 3.1.7
Environment: Production Are logs available? No, I wasn't able to get any meaningful output for this scenario.
Describe the bug The React Native SDK documentation mentions that the SDK will automatically track
delivered
andopened
metrics. However, upon launching our first campaign that included push notifications, onlydelivered
metrics were being tracked, andopened
were not. We tested this in a test campaign by opening the push notification in multiple different app states, and theopened
metric was never tracked.To Reproduce
Expected behavior The
opened
push metric is tracked automatically by the React Native SDK, as described in the documentation.Screenshots
In the screenshot below, this user confirmed that they had opened each of those push notifications.
Additional context Link to the campaign: https://fly.customer.io/workspaces/101782/journeys/campaigns/200/overview?channels=email-twilio-push-webhook-slack-in_app