Slide 1

Slide 1 text

/dev/world User Notifications in Depth Sam Jarman Sailthru NZ Aug 29-31, 2016 @samjarman * Making apps for 6 years * Work with fortune 500 companies on setting up push and more daily * Obsessed with Push and getting it right

Slide 2

Slide 2 text

Today • Conceptual Overview of User Notifications + iOS 10 Changes • Implementation and Debugging • Best Practices for Notifications Today I want to cover 3 topics in Push Notifications and try go beyond what you’ll see in the WWDC videos. Too easy to regurgitate a keynote, so this will try to be something a bit different for more value. And lastly iOS drops next month, so let’s talk about that too!

Slide 3

Slide 3 text

Conceptual Overview of User Notifications First up, let’s talk about notification concepts

Slide 4

Slide 4 text

What Are They? First question, what are user notifications?

Slide 5

Slide 5 text

User Notifications • Two types - Local and Remote • Both require permission • Both present the same way There are two types of notification Local & Remote When you’re asking for permission, you’re asking for permission for either. The notification is generally visually indistinguishable from the user.

Slide 6

Slide 6 text

Local Notifications • Configured by developer • Time based triggers - Interval and Calendar • Location based triggers Local notifications are scheduled in code. They have to be thought about ahead of time in terms of structure and even content.

Slide 7

Slide 7 text

Remote Notifications • A.K.A Push Notifications • Sent from a server • Processed by a OS + your app, delivered to user Remote notifications are the the usual suspects. Called push Notifications They are sent by a server at given time, and should be delivered shortly after. The OS processes it and does what it needs to to display it

Slide 8

Slide 8 text

How Do They Look? So what do these notifications look like?

Slide 9

Slide 9 text

Presentation Style • Alert • Badge • Sound Notifications typically show up as an alert. Optionally, an icon is badged, and a sound or vibration is played. We should be all familiar with these notifications from at least Messages or Mail.

Slide 10

Slide 10 text

Platforms Platform Capabilities iOS Alert, Badge, Sound macOS Alert, Badge, Sound tvOS Badge watchOS Alert, Sounds CarPlay Sounds Safari Alerts, Custom Button Title While I’m talking about mainly push for iOS today, it’s not just iOS you can push to other platforms to.
 Obviously on iOS, you can get everything, as with macOS With TV you can badge the icon, such as to shown an unread or unwatched count On watchOS, you can get alerts and vibrations On Carplay, you can play sounds overtop of the music when a push arrives Safari can also receive alerts and set a custom open button title.

Slide 11

Slide 11 text

What Can You Do? So what can you do with these notifications?

Slide 12

Slide 12 text

Alerts • Localisable text • Fit to screen • Title, Subtitle • Localisation available Firstly and most typically you’d set some alert text. There’s not really a hard limit here for length, but its gonna fit on the screen. You can set a title and subtitle, and, if you have translations you can also send down a localization string. Even those with parameters an their values.

Slide 13

Slide 13 text

Badge • 1-999,999,999,……. • Setting to 0 clears all alerts • No negative numbers You have the ability to set the badge. It can be an integer anywhere from 1 to INT MAX digits long… but dont. Use 6 at most.
 0 clears notifs for that app out of the tray

Slide 14

Slide 14 text

Sounds • Must be included in the app bundle • .wav, .caf or .aiff file • < 30 seconds in duration afconvert /System/Library/Sounds/ Submarine.aiff ~/Desktop/sub.caf -d ima4 -f caff -v When a notification arrives, an optional sound can be played too. 
 Sounds must be included in the app bundle 30 seconds or less, otherwise they’re not played.

Slide 15

Slide 15 text

Actions and Input • Configured when registering for user notifications • Different scenarios trigger different possible actions -“Categories” • Handled in your app iOS 8+ iOS 8 brought with it a concept of Actions. Actions are defined by the developer and are configured when registering for notifications. 
 Different scenarios trigger different possible actions. These scenarios are called “Categories” The user tapping the action kicks off a method in your app.

Slide 16

Slide 16 text

