January 7th, 2021

Use Templates Effectively

Martin Strobel
Senior Software Engineer

Every time development of a new mobile app starts, one of the first questions that needs to be answered is, “How are we going to support both iOS and Android?” Deciding on a technology to build the client-side app logic and UI alone is complicated enough, extending client specific knowledge into your backend is only going to exacerbate that pain.

Using Azure Notification Hubs’ templates, you can let each client maintain full control of how notifications will look, protecting your backend server from needing to know platform details.

Define Personalization on the Client

Let’s say you’re writing an application for ice hockey fans, to keep them in-the-know about their favorite teams’ news and scores. You’ve decided to write client apps that run on iOS and Android, using Apple Push Notification Service (APNS) and Firebase Cloud Messaging (FCM) respectively to deliver notifications. You’ll start with a simple notification, to inform the user that a game is about to start. Even for this simple scenario, you’d need to provide two slightly different notification payloads:

APNS (iOS):

{
    "aps": {
        "alert": {
            "title": "Seattle Kraken game starting soon.",
            "body": "A game you want to watch is starting in 5 minutes."
        }
    }
}

FCM (Android):

{
    "notification":{
        "title": "Seattle Kraken game starting soon.",
        "body": "A game you want to watch is starting in 5 minutes."
    }
}

One simple solution would be to have your server keep track of the two payloads that need to be sent out. When your server detects that it’s just before game time, you could issue two send HTTP requests to Azure Notification Hubs: One for iOS devices, and another for Android devices. Each time specifying that only registrations with the kraken tag should be targeted.

With only two different versions of this payload, that strategy works pretty well! But what about when you start adding other dimensions? Each new dimension multiplies the number of requests you’ll need to send to ANH to ask for a batch of notifications to be sent, and is more complexity for your server to handle. Let’s say you’ve localized this message into French and German, and have two client versions that require different payload bodies. Suddenly, instead of issuing two requests you’re needing to cycle through 12 different configurations and track the results of 12 separate operations. Each time with the correct tag expression to guard against each of your users receiving notifications in French, German, AND English.

By using Azure Notification Hub templates, you can offload this complexity to Microsoft servers, and let your client application define the notifications that will come to it. Because templates are associated with each individual device, this is easy to do in your iOS and Android applications:

APNS (iOS):

let krakenStarting = MSInstallationTemplate()
krakenStarting.body = "{\"aps\":{\"alert\":{\"title\":\"Seattle Kraken game starting soon.\",\"body\":\"A game you want to watch is starting in 5 minutes.\"}}}"
krakenStarting.addTags(["kraken", "gameStarting"])

MSNotificationHub.setTemplate(krakenStarting, forKey: "kraken-starting")

FCM (Android):

// Existing initialization code:
NotificationHub.start(this.getApplication(), /* YOUR HUB NAME */, /* YOUR CONNECTION STRING */);

// Adding the FCM specific payload for future sends:
InstallationTemplate krakenStarting = new InstallationTemplate();
krakenStarting.addTag("kraken");
krakenStarting.addTag("gameStarting");
krakenStarting.setBody("{\"notification\":{\"title\":\"Seattle Kraken game starting soon.\",\"body\":\"A game you want to watch is starting in 5 minutes.\"}}");
NotificationHub.setTemplate("kraken-starting", krakenStarting);

Note: To localize per device, all you would need to do is read the title and body from a localized resource file instead of hard coding them.

With the code above, each device defines what the “kraken-starting” template should look like for itself. This allows your server to send just one template send HTTP request to Azure Notification Hubs: a template send with the tag expression: kraken && gameStarting.

Gettin’ Dynamic with It

In the notifications sent above, the message will always be delivered looking the same. What if you wanted to include the name of the Kraken’s opponent in the title? What if your server side behavior changes, and you decide to start informing users 15 minutes before game time? Surely, pushing an update to each users’ phone before every game is too heavy-handed.

Without being able to customize the text in templates from the server side, these scenarios could force the hand of a developer into accepting the complexity of abandoning templates and generating the the payload server side. But fear not! Templates can include parameters that will be defined when you call “send”. To make the changes discussed above, we could use the following template definitions:

APNS (iOS):

krakenStarting.body = "{\"aps\":{\"alert\":{\"title\":\"Seattle Kraken v. $(opponent) starting soon.\",\"body\":\"A game you want to watch is starting in $(minutes_to_start) minutes.\"}}}"

FCM (Android):

krakenStarting.setBody("{\"notification\":{\"title\":\"Seattle Kraken v. $(opponent) starting soon.\",\"body\":\"A game you want to watch is starting in $(minutes_to_start) minutes.\"}}");

This time when you call the template send, the body of the send request will define the parameters:

{
    "opponent": "Vancouver Canucks",
    "minutes_to_start": 5
}

With this injection, the server can maintain the convenience of sending just one request when looking to inform users, while adding dynamic content into the text that will be shown to users.

Summing it Up

Templates are a versatile tool, that allow you to get a lot closer to the dream of “notifications just work.” By allowing clients to define the shape of notifications that are delivered to them, you can abstract away the platform being targeted, re-use existing localization mechanisms, and write less code to deal with notifications; all while preserving the ability to send out dynamically generated notifications. And as always, because you’re using Azure Notification Hubs, you’ll be avoiding needing to scale your compute and network capacity to deal with a burst of notifications being issued to all of your users.

Author

Martin Strobel
Senior Software Engineer

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • zeeshan badshah · Edited

    Hi,

    Thanks. 🙏 This is helpful.
    But I need to know how to add headers to templete on client devices. for example I want to add “apns-collapse-id” : “$(conversation_id)”.
    I know from some other posts that headers are supported in token (key) based APNS credentials but cannot figure out how.

    Thanks