Successful Messaging in the Age of Over-Communication

Successful Messaging in the Age of Over-Communication

The year is 2018. A vast majority of people have embraced mobile technology and with it, the ability to stay connected and engaged. While in theory, receiving emails, push notifications, SMS, and chat messages means users now have the chance to remain informed, such methods are becoming increasingly overused and contributing to the noisy landscape which in turn is selectively consumed by recipients. So as marketers or operative managers, how do you succeed at ensuring your message, sometimes a critical one, is actually engaged? Let’s start at the top.

My Message is Important

Everyone thinks so, and some people are right to think it. So how do you stand out? Messaging teams have long-relied on statistics and trends around open and click-through rates to ensure that their next message has optimal delivery. Take as an example a hypothetical grocery store sending app users a push notification to visit the store on the way home from work. If the strategy involves sending a push-notification at 5:30 pm to catch people on the commute home, this tactic is constructed on the variable of general time.

Conversely exists the strategy of “on my time” (timing). Applications can provide administrators, marketers, and managers information that is knowledgeable about the end user. In the same scenario, a grocery store can use geofencing to detect as users approach the store and notify them of sales and promotions on their personal commonly purchased products.

Both scenarios used the same messaging format, but one delivered invaluable utility while the other one took broad strokes. The latter is considered part of the noisy landscape — a message that can ultimately drive users to turn off push notifications or sometimes delete an application altogether.

 

Timing in Business Operations

Many of these messaging methods have become increasingly thought of as consumer-facing tactics. Truth is, enterprise operations have more to gain than ever by embracing the right medium at the right time. As the supply chain makes a shift to be increasingly digital, it’s not just the senior management and supervisors leveraging technology. Companies such as Amazon, Arrow Electronics, and Oneok are placing more managers and operative members into the digital environment to ensure the quality of process and deliver. How so?

Warehouse operators

  • As shifts begin, a push notification including a short list of initial items can remind operators of where to begin their work and click on the application and begin the picking process.
  • Notifications can be sent for upcoming picks or incorrectly scanned items.

Mobile workforce

  • Appointment reminders, traffic updates, and route adjustments — whether employees are on the field fixing pipeline or servicing HVAC, companies can use application data to send well-timed SMS and push notifications to keep employees on track.

Management and Supervisors

  • Performance metrics can be emailed at the day’s conclusion. How many successful picks? Who is overperforming? Who needs additional training?
  • Chatbots can bridge the gap between onboarding and company know-how. Common questions can be answered by seeking out keywords. More challenging queries can now be processed through AI-powered chatbots that can seek out common threads, tone, context, and timing to give the best possible answer.

The common element in each instance above is ‘utility.’ A message is likely to be engaged if it provides value at the right moment, and in each case above it helps workers optimally complete a task. This is the universal ingredient to successful messaging in 2018 — if you’re delivering irrelevant content at the wrong time it is likely that the user will learn to disregard messages and ultimately drive the overall process to failure.

 

Consumer Facing Timing

When it comes to customer-facing applications, timing is arguably trickier, but in truth, it’s built on the same principles as before. Earlier we took a look at how a grocery store could provide utility vs. blanket marketing. As a CMO, this is the fundamental principle that should be looked at when figuring out the best moment to engage your customers.

Great timing stems from understanding your specific consumer and their buying/use habits. Whether you’re a bank, a retailer, or a service provider, nobody likes unsolicited sales pleas having nothing to do with their day. Nevertheless, if you know when your customer is supposed to be boarding their plane, or you know when they regularly shop at your store, or you got to know a need of theirs through a customer service chatbot, leverage your knowledge to push information that will deliver the utility they seek from working with your company digitally.

How are different industries delivering this type of utility?

Banks & Money Management

  • Reserved for truly personal and time-critical information, banks should use a mixture of SMS and push notifications to notify users of security breaches and irregular withdrawals from their accounts.
  • For less pressing information including account statements and policy updates, an email will ensure there is a delivered record. Without the urgency
  • Companies like Mint and YNAB are communicating updates on excessive spending and budget thresholds through push notifications that ensure users keep an eye on their finances day-to-day.

Travel & Logistics

  • Travel updates, flight cancellations, train re-routes and detours. When there are adjustments that impact the path of travel, companies can communicate with passengers through SMS and push notifications to potentially save a trip to the airport and get rescheduled through the application.