Action Buttons • Configurable scenarios / “Categories” • Call into your app • May open your app • May indicate a destructive action • May require authentication iOS 8+ For example, the scenario of a new mail message could be a category of “new message”, with the actions of Mark as Read and Trash.
 Destructive means that some user data will be changed and not easily unchanged, for example, deleting an incoming email. This should be familiar as it’s red. You also get to define a minimal and default set, as some banners can show more than 2 actions at times. An extra possible action here is “Open Message”

Slide 17

Slide 17 text

Text Input • A type of Action • Allow user to reply to type • Text is delivered to your app • iOS 10 allows for more control over the text input iOS 9+ iOS 9 bought with it the ability to reply in the actions. This was previously possible in Messages, but now any app can take register for notifications with actions that accept text. The text is delivered to your app as a string and you can do with it what you please. iOS 10 lets you define your own text input, allowing you to add accessories to the input. Speaking of iOS 10…

Slide 18

Slide 18 text

iOS 10 Changes I originally thought of this talk before iOS 10 was announced. While I was happy with the features I’ve been describing, Apple gave us some cool new stuff.

Slide 19

Slide 19 text

Big iOS 10 Changes • Revamped, enhanced API • Notification Service Extensions • Notification Content Extensions iOS 10 brings with it a completely revamped API, and two new extensions to deal with notifications too.

Slide 20

Slide 20 text

Revamped UI • UN* classes (User Notifications) • Same concepts • Robust API iOS 10+ During the revamp, Apple replaced all the UIUserNotification classes with classes prefixed with UN. Overall, the same concepts I’ve described apply to the API, alerts, badges, sound, actions and categories, but now the API is a bit more sensible and robust - nice because lines up with UI
 The old API is deprecated so can be used, but you should like any deprecation start to move over.

Slide 21

Slide 21 text

Notable Improvements • Manage remote notifications • Inspect responses - dismissed? • Control foreground appearance iOS 10+ You can now manage remote notifications, which you had almost no control over before. 
 You can find out whether a notification was dismissed - an interesting mechanism for A/B testing…or even AI. 
 You can now control some foreground appearance too. Neato.


Slide 22

Slide 22 text

Notification Service Extensions • Called before the user is shown an alert • Chance to modify content • Download additional content iOS 10+ Notification service extensions are called before your alert is shown. It’s a great time to maximize the value of the content for your user. Perhaps you want to add a thumbnail or download a larger image, video or GIF for use inside the app. Perhaps you even want to decrypt the content of the push notification further. You then pass modified notify back

Slide 23

Slide 23 text

Notification Content Extension • Create your own UI for an extension • Full storyboard access • Non-interactive • Format data in a readable, valuable way iOS 10+ Notification content extensions are activated when the user 3D touches on a notification (later betas may unlock long press too). 
 They allow you to create rich UI to display the push information. 
 They’re a view controller like any other, so you’re able to have a storyboard and layout as many UIElements as you like with auto-layout. 
 They are however read only, and cannot be interacts with. 
 This example here of the calendar is a simple example of how putting some push content in context of the rest of their day makes for a much more understandable and valuable notification. It’s pretty cool stuff and I encourage you to think about ways to visualize the data in your pushes to add value. 


Slide 24

Slide 24 text

Learn More • Sessions 707, 708 - WWDC 2016 iOS 10+ To learn more on iOS 10, check out sessions 707 and 708. 


Slide 25

Slide 25 text

Conceptual Overview of User Notifications So that’s a conceptual overview of Notifications and the changes in iOS 10.

Slide 26

Slide 26 text

Implementation and Debugging Next up, let’s talk about how we actually start setting some of this stuff up!

Slide 27

Slide 27 text

Setting up Server Side The first part for any push notification is setting up the server side.

Slide 28

Slide 28 text

Setting up Remote Push • Create/Edit App ID • Enable Push Notifications • Upload certificates • Generate new provisioning profile • Configure, build and run Setting up push is a tricky as heck thing to do! These are the abbreviated! steps to achieve this. So let’s walk through it.

Slide 29

Slide 29 text

First up, you want to go and make you edit your App ID to enable push notifications. If you let Xcode manage your certs and provisioning this is a lot simpler. but I’ve never trusted that capabilities screen much.

Slide 30

Slide 30 text

Go ahead and click create certificate

Slide 31

Slide 31 text

