Firebase notification sent to an audience does not reach all devices it should - ios

I have an interesting situation. For some time I have been collecting an audience based on a single user property. Now it has significant amount of devices included. The audience is for ios devices.
I then sent a notification to that audience and I that see some of the devices receive that notification, some don't. Why could that be?
Experiments show that devices that don't receive the notification, receive a notification targeted to single device only. Also they receive notifications send to all users. That makes me suspect that this is related to audiences. I have verified that at least one device that does not receive the notifications has proper value for the user property in question. However, it is possible that the during the past days device has had varying values for the property, based on the account used for logging in to the app. Sometimes it has had two versions of the same app installed at the same time.
I have similar audience for Android and as far as I can tell, all members in the audience receive the notification.
The audience's are in thousands, so the information is based only on few devices I see around me, plus Firebase and Google Analytics.
From Firebase documentation I learn that "a user is a permanent member of an audience after they are assigned to it", which explains why two opposite audiences combined may be bigger than the total number of users, but it makes it even more difficult to understand why someone having the properties required for the audience would not belong to it.
Any ideas on how to debug this or what could be the reason. Or even better, how to fix this? Since this is production software, I can not send excessive number of notifications to try different things.

While I probably still don't know all of the possible reasons for this, there are at least two things that seemed to have some effect on this in our case and third one that could have been the reason if not correctly understood:
1) Our app did register list of values with single call to setUserPropertyString and in some cases the string did exceed the 24 character limit, which caused the property not to be set and the user/device not to be included in an audience.
2) When sending the notification to iOS app, the "High" prority should be selected, otherwise it is possible, or even likely that the notification does not reach the device.
3) Firebase console texts for combining multiple audiences are not all that clear, especially the "does not ..." texts could be clearer in my opinion. This is what they mean in practice:
includes all of == AND, notification is sent if user is included in all selected audiences
includes at least one of == OR, notification is sent if user is included in at least one of the selected audiences
does not include all of == NAND, notification is sent if user is not included in all of the selected audiences, but user can be included in some of them
does not include at least one of == NOR, notification is sent only if user is not included in any of the selected audiences

Related

Managing PushSubscriptions within shared browsers

Working on ironing out some UX considerations around a push notification system using WebPush and ServiceWorkers. Additionally, this system should gracefully handle multiple users sharing the same browser.
More concretely, I have the following constraints:
1) A user should not be able to see notifications which are not intended for them.
2) The state of a user's push subscription should be opaque to and immutable by other users. i.e. the state of my push subscription should not be based on the behavior/actions of anybody but my own.
Satisfying the first constraint was quite straightforward. I decided to store the currently logged-in user id in IndexedDB and include the id of the intended user within the push payload. It is then straightforward to only show the push notification to the user if those 2 ids match.
However, satisfying constraint 2 has proved to be quite elusive. So far I've tried:
1) One-to-one mapping between users and push subscriptions. This was the first thing I tried, as it struck me as the most natural mapping. However, this ends up falling flat on its face as creating a new push subscription will invalidate the subscription for the previous user, thus requiring the original user to create another subscription on subsequent logins, thus failing the second constraint.
2) Shared push subscription. This has the benefit of not invalidating the push subscriptions, so subsequent logins for the original user will behave as expected. However, none of the subsequent users will actually need to grant permission to the browser, thus failing the second constraint.
3) Even if I was able to get something working with one of the above 2 options, there is still nothing preventing another user from simply going to the browser settings and disallowing notifications, thus nuking all push subscriptions. However, I imagine that this is just something I will have to live with that will have no elegant solution.
I'm certain there have been many brilliant minds working on the above problem, so I'm all ears with regards to how constraint 2 above has effectively been satisfied.
Thanks.
I had the same problem when I was developing Pushpad. We tried different solutions and some of them, such as the many to many relation between users and browsers, became a nightmare very soon. So I would recommend the following approach, which proved to be the best one for us.
Each subscription (endpoint) is a device (browser) and can be associated at most to one user at a time. Whenever possible try to keep data associated to users and not to devices. In this way a subscription (endpoint) can be transferred to a different user and you don't loose data when the endpoint expires or gets replaced. Then when you need to send a notification filter your audience based on the user data, find the recipients and send the notification to the associated devices.
The only data that you may want to associate to devices are device preferences and device preferences are global to all the users that use that browser. This is consistent with the fact that the browser permission (allow / block) is global to all users.
The above solution partially meets your requirements:
1) A user should not be able to see notifications which are not intended for them.
Yes:
when a user logs out you can remove the association between the user and the device
when a browser (user) logs in with a different account on your website you associate the device to the new user (and you remove the previous association)
2) The state of a user's push subscription should be opaque to and immutable by other users.
Yes, because you don't keep data associated to the device. You associate data to the users in your database.
There is no way to satisfy both constraints. You will need to choose either the one-to-one mapping (1) or the shared push subscription (2). You cannot use the browser to deliver your push notifications and at the same time expect certain behaviour (w.r.t. permissions, nuking) from that very same browser...