Retailers

  • Brands recognize the importance of keeping consumers connected to their carts, regardless of if they complete their transaction. If a consumer has added products to their cart in the app and they lock their phone/go inactive, a push notification to remind them that they have items in their cart and increase the likelihood of a completed purchase.
  • To help reconnect customers to brands, emails are helpful for helping customers plan for sales events. Customers can receive coupons after not visiting their site for a certain set of days, invites to sale events on products based on their shopping habits, or even calendar events so customers can have a sale set in their personal calendars.

The Noisy Messaging Landscape

Email, SMS, push notifications, and in-app messaging began with humble beginnings — mechanisms for maintaining personal relationships and running business processes and workflows. Marketers saw an opportunity to embed themselves as part of that world, first by email, then by text, and today through push notifications and chat-bots.

The result is a digital space filled with endless noise. Consumers and employees are getting inundated with messages. According to the Worldwide Daily Email Traffic Report, by 2019 people will receive and send between 100 and 250 emails a day.

 

Worldwide-Daily-Email-Traffic

                                          Worldwide Daily Email Traffic

 

Similarly, text messaging, once an exclusive space for friends, family, and close colleagues, is becoming an increasingly used medium for businesses and marketers to promote products and services. Even though there are the limitations to length and content, it’s a popular enough medium that people will exchange anywhere between 25 and 130 daily messages.

 

Daily -Texts

                                                  Daily Texts by U.S. Adults

 

Last but not least, push notifications, in-app messaging, and toast, have finished saturating the space by engaging audiences across all connected devices (PC, tablet, phone), regardless of whether the device is in use or not. As with the previous two mediums, marketers have found a way to interrupt the average person as many as 45 times per day with push notifications.

 

Benchmark-Open-Rates

                               Push Notifications Benchmark Open Rates

 

So what does this all mean? Unsurprisingly, the limited bandwidth and desire to sift through content means open and engagement rates are at an all-time low.

 

You can still stand out

The reality is when used at the right time and for the right purpose, these three mediums can be highly effective at engaging users. Shockoe approaches messaging in the same way we approach all other technology; we incorporate utility into technology that will make work easier. The result should be a user base that will grow to believe in the value of your message, your application, and your service.

If you’re not sure how to approach messaging in your own application, internal or customer facing, give us a shout! We’ve got a few tricks up our sleeve to help your company leverage the power of effective messaging.

 

Jaime De La Ree

Jaime De La Ree

Business Development Lead

Jaime De La Ree is the acting business development lead at Shockoe with five years of experience in mobile technology consulting. Before joining Shockoe, Jaime worked in supply chain distribution management and later as a non-profit technology partner. When he’s not helping Shockoe build partnerships, Jaime spends his time with his wife and son, and in the remaining time is an avid carpenter, photographer, and astronomer.

Scaling a Push Notification Server

Scaling a Push Notification Server

Previously we explored the topic of setting up a sandbox push notification server in Node.js. This featured a Mongodb instance to store users and device IDs, as well as endpoints to register users and send them the push notifications all at once. But what happens when you need to target individual devices instead of blasting your entire user base all at once? All of a sudden instead of processing one API call to send notifications to all of your users, you’re fielding multiple calls at once, possibly on the order of thousands of requests per second during peak user hours for your application. Fortunately, Node.js has built-in tools to help you scale your server.

The first issue we can tackle is breaking our Send endpoint out to work as a tool to send an individual push notification. We’ll assume in this case that the requests to this endpoint will come from another source with knowledge of the device Id and operating system to target. We’ll again use restify to set up our server:

 

//server.js

const restify = require('restify');

const server = restify.createServer({
name : 'pushTest'
});

// this allows us to parse the POST request body
server.use(restify.plugins.bodyParser());

server.listen(8080, () => {
console.log('listening on port 8080');
});

// set up a basic route
server.post('/', (req, res) => {
// parse the request body
let body = JSON.parse(req.body);

// check to make sure the body has the correct fields
if (body && body.platform) {
// send push here
}
// send a success response
res.send(200);
});

We’ll skip over actually sending the push since we covered that in our previous post. Once we start the server, we can use the ApacheBench command line tool to load test it. In a separate terminal window, paste:

ab -p test.json -c 20 -t 10 http://localhost:8080/

Where test.json is a local json file with test data. This will open up 20 connections per second for 10 seconds on our server. When we run this we get an output of about 150 successful requests per second, but let’s see if we can do better. The cluster module ships with node and allows us to spin up a server for every CPU we have on our machine. In a separate file we can have a “master” node that spins up servers for every CPU we have on our machine:

// master.js

const cluster = require('cluster');
const os = require('os');

// check if master
if (cluster.isMaster) {
// find out how many CPUs we have available
const cpuNum = os.cpus().length;

console.log(`Found ${cpuNum} CPUs`);

// fork the process for as many CPUs as we have
for (let i = 0; i < cpuNum; i++) {
cluster.fork();
}
} else {
// otherwise spin up server
require('./server');
}

Now instead of running

node server.js, run

node master.js

On my personal machine, this spins up eight different instances of the push server, and when I run our same ab command, I’m now seeing over 500 requests per second. This works by running master once and then running it again every time cluster.fork() is called for as many CPUs as we have. If master.js is entered as a result of calling fork, the isMaster call will fail and it will spin up the server.

This is a simple example of the built-in power of Node.js to increase the scalability of your application and expertly handle any kind of heavy load your test servers might need to endure.

John Surface

John Surface

Senior Developer

With a birth weight of just under seven and a half pounds, John has in less than three decades managed to gain thirteen stone and several years of experience as a full-stack and mobile engineer. He does his part to slow the spin of the earth spiraling out of control by creating robust backend solutions and intuitive cross-platform and native mobile applications.

Creating a Push Notification Server with Node.js

Creating a Push Notification Server with Node.js

At Shockoe we’re used to integrating our clients’ complicated backend systems into our apps, and this often includes push notifications. However, to get that initial proof that our app is playing nicely with GCM and APNS we’ll sometimes rig up a sandbox server of our own. Since we’re used to JavaScript, Node is an obvious go-to. Here are the steps for rigging up a simple push notification server in Node.js. If you’re looking for a deeper dive into messaging 2018, you can also check out Shockoe’s Innovative Brand Messaging in a World Noise page shown below — it’s just as important to know when to use push notifications, especially in today’s saturated push-notification environment.

How to Message in a World of Noise

Push notifications without a sound messaging strategy can be quickly damaging to a brand’s reputation. See how Shockoe is working with leading companies to build the right messaging tactics to delight the modern-day user.

Learn to Message in 2018

A push notification server consists of two parts: storing deviceIds and sending push notifications. To achieve this we’ll create two endpoints: register and send. Register will utilize the mongodb node module mongoose and Send will leverage two platform-specific node modules: apns and node-gcm. We’ll also be using restify to set up our endpoints.

Register

For a basic implementation we only need two pieces of information: the deviceId and platform (Android or iOS). Technically–in some mongoose schema code golf scenario–we just need the deviceId, and could make both calls with one always failing.

So our mongoose schema, with the proper requirements, would look something like this:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Device = new Schema({
    deviceId : String,
    platform : String
});

const DeviceSchema = mongoose.model('Device', Device);

Mongoose is generally a lot more powerful than this implementation, with validations and enumerations that allow for easy error checking, but for the purposes of this demo we’ll use a basic schema. After making sure mongodb is installed and running on your machine, our restify endpoint would look something like this:

const restify = require('restify');

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'connection error:'));

db.once('open', function(){
    console.log('db open');
});

mongoose.connect('mongodb://localhost/pushserver');

const server = restify.createServer({
    name : 'pushServer'
});

server.use(restify.plugins.bodyParser());