This is done with Keychain access on the mac, and you just need to request a new certificate from a certificate authority. Sounds fancy. Really isn’t.

Slide 32

Slide 32 text

Fill in the fields and save it to disk.

Slide 33

Slide 33 text

and if that’s all too hard, the instructions are there again when you actually go to do this. Upload the certificate request file and you’re good to go.

Slide 34

Slide 34 text

And then boom, your push certificate is ready.

Slide 35

Slide 35 text

and at this point, you’d follow the instructions to upload it to your push service. Typically this involves exporting it out of keychain access with an optional password. This is what it looks like in the Carnival product. Your service should run some additional validation to tell you you’ve got it all right.

Slide 36

Slide 36 text

Server Sent Push Device Server APNS Cert Token(s) + Content So here’s a diagram of how a service like this goes about getting a push to your device. They use tokens and the content and talk to Apple. Apple then works out which device it is and which app and tries to do the push via it’s persistent socket connection with each device.

Slide 37

Slide 37 text

Setting up Client Side Moving on to how we set up client side

Slide 38

Slide 38 text

Registering for Push • Alerts, Badges, Sounds • Categories • Remote? • Perform at a suitable time for your user (not just straight away) Now, you’ve added your new provisioning profile, you’ve tuned on the capabilities in Xcode, and you’re ready to go. 
 You need to set up your categories and their actions and then register the lot at once with he operating system. 
 You’ll also optionally register for remote notification, and you’ll get a token at this stage.

Slide 39

Slide 39 text

Registering for push let settings = UIUserNotificationSettings(forTypes: [.Alert, .Sound, .Badge], categories: nil) UIApplication.sharedApplication().registerUserNotificationSetti ngs(settings) UIApplication.sharedApplication().registerForRemoteNotification s() This is the basic code to register for push. There’s some concepts here Types refer to alert, badge, sound categories are what we spoke about earlier, each with a set of actions. You can have multiple categories You register for the lot Then you additionally register for the push notifications. This API has changed slightly in iOS 10.

Slide 40

Slide 40 text

Becoming Registered func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { } func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) { } Once you register for push,
 One of these two methods will get called, and hopefully its not the fail case. 
 Devices always get tokens after registration, even if the user denies push. 
 Simulator will never get a token. Hand the token off to your server for push and you’re good to go!

Slide 41

Slide 41 text

Server Sent Push Token Device Server APNS Cert Token(s) + Content And this is how it all works once you have the token handing off

Slide 42

Slide 42 text

Running on Device • Notifications won’t work in the simulator • Need to use either development or production gateways • Production gateways require a production provisioning profile So, you’re up and running and you’ll notice that notifications don’t work in the iOS simulator The OS will register automatically for a given gateway based on the provisioning profile (distribution or development)

Slide 43

Slide 43 text

In code func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { } func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { } iOS <10 and the finally in here you’ll get the push. But only if your app is in the background (not restarted or swiped out of memory) There is an alternative method, that allows you to do background processing.

Slide 44

Slide 44 text

Background Fetch • Prepare/Download content for user • “content-available”:1 • ~30 seconds to do something before alert is presented to user • Much more power in iOS 10+ This will call the didReceiveRemoteNotification with fetchCompletionHandler.

Slide 45

Slide 45 text

Push Tools and The Remote Notification Payload Let’s talk about how you as a developer can use tools to send your own push, in development or even in production.

Slide 46

Slide 46 text

APNS/2 The first tool I want to share is one called APNS/2

Slide 47

Slide 47 text

Developed in house at Carnival, we use this in our infrastructure. It takes advantage of Apple’s new HTTP 2 interface and is written in Go for it’s really nice routines system and HTTP2 client.

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

https://www.kumulos.com/2015/11/11/top-8-best-push-notification-services-for-mobile-apps/ You can just google “best push notifications” and the first non ad is this post. 


Slide 50

Slide 50 text

APNS Payload { "aps" : { "alert" : { "title" : "Game Request", "body" : "Sam wants to play poker" }, "badge" : 1, "sound" : "gamerequest.wav", "category" : “GAME_REQUEST”, "content-available" : 1 }, "some_key" : "Some Value", "some_other_key" : [ "bang", "whiz" ] }