How to implement user suspend feature in iOS

In an iOS application, When I detect a users improper action (for example posting violent content), I wan't to suspend the user from using my application. The basic idea to implement this feature is to create and save an unique id for each application installs and suspend the usage from server api's.
My question is, how can I implement this feature even if the user re-installs the application, and still pass the Apple's iTunes submission?
I came up with two ways to technically implement this feature, but wondering how Apple would respond.
Store the IDFA (I understand that users can reset the id on their behalf)
Store an app generated udid to the Keychain (which should not be deleted even if the user deletes the app)
I know there are no perfect answers, but would appreciate to discuss this issue with anyone that have tried submitting a similar application, or anyone that is well aware of the Apple's guidelines. Thank you.
Apple will reject apps that inappropriately use the IDFA.
If your app does not use server login (at which point, whatever flags you require could be delivered to the client), keychain storage would be the only real solution.
However, if you don't use server login, you block the device, not the user. Is this your intent?
BTW, without server login, a determined user can still get around keychain storage: Reset keychain on the device
You can block a given account. Most people these days key an account with an email address. Some require a credit card (Facebook fully validates accounts using credit card numbers), others require a bank account (PayPal has to send money somewhere!) and it is growing in popularity to request a phone number (Twitter is getting there). In the end, to really be effective, you have to block something that is difficult to produce.
With email, your users can always create a new account. Check out mailinator.com. Alternatively, all you need is one domain to have as many email addresses as you want -- I use five different email accounts daily, and I use about two dozen more on a monthly basis.
Installation ids are ok but users can always just uninstall/reinstall. And if you do manage to get a device-identifying number (easy to do really, even in the post-UDID era) so that you can block a given device, your users can just get a new device, or hack your app to use some random value, or spoof your API with cURL. I own three iPhones, two iPads, two Samsung tabs, three other Android phones, two Mac Book Pros, a mini, two PCs, and I run three virtual Linux boxes, and one virtual XP box. And what happens when somebody sells a blocked device to a non-abusive user?
So just block the user's account, keep excellent log files, and keep fighting the good fight.

APNs duplicate tokens

We have a push notification server which holds the data (device tokens) for several different applications. With Apple wanting to stop people using the UDID as identifier, I was looking into changing this server so that it does not rely on UDIDs to identify devices any longer.
I understand that the tokens returned by APNs are not globally unique, but rather unique per device. However, when going through our database, I noticed that there are several cases (a few hundred on 750k+ registrations) where the same token is used for different devices.
So I'm trying to figure out what's causing this. At this point, I see 2 possibilities:
There is an obscure bug in our server registration handling somewhere
Apple recycles these device tokens (perhaps after a device reset?). We always store the last time a certain device registered, and I noticed that there are always at least several days between registrations of different devices with the same token. As far as I can tell, there are no tokens that are concurrently used by different devices.
I would really appreciate it if someone could shed some light on this.
What we know is that Apple tells us to use the Device Token to push notifications to a device. So, as long as you are:
Querying the APNs for a new device token every time the application is launching and registering it in your database
Querying the Feedback service for inactive devices and purging them from your database
... you are doing what Apple is expecting you to do.
However, I do suspect that there may be a bug in your registration code because 100/750k is a pretty high conflict rate. Considering these device tokens are used to push notifications, a lot of people would be complaining about receiving notifications that don't belong to them...