server.post('/register', (req, res, next) => {
    let body = JSON.parse(req.body);

    if (body) {
        let newDevice = new DeviceSchema(body);
        newDevice.save(err => {
            if (!err) {
                res.send(200);
            } else {
                res.send(500);
            }
        }
    }
}

Ideally we would perform a find on DeviceSchema to make sure we’re not adding duplicate devices.

Send

For Send we’ll implement a basic endpoint that will send a push notification to every device in the database. We can use a simple GET, grab the devices from mongo, and call functions to send the push, based on whether the target is an iOS or an Android device. The Android push module can take an array of deviceId’s instead of one at a time, so we’ll push those ids onto an array and call the sendAndroid function on all of them.

server.get('/send', (req, res) => {
    DeviceSchema.find( (err, devices) => {
        if (!err && devices) {
            let androidDevices = [];
            devices.forEach(device => {
                if (device.platform === 'ios') {
                    sendIos(device.deviceId);
                } else if (device.platform === 'android') {
                    androidDevices.push(device.deviceId);
                }
            });
            sendAndroid(androidDevices);
            res.send(200);
        } else {
            res.send(500);
        }
    });
});

Ideally we would only send the 200 response once we were sure that every push had been sent successfully, but for now it will indicate that the send functions were called.

Our sendIos function will leverage the apns module, which takes an options object. Make sure to include your push key and certificate .pem files at the root of your project:

const apns = require('apns');

const options = {
    keyFile  : 'key.pem',
    certFile : 'cert.pem',
    debug    : true,
    gateway  : 'gateway.sandbox.push.apple.com',
    errorCallback : function(num, err) {
        console.error(err);
    }
};

function sendIos(deviceId) {
    let connection = new apns.Connection(options);

    let notification = new apns.Notification();
    notification.device = new apns.Device(deviceId);
    notification.alert = 'Hello World !';

    connection.sendNotification(notification);
}

For android we’ll use node-gcm. Make sure you have your api key:

const gcm = require('node-gcm');

function sendAndroid(devices) {
    let message = new gcm.Message({
        notification : {
            title : 'Hello, World!'
        }
    });

    let sender = new gcm.sender('<YOUR_API_KEY_HERE>');

    sender.send(message, {
        registrationTokens : devices
    }, function(err, response) {
        if (err) {
            console.error(err);
        } else {
            console.log(response);
        }
    });
}

After that it’s just a simple matter of running your project and you’re ready to hit these endpoints and test push notifications on your app!

Want to chat about Push in your App?

We’re all ears! We’ll help your team communicate with your audience more effectively through app-based push notifications. Give us a ring and our team of strategist and developers will discuss with you ways to bring your team’s strategy up to tomorrow’s standards.

Enabling Push Notifications Part 3 of 3

Enabling Push Notifications Part 3 of 3

Android Code Setup

Android is set up the same way with just a few minor differences.  On Android, we use the ti.cloudpush module and ti.cloud for Push Notifications.  After registering with the server, the function should return a device token.  Save this device token in-app properties.

Example: Ti.App.Properties.setString(‘deviceToken’, e.deviceToken);

 However, make sure you set the application properties on the callback and not inside the common JS library.  These lib files can sometimes act strangely when it comes to saving app properties.

//require the notifications common js lib file
var notifications = require('notifications');
//check for a device token
var deviceToken = Ti.App.Properties.getString('deviceToken');

//check to see if deviceToken exists
if(deviceToken === '') {
	//get the devices token
	deviceToken = notifications.getToken();
	//set the deviceToken app property
	Ti.App.Properties.setString('deviceToken', deviceToken);
}

In the index js file we set up the device to look for a token and if there is not one to register the user for Push Notifications.

//require ti.cloudpush module
var CloudPush = require('ti.cloudpush');
//require ti.cloud module
var Cloud = require('ti.cloud');

//get device token
exports.getToken = function() {
  // Initialize the module
  CloudPush.retrieveDeviceToken({
      success: deviceTokenSuccess,
      error: deviceTokenError
  });
  // Enable push notifications for this device
  function deviceTokenSuccess(e) {
      CloudPush.enabled = true;
      return e.deviceToken;
  }
  function deviceTokenError(e) {
      alert('Failed to register for push notifications! ' + e.error);
  }
  // Process incoming push notifications
  CloudPush.addEventListener('callback', function (evt) {
      alert(evt.payload);
  });
};

The device token that is generated will allow the application to receive notifications.  You will be able to register the device with ‘Channels’.   The server can push information to certain Channels.  Say you want sports news.  Then a Channel called ‘sports_updates’ could be created.  Channels are not done server side.  Creation is done on the user side.  There is not a way to manually add a channel on the ACS Dashboard.  Once a user subscribes to a channel for the first time then it is created.

Subscribing a device token to a channel is a function in the common JS library you created for Push Notifications.  In this function, we pass two variables. One being the channel and the other being the device token that was generated earlier.  Each one is needed for the subscription.  Now the module ti.cloud will be required for this project as well.  The first module, ti.cloudpush, is just for registering a device token, and ti.cloud does the rest.  So we add ti.cloud to the notifications lib file.

//subscribe to a specific channel
exports.subscribe = function(channel, token) {
    Cloud.PushNotifications.subscribeToken({
        device_token: token,
        channel: channel
    }, function (e) {
        if (e.success) {
            alert('Subscribed');
        } else {
            alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

Subscribing a device token to a channel is a function in the common JS library you created for Push Notifications.  In this function, we pass two variables. One is the channel and the other being the device token that was generated earlier.  Each one is needed for the subscription.

You will also need to allow the user to unsubscribe from Channel based Pushed Notifications, which can be done using the unsubscribe function.

//unsubsribe from a specific channel
exports.unsubscribe = function(channel, token) {
    Cloud.PushNotifications.unsubscribeToken({
        device_token: token,
        channel: channel,
    }, function (e) {
        if (e.success) {
            alert('Unsubscribed');
        } else {
            alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

//device token
var deviceToken = Ti.App.Properties.getString('deviceToken');
//require notificiations lib file
var notifications = require('notifications');
//create view to house label and buttons
var container = Ti.UI.createView({
	width           : Ti.UI.FILL,
	height          : Ti.UI.FILL,
	top             : 30,
	layout          : 'vertical',
	backgroundColor : '#FFFFFF'
});
//create label for title
var channelLabel = Ti.UI.createLabel({
	width     : Ti.UI.FILL,
	height    : Ti.UI.SIZE,
	text      : 'Select a Channel',
	textAlign : 'center'
});
//create sports channel button
var sportsButton = Ti.UI.createButton({
	width     : Ti.UI.FILL,
	height    : Ti.UI.SIZE,
	top       : 10,
	title     : 'Sports'
});
//sports button event listener
sportsButton.addEventListener('click', function(e){
	if(deviceToken !== '') {
		notifications.subscribe('sports_updates', deviceToken);
	} else {
		alert('Error, device not registered for Push Notifications');
	}
});
//add elements together
container.add(channelLabel);
container.add(sportsButton);
$.win.add(container);

Now we need to create a sample page to test this all out with.  It will have a view, label, and button.  Clicking this button will subscribe the user to sports updates from the ACS server.

 This will create a basic view with a label and button on top of the window.  It will say ‘Sports’ and upon click will call the register function from the notifications lib file.

notifications.js

exports.userLogin = function() {
    // Log in to ACS
    Cloud.Users.login({
        login: 'push_notifications',
        password: 'pushy'
    }, function (e) {
        if (e.success) {
            alert('Login successful');
        } else {
            alert('Error:\n' +
                ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

You can also have users set up on the ACS server and log them in and subscribe to channels.  However, the user account must exist.  Generally, one user is created for the public, such as the ‘push_notifications’ user we see in the code.   This is perfect for just a basic app with notifications.  If you want user sessions and give the ability for people to create their own accounts you will have to look into Titanium.Cloud.Users on the documentation.

Sending Push Notifications using the Dashboard (http://dashboard.appcelerator.com)

This will cover three different ways for notifications to be sent.

Sending to Specific Channel/Users
Sending to All Channels
Setting up Recurring Notifications

 

Go to the Dashboard, then Cloud, then Push Notifications.  You will see a button that says ‘Send Push Notification’, click on it.

Sending to Specific Channel/Users

  • Channel – Which channel to send the notification to

    • Choose ‘Specific Channel’

  • Choose ‘Specific Channel’

  • Users – You can choose to enter a username if you have created any to notify just users who subscribe to that channel.

  • Alert – The message body you want the user to see

  • Send When – The time you would like to send the notification

    • Choose ‘Send Now’

  • Title – The title of the notification

Let’s say we notify the ‘sports’ channel, then we need to choose ‘Specific Channel’ under the Channel.  Then under ‘Channel Name’ you would put ‘sports’.  The ACS server is Case Sensitive, so stick with lowercase or camel case.  For the ‘Alert’ section just come up with something such as ‘Richmond, Virginia to get a Major NFL Team’.  Under ‘Send When’ choose ‘Send Now’.  Then for ‘Title’ enter ‘WZYB Sports’ or something like that.

 

Click ‘Save Changes’ which will send the notification to the subscriber devices.

Sending to All Channels

  • Channel – Which channel to send the notification to

    • Choose ‘All Channels’

  • Alert – The message body you want the user to see

  • Send When – The time you would like to send the notification

    • Choose ‘Send Now’

  • Title – The title of the notification

Click ‘Save Changes’ which will send the notification to the subscriber devices.

Setting up Recurring Notifications

  • Channel – Which channel to send the notification to

    • Choose ‘All Channels’ or ‘Specific Channel’

  • Alert – The message body you want the user to see

  • Send When – The time you would like to send the notification

    • Choose ‘Recurring’

    • Enter the Start Date, End Date, Cycle and Time of Day

  • Title – The title of the notification

Click ‘Save Changes’ which will send the notification to the subscriber devices.

That concludes this tutorial on Push Notifications.  Please feel free to leave a comment and let us know if this worked for you.

 

Enabling Push Notifications Part 2 of 3

Enabling Push Notifications Part 2 of 3

This document is intended for the average Titanium Developer to enable push notifications.  It is assumed that the reader already has a basic knowledge of Titanium and the APIs.

Today we will talk about Part 2 of 3 of Push Notifications, which begins with Google App Registration.

Register your application with Google

Android Setup

  1. Create a Google API Project

  2. Register with Appcelerator Cloud Services

Step 1: Create a Google API Project

 

You will need to open the Google Developers Console by visiting https://cloud.google.com/console. From there you will need to sign in with your Google ID that you want to be associated with this project.  Once signed in you will see a basic screen and a big red button that says ‘CREATE PROJECT’.

Enter a Project Name, and ignore Project ID.  Project ID is randomly generated by Google to avoid duplication of IDs.  Click the ‘Create’ button and the Google Developer.

The console should refresh.  Now you should be on the projects Overview page.  At the top of this page, you will see Project ID and Project Number.

 

Copy the Project Number, since this will be used at a later point as the GCM Sender ID.  On the left corner of the page, there is an APIs & Auth section.  Go to that page and a list of API items will populate.  Turn On the Google Cloud Messaging for Android.

Again under APIs & Auth you will see ‘Credentials’, click here.  Now you will see a section called ‘Public API Access’.  Click the ‘CREATE NEW KEY’ button to generate an API Access Key.

A popup will appear, on that select ‘Server Key’.  Another popup will appear asking you to enter IP Addresses in the text field, just click ‘Create’.

DO NOT ENTER ANY IP ADDRESSES

Now under the Public API access section, there is a section for API key with a rather strange combination of letters & numbers.  Copy that text and hang onto it.  Now go to the Appcelerator Dashboard https://dashboard.appcelerator.com/.

As before select the app you are working with and click the ‘Cloud’ tab.  On the left menu click ‘Settings & Configurations’.  Then on the tabbed menu click ‘Android Push’.  It will ask you for the GCM API Key and GCM Sender ID, which you should have saved.  Enter those values in and click ‘Save Changes’.

Implement the code into a Common JS library

Ensure that you are using a Common JS library for notifications.  Create a ‘notifications.js’ file inside the ‘lib’ folder.  If the folder does not exists then create it.

iOS Code Setup

With iOS, you must use Ti.Network.registerForPushNotifications the first time the user enters the application.  After registering with the server, the function should return a device token.  Save this device token in-app properties.

Example: Ti.App.Properties.setString(‘deviceToken’, e.deviceToken);

However, make sure you set the application properties on the callback and not inside the common JS library.  These lib files can sometimes act strangely when it comes to saving app properties.

index.js

//require the notifications common js lib file
var notifications = require('notifications');
//check for a device token
var deviceToken = Ti.App.Properties.getString('deviceToken');

//check to see if deviceToken exists
if(deviceToken === '') {
	//create a device token by registering for notifications
	deviceToken = notifications.register();
	//set the deviceToken app property
	Ti.App.Properties.setString('deviceToken', deviceToken);
}
//open the index window
$.index.open();

//controller
var mainWindow = Alloy.createController('Main').getView();
//open the mainWindow
mainWindow.open();

notifications.js

//require ti.cloud for iOS Notifications
var Cloud = require('ti.cloud');

//register the device and receive a token
exports.register = function() {
    Ti.Network.registerForPushNotifications({
        // Specifies which notifications to receive
        types: [
            Ti.Network.NOTIFICATION_TYPE_BADGE,
            Ti.Network.NOTIFICATION_TYPE_ALERT,
            Ti.Network.NOTIFICATION_TYPE_SOUND
        ],
        success: deviceTokenSuccess,
        error: deviceTokenError,
        callback: receivePush
    });
    // Process incoming push notifications
    function receivePush(e) {
        alert('Received push: ' + JSON.stringify(e));
    }
    // Save the device token for subsequent API calls
    function deviceTokenSuccess(e) {
        return e.deviceToken;
    }
    // Display an error upon failure to register
    function deviceTokenError(e) {
        alert('Failed to register for push notifications! ' + e.error);
    }
};

The device token that is generated will allow the application to receive notifications.  You will be able to register the device with ‘Channels’.   The server can push information to certain Channels.  Say you want sports news updates.  Then a Channel called ‘sports_updates’ could be created.  Channels are not done on the server side.  Creation is done on the user side.  There is not a way to manually add a channel on the ACS Dashboard.  Once a user subscribes to a channel for the first time then it is created.


//subscribe to a specific channel
exports.subscribe = function(channel, token) {
    Cloud.PushNotifications.subscribeToken({
        device_token: token,
        channel: channel
    }, function (e) {
        if (e.success) {
            alert('Subscribed');
        } else {
            alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

Subscribing a device token to a channel is a function in the common JS library you created for Push Notifications.  In this function, we pass two variables. One is the channel and the other being the device token that was generated earlier.  Each one is needed for the subscription.


//unsubsribe from a specific channel
exports.unsubscribe = function(channel, token) {
    Cloud.PushNotifications.unsubscribeToken({
        device_token: token,
        channel: channel,
    }, function (e) {
        if (e.success) {
            alert('Unsubscribed');
        } else {
            alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

You will also need to allow the user to unsubscribe from Channel based Pushed Notifications, which can be done using the unsubscribe function.

Main.js

//device token
var deviceToken = Ti.App.Properties.getString('deviceToken');
//require notificiations lib file
var notifications = require('notifications');
//create view to house label and buttons
var container = Ti.UI.createView({
	width           : Ti.UI.FILL,
	height          : Ti.UI.FILL,
	top             : 30,
	layout          : 'vertical',
	backgroundColor : '#FFFFFF'
});
//create label for title
var channelLabel = Ti.UI.createLabel({
	width     : Ti.UI.FILL,
	height    : Ti.UI.SIZE,
	text      : 'Select a Channel',
	textAlign : 'center'
});
//create sports channel button
var sportsButton = Ti.UI.createButton({
	width     : Ti.UI.FILL,
	height    : Ti.UI.SIZE,
	top       : 10,
	title     : 'Sports'
});
//sports button event listener
sportsButton.addEventListener('click', function(e){
	if(deviceToken !== '') {
		notifications.subscribe('sports_updates', deviceToken);
	} else {
		alert('Error, device not registered for Push Notifications');
	}
});
//add elements together
container.add(channelLabel);
container.add(sportsButton);
$.win.add(container);

Now we need to create a sample page to test this all out with.  It will have a view, label, and button.  Clicking this button will subscribe the user to sports updates from the ACS server.

This will create a basic view with a label and button on top of the window.  It will say ‘Sports’ and upon click will call the register function from the notifications lib file.

notifications.js Again


exports.userLogin = function() {
    // Log in to ACS
    Cloud.Users.login({
        login: 'push_notifications',
        password: 'pushy'
    }, function (e) {
        if (e.success) {
            alert('Login successful');
        } else {
            alert('Error:\n' +
                ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

You can also have users set up on the ACS server and log them in and subscribe to channels.  However, the user account must exist.  Generally, one user is created for the public, such as the ‘push_notifications’ user we see in the code.   This is perfect for just a basic app with notifications.  If you want user sessions and give the ability for people to create their own accounts you will have to look into Titanium.Cloud.Users on the documentation.

 

Try it and leave a comment below to let us know if you had any problems following these steps.

We will continue next week with part 3.