Slide 51

Slide 51 text

Troubleshooting So push is great when it works, but it’s not always smooth sailing. Let’s talk about how you’d go about troubleshooting push, both during integration and ongoing.

Slide 52

Slide 52 text

Common Pitfalls • Forgetting to regenerate provisioning profile after modifying app ID • Using the wrong APNS gateway • Using the “Fix Issue” button in Xcode. Just don’t. I deal with a lot of customers setting up put with our system, so I see the pitfalls a lot.

Slide 53

Slide 53 text

Troubleshooting • Retracing your steps • Using TN2265 • Use Persistent Connection Logs For more troubleshooting, we often find a lot of success simply retracing your steps. There’s quite a few when setting up and it’s easy to miss them. 
 There’s also Tech Note 22 65 which describes a bunch more troubleshooting ideas, but really just gets you to trace your steps.
 The final way to really dig in deep is to use the persistent connection logs.

Slide 54

Slide 54 text

Logging Apple maintains a persistent socket connection with APNS every time your phone is powered on. This logging profile when installed will log out everything going over that connection, as well as a bunch more logs from the OS. 
 To install, download it from the TN2265 and email to your phone. Restart the phone and you’re good to go.

Slide 55

Slide 55 text

Log Messages Log Message Meaning Connected to courier Connected to APNS Disconnecting in response to connection failure. Your network has blocked APNS/ TCP Port 5223 connection set ignored topics The user chose to turn off notifications Failed to parse JSON message payload Server send malformed JSON Received message for enabled topic Log message for incoming push Once you’ve synced your phone with iTunes, or easier still, use the Xcode device log, you’ll be able to search for messages along these lines. This is super interesting stuff to see where things might be going wrong. For example, blocked ports, the users turned it off, or the server side has botched the JSON.

Slide 56

Slide 56 text

2016-08-13 14:47:01 +1200 apsd[100]: : Received message for enabled topic 'com.carnivalmobile.carnivaltestapp' with payload '{ "_nid" = 57ae8a248234f60009002e2f; aps = { alert = “Oh, Hi Mark!”; "content-available" = 1; }; }' onInterface: WWAN for device token: NO with priority (null) Here’s an example log message of a payload.

Slide 57

Slide 57 text

Implementation and Debugging I wish you the best of luck with your implementation of push. It can be tricky but it’s just a matter of slowing down and making sure you’re checking those boxes. I’ve done this hundreds of times now so it’s second nature.

Slide 58

Slide 58 text

Best Practices Finally today I wanted to bring it a little less technical and talk about best practices for remote notifications. I want to start with an important statement.

Slide 59

Slide 59 text

Notifications go to people, not devices. @samjarman Notifications go to people, not devices. Remember this. People have good times to be contacted or interrupted, and they have terrible times. They might see your push and not care at all, or it might be something super important to them.

Slide 60

Slide 60 text

71% of app uninstalls are triggered by Push Notifications @samjarman Another important stat I heard recently is this. 71% of app uninstalls are triggered by Push Notifications.
 The good thing about notifications is they remind your users that your app is installed. A bad thing about notifications is they remind your users that your app is installed. Get that touchpoint wrong, and you’ve lost that user, perhaps for life. Usage, feedback and revenue are all gone. Bad push practices can really harm your bottom line.

Slide 61

Slide 61 text

Make Them Timely So my first tip is make push notifications timely. And what I mean by this is to try predict the right time to contact your user. Can you be more flexible than just when you want?

Slide 62

Slide 62 text

Respect Local Timezone Respect their timezone. It might be easy to say oh it’s 5pm here in Melbourne lets send out a push to all commuters, only to have your audience asleep in other parts of the world. If you have a sale or something, try send in the local timezone for the user. This will stagger the pushes over a window and might even reduce load on your server, if that’s required. A decent push service should give this this option.

Slide 63

Slide 63 text

Respect Back-off Times Sometimes you might want to send multiple pushes per day, or different services that interact with your app with to inform the user. Consider having a hard limit on this. The limit is relative to the value, but something like a 5-10 max per day would suit most applications. Chat apps for example, won’t have a limit. 
 Consider also an internal priority for some notifications over the other.

Slide 64