Newsstand kit and providing multiple magazines/newspapers in one application

So basically my questions is: Can newsstand kit be used in one single app for several different magazine subscriptions? From the wwdc 504 session it doesn't really appear that this is true. In my understanding it appears that a magazine/newspaper subscription is coupled with 1 app. For instance the UIApplication setNewsstandIconImage only has a single UIImage parameter, so I can only deduce from this that one and only one newstand image can exist or rather be active for a single application. Am I missing something here, can someone confirm or deny my suspicions? Thanks in advance!
setNesstandIconImage sets the icon of your app. You app only ever has one icon, so it doesn't make sense to set it to multiple images. This, in an of itself, does not limit Newsstand to being used for one publication only. Just set the icon to whatever the newest issue is, regardless of publication.
While subscriptions are coupled to an app (you can only purchase a subscription from the app it's linked to), there is no limit to the number of subscriptions your app can offer. And what you do with those subscriptions is completely up to you. The only thing Apple will tell you is the subscription ID, if it's active, and when it was purchased (and a few other meta). What you download/enable/unlock based on that information is up to you.
So there's no technical reason your single app couldn't offer subscriptions to Time, Newssweek, and the Wall Street Journal (and maybe a fourth subscription to all three for a reduced price).
There may be usability or design reasons you wouldn't want to do that. But technically the API supports it.
You're right that the way Newsstand is today managed and displayed by iOS makes it more suitable for one-app-one-magazine apps than multi-magazine ones.
Technically making a multiple magazine Newsstand app is not impossible. All in all Apple limits pushes to one per day, but it doesn't mean that in your push notification you can add a payload that refers to multiple issues to be downloaded at a time: as far your app is moved in the background from the push notification you will be able, based on payload data, to schedule as many downloads as you want (they will be serially queued in the NK download queue).
Of course the single UIImage parameters is a real limitation. Normally you should add on it the latest downloaded issue: intact the rule is that the cover must be updated once the magazine is ready in the device, so typically you will update the cover after magazine download and installation. Eventually for a multiple-magazine app you can consider a generic cover and then keep the user informed of the latest download thanks to the badge in the icon.
Anyway I agree with you: the user experience is improved by Newsstand mainly on single-magazine apps.

Confirm iPhone user

I have developed an iPhone application for a café. In the application you can order takeaway food and therefore I need a way to be sure that there are no orders in a "fake" name (e.g. a person who makes an order with a strangers name, e-mail and so on)
Therefore I have to make the user confirm the order before it's sent to the café. I am not sure what the best way to do this is.
I have been thinking of setting up an SMS gateway and when an order is placed, an SMS is sent to the the entered phone number and the user will have to send a confirmation SMS back. I am not a fan of this approach, as the confirmation is not happening in the application itself.
Then I got the idea that this might be possible with push notifications. I am not exactly sure how it would work (if you have any ideas on this, please let me hear) but since Apple writes the following in their documentation I do not really dare to rely on this for confirmation.
Important: Because delivery is not guaranteed, you should not depend on
the remote-notifications facility for
delivering critical data to an
application via the payload. And never
include sensitive data in the payload.
You should use it only to notify the
user that new data is available.
Another approach which would be very easy to implement would be to programtically retrieve the user's phone number from the SIM card but I have read that Apple rejects applications which does this.
I would like to ask if you have any ideas how I can do this confirmation? It could be one of the above approaches or a completely new. Would it be possible to do something with the unique ID that the every iPhone has?
Could you do the SMS confirmation, but only once? Keep a link of UDID and phone number pairs, and once a confirmation has been made for a pair then don't request it again? That way, regular customers will get minimal hassle.
Don't forget that the UDID for a phone number, or the phone number for a UDID, may change, if the person gets a new device or a new SIM card: make sure your code supports that.
Another approach is to validate credit card information up front as part of account setup. Then offer the option to pay now or cash n carry. This eliminate 99% of the no shows.

Resources