Slide 64 text

Respect Sleepy Time So yeah, sure, most people have their phones on do not disturb overnight, or at least on silent. But consider this… do you read all your notifications in the morning? or do you clear them all immediately maybe after reading the important ones? 
 If you’re part of that overnight noise, you have a lower chance of standing out. Perhaps restrict the amount of pushes you send over night and send a summary style push in the morning.

Slide 65

Slide 65 text

Keep Them Relevant Next up, keep your pushes relevant.

Slide 66

Slide 66 text

Don’t send content for anyone. Ultimately the most valuable pushes are the pushes for me. Chats, deals based on history, or news alerts based on preferences. Don’t send me junk and certainly don’t something that can’t apply to me, for whatever reasons.

Slide 67

Slide 67 text

Personalize based on journey Carnival, and services like it, offer personalization based on journey. This could be anything to do with the context of the app. What level of the game you’re on, which items you have in your cart, which news stories you’ve read. How long you’ve had the app installed, or how long it’s been since you’ve last used it. There’s a bunch of marketing and engagement automation possible here off some basic stuff.

Slide 68

Slide 68 text

Use transactional push Alternatively, but not mutually exclusively with audience segmentation is transitional push. These is the 1:1 pushes that go to a single users only. Perhaps their package is shipping, or they have a chat, or they’ve got a new like. These sorts of notifications are perfectly personalized by definition, but still adhere to the other best practices I’m talking about such as timeliness.

Slide 69

Slide 69 text

Personalise with Names Use the persons name in a push, if you have it. “Sam, check out these new doctor who toys. Tap here”. Oh, and don’t say “click”.

Slide 70

Slide 70 text

Use Precise Language Use precise language. Be obvious what you want. Make the call to action here. “You have a new chat from Ben”. “A new deal for you. Tap here for more” “Sam sent you a friend request”. You have no more than 10 words to make your impact. Use them wisely.

Slide 71

Slide 71 text

Being a Good Citizen

Slide 72

Slide 72 text

Ask for Permission Carefully That alert box that pops up after you register push may be one of the most important dialogs for your apps. 
 
 Preempt it. Onboard your user well. Explain “hey, here’s why we want to send you pushes and here’s what you get out of it. Keen?” If you explain the value before you present that alert, you’ll get a much higher opt in rate. We’ve seen rates go from 20-30% opt jump to 70-90% with these techniques. This also applies to all other dialogs such as location or bluetooth by the way.

Slide 73

Slide 73 text

Use a 3rd party push service. Don’t try this yourself in production. Scaling. Reliability. Feedback. Etc etc. 
 Just use another service.

Slide 74

Slide 74 text

Preload Content If your push drives a user to some in app content, you should really be pre-loading that with the available API first. This will delay the push by 20 seconds or so, but when they open the app, the UI should be ready to go. No one wants to be driven to a loading screen.
 Example: Facebook sometimes does this well.

Slide 75

Slide 75 text

Duplicate Notifications Inside Your App Let’s be honest, it’s super easy to clear notifications. You should always try and duplicate the notification content inside the app. This could be an activity log, a chat history or a notifications log. Make it so users can always re-read the alert text of a notification.
 Example: Tweetbot’s activity screen

Slide 76

Slide 76 text

Expose Settings If your app has different scenarios in which to send push, let the user turn off hearing about certain situations. 
 You can also use the notifications API to see which alerts they’ve enabled, and if they’ve denied you in past, you can always remind the users of the benefits (of which there should be some) of turning off push. Deep link them to the settings app and you’re done.
 Example: Swarm

Slide 77

Slide 77 text

Have more? Medium post coming!
 Tweet me! - @samjarman Do you have any best practices? Tweet them to me as I’m compiling a list for a blog post soon.

Slide 78

Slide 78 text

Conclusion • Conceptual Overview of User Notifications • Implementation and Debugging • Best Practices for Notifications So today you’ve heard about what notifications are, how to code them and how to use them for good and not evil.

Slide 79

Slide 79 text

Thank You! " Sam Jarman • iOS Developer, Sailthru • @samjarman All images subject to copyright of their original owners. - I’ve been Sam Jarman, thank you very much. Enjoy the rest of the conference.