Push Notifications are a great way to keep your users engaged and informed about your app. You can reach your entire user base quickly and effectively. This guide will help you through the setup process and the general usage of Parse to send push notifications.
If you haven't installed the SDK yet, please head over to the Push QuickStart to get our SDK up and running.
Currently .NET SDK can receive push on Windows 8, Windows Phone 8, Xamarin iOS and Xamarin Android.
If you want to start using push on Windows 8, start by completing the Windows 8 Push tutorial to learn how to configure your app. Come back to this guide afterwards to learn more about the push features offered by Parse.
Windows Phone 8 supports authenticated and unauthenticated push notifications. Authenticated push notifications are not supported at this time. In the meantime, enjoy toast push notifications without any required setup. Some things you need to keep in mind:
- The communication between Parse and Microsoft's cloud is unencrypted. The communication between your device and Parse will always be secure.
- You are limited to 500 pushes per day per subscription.
If you want to start using push on Xamarin iOS, start by completing the iOS Push tutorial to learn how to configure your push certificate.
If you want to start using push on Unity Android, start by completing Android Push tutorial to learn how to configure your app.
Every Parse application installed on a device registered for push notifications has an associated Installation
object. The Installation
object is where you store all the data needed to target push notifications. For example, in a baseball app, you could store the teams a user is interested in to send updates about their performance. Saving the Installation
object is also required for tracking push-related app open events.
On .NET, Installation
objects are available through the ParseInstallation
class, a subclass of ParseObject
. It uses the same API for storing and retrieving data. To access the current Installation
object from your .NET app, use the ParseInstallation.CurrentInstallation
property.
While it is possible to modify a ParseInstallation
just like you would a ParseObject
, there are several special fields that help manage and target devices.
channels
: AnIEnumerable<string>
of the channels to which a device is currently subscribed. In .NET, this field is accessible through theChannels
property.timeZone
: The current time zone where the target device is located. This field is readonly and can be accessed via theTimeZone
property. This value is synchronized every time anInstallation
object is saved from the device.localeIdentifier
: The locale identifier of the device in the format [language code]-[COUNTRY CODE]. The language codes are two-letter lowercase ISO language codes (such as "en") as defined by ISO 639-1. The country codes are two-letter uppercase ISO country codes (such as "US") as defined by ISO 3166-1. This value is synchronized every time aParseInstallation
object is saved from the device (readonly).deviceType
: The type of device, "ios", "android", "winrt", "winphone", or "dotnet". This field is readonly and can be accessed via theDeviceType
property.pushType
: This field is reserved for directing Parse to the push delivery network to be used. If the device is registered to receive pushes via GCM, this field will be marked "gcm". If this device is not using GCM, and is using Parse's push notification service, it will be blank (readonly).installationId
: Unique Id for the device used by Parse. This field is readonly and can be accessed via theInstallationId
property.deviceToken
: The Apple generated token used for iOS devices, or Google generated token used for Android devices (readonly).channelUris
: The Microsoft-generated push URIs for Windows devices. This field is readonly and can be accessed via theDeviceUris
property.appName
: The display name of the client application to which this installation belongs. This field is readonly and can be accessed via theAppName
property.appVersion
: The version string of the client application to which this installation belongs. This field is readonly and can be accessed via theAppVersion
property.parseVersion
: The version of the Parse SDK which this installation uses. This field is readonly and can be accessed via theParseVersion
property.appIdentifier
: A unique identifier for this installation's client application. This field is readonly and can be accessed via theAppIdentifier
property. On Windows 8, this is theWindows.ApplicationModel.Package
id; on Windows Phone 8 this is the ProductId; in other .NET applications, this is theApplicationIdentity
of the currentAppDomain
There are two ways to send push notifications using Parse: channels and advanced targeting. Channels offer a simple and easy to use model for sending pushes, while advanced targeting offers a more powerful and flexible model. Both are fully compatible with each other and will be covered in this section.
Sending notifications is often done from the Parse.com push console, the REST API or from Cloud Code. However, push notifications can also be triggered by the existing client SDKs. If you decide to send notifications from the client SDKs, you will need to set Client Push Enabled in the Push Notifications settings of your Parse app.
However, be sure you understand that enabling Client Push can lead to a security vulnerability in your app, as outlined on our blog. We recommend that you enable Client Push for testing purposes only, and move your push notification logic into Cloud Code when your app is ready to go into production.

You can view your past push notifications on the Parse.com push console for up to 30 days after creating your push. For pushes scheduled in the future, you can delete the push on the push console as long as no sends have happened yet. After you send the push, the push console shows push analytics graphs.
The simplest way to start sending notifications is using channels. This allows you to use a publisher-subscriber model for sending pushes. Devices start by subscribing to one or more channels, and notifications can later be sent to these subscribers. The channels subscribed to by a given Installation
are stored in the channels
field of the Installation
object.
A channel is identified by a string that starts with a letter and consists of alphanumeric characters, underscores, and dashes. It doesn't need to be explicitly created before it can be used and each Installation
can subscribe to any number of channels at a time.
An installation's channels can be set using the Channels
property of ParseInstallation
. For example, in a baseball socre app, we could do:
// When users indicate they are Giants fans, we subscribe them to that channel.
var installation = ParseInstallation.CurrentInstallation;
installation.Channels = new List<string> { "Giants" };
await installation.SaveAsync();
Alternatively, you can insert a channel into Channels
without affecting the existing channels using the AddUniqueToList
method of ParseObject
using the following:
var installation = ParseInstallation.CurrentInstallation;
installation.AddUniqueToList("channels", "Giants");
await installation.SaveAsync();
Finally, ParsePush
provides a shorthand for inserting a channel into Channels
and saving:
await ParsePush.SubscribeAsync("Giants");
Once subscribed to the "Giants" channel, your Installation
object should have an updated channels
field.

Unsubscribing from a channel is just as easy:
var installation = ParseInstallation.CurrentInstallation;
installation.RemoveAllFromList("channels" new List<string> { "Giants" });
await installation.SaveAsync();
Or, using ParsePush:
ParsePush.UnsubscribeAsync("Giants");
The set of subscribed channels is cached in the CurrentInstallation
object:
var installation = ParseInstallation.CurrentInstallation
IEnumerable<string> subscribedChannels = installation.Channels;
If you plan on changing your channels from Cloud Code or the data browser, note that you'll need to call FetchAsync
prior to this line in order to get the most recent channels.
In the .NET SDK, the following code can be used to alert all subscribers of the "Giants" channel that their favorite team just scored. This will display a toast notification to Windows users. iOS users will receive a notification in the notification center and Android users will receive a notification in the system tray.
// Send a notification to all devices subscribed to the "Giants" channel.
var push = new ParsePush();
push.Channels = new List<string> {"Giants"};
push.Alert = "The Giants just scored!";
await push.SendAsync();
If you want to target multiple channels with a single push notification, you can use any IEnumerable<string>
of channels.
While channels are great for many applications, sometimes you need more precision when targeting the recipients of your pushes. Parse allows you to write a query for any subset of your Installation
objects using the querying API and to send them a push.
Since ParseInstallation
is a subclass of ParseObject
, you can save any data you want and even create relationships between Installation
objects and your other objects. This allows you to send pushes to a very customized and dynamic segment of your user base.
Storing data on an Installation
object is just as easy as storing any other data on Parse. In our Baseball app, we could allow users to get pushes about game results, scores and injury reports.
// Store the category of push notifications the user would like to receive.
var installation = ParseInstallation.CurrentInstallation;
installation["scores"] = true;
installation["gameResults"] = true;
installation["injuryReports"] = true;
await installation.SaveAsync();
You can even create relationships between your Installation
objects and other classes saved on Parse. To associate an Installation with a particular user, for example, you can simply store the current user on the ParseInstallation
.
// Associate the device with a user
var installation = ParseInstallation.CurrentInstallation;
installation["user"] = ParseUser.CurrentUser;
await installation.SaveAsync();
Once you have your data stored on your Installation
objects, you can use a ParseQuery
to target a subset of these devices. Installation
queries work just like any other Parse query, but we use the special static property ParseInstallation.Query
to create it. We set this query on our ParsePush
object, before sending the notification.
var push = new ParsePush();
push.Query = from installation in ParseInstallation.Query
where installation.Get<bool>("injuryReports") == true
select installation;
push.Alert = "Willie Hayes injured by own pop fly.";
await push.SendAsync();
We can even use channels with our query. To send a push to all subscribers of the "Giants" channel but filtered by those who want score update, we can do the following:
var push = new ParsePush();
push.Query = from installation in ParseInstallation.Query
where installation.Get<bool>("scores") == true
select installation;
push.Channels = new List<string> { "Giants" };
push.Alert = "Giants scored against the A's! It's now 2-2.";
await push.SendAsync();
Alternatively, we can use a query that constrains "channels" directly:
var push = new Parse.Push();
push.Query = from installation in ParseInstallation.Query
where installation.Get<bool>("scores") == true
where installation.Channels.Contains("Giants")
select installation;
push.Alert = "Giants scored against the A's! It's now 2-2.";
await push.SendAsync();
If we store relationships to other objects in our Installation
class, we can also use those in our query. For example, we could send a push notification to all users near a given location like this.
// Find users in the Seattle metro area
var userQuery = ParseUser.Query.WhereWithinDistance(
"location",
marinersStadium,
ParseGeoDistance.FromMiles(1));
var push= new ParsePush();
push.Query = from installation in ParseInstallation.Query
join user in userQuery on installation["user"] equals user
select installation;
push.Alert = "Mariners lost? Free conciliatory hotdogs at the Parse concession stand!";
await push.SendAsync();
Push notifications can do more than just send a message. On Xamarin, Windows, Windows Phone 8, pushes can also include a title, as well as any custom data you wish to send. An expiration date can also be set for the notification in case it is time sensitive.
If you want to send more than just a message, you will need to use an IDictionary<string, object>
to package all of the data. There are some reserved fields that have a special meaning.
alert
: the notification's message.badge
: (iOS only) the value indicated in the top right corner of the app icon. This can be set to a value or toIncrement
in order to increment the current value by 1.sound
: (iOS only) the name of a sound file in the application bundle.content-available
: (iOS only) If you are a writing a Newsstand app, or an app using the Remote Notification Background Mode introduced in iOS7 (a.k.a. "Background Push"), set this value to 1 to trigger a background download.category
: (iOS only) the identifier of theUIUserNotificationCategory
for this push notification.uri
: (Android only) an optional field that contains a URI. When the notification is opened, anActivity
associated with opening the URI is launched.title
: (Android, Windows 8, and Windows Phone 8 only) the value displayed in the Android system tray or Windows toast notification.
For example, to send a notification that contains a title, you can do the following:
var push = new ParsePush();
push.Channels = new List<string> {"Mets"};
push.Data = new Dictionary<string, object> {
{"title", "Score Alert"}
{"alert", "The Mets scored! The game is now tied 1-1!"},
};
await push.SendAsync();
When a user's device is turned off or not connected to the internet, push notifications cannot be delivered. If you have a time sensitive notification that is not worth delivering late, you can set an expiration date. This avoids needlessly alerting users of information that may no longer be relevant.
There are two properties provided by the ParsePush
class to allow setting an expiration date for your notification. The first is Expiration
which simply takes a DateTime?
specifying when Parse should stop trying to send the notification.
var push = new ParsePush();
push.Expiration = new DateTime(2015, 8, 14);
push.Alert = "Season tickets on sale until August 14th!";
await push.SendAsync();
There is however a caveat with this method. Since device clocks are not guaranteed to be accurate, you may end up with inaccurate results. For this reason, the ParsePush
class also provides the ExpirationInterval
property which accepts a TimeSpan
. The notification will expire after the specified interval has elapsed.
var push = new ParsePush();
push.ExpirationInterval = TimeSpan.FromDays(7);
push.Alert = "Season tickets on sale until next week!";
await push.SendAsync();
If you build a cross platform app, it is possible you may only want to target one operating system. There are two methods provided to filter which of these devices are targeted. Note that all platforms are targeted by default.
The following example would send a different notification to Android, iOS, and Windows users.
// Notification for Android users
var androidPush = new ParsePush();
androidPush.Alert = "Your suitcase has been filled with tiny robots!";
androidPush.Query = from installation in ParseInstallation.Query
where installation.Channels.Contains("suitcaseOwners")
where installation.DeviceType == "android"
select installation;
await androidPush.SendAsync();
// Notification for iOS users
var iosPush = new ParsePush();
iosPush.Alert = "Your suitcase has been filled with tiny apples!";
iosPush.Query = from installation in ParseInstallation.Query
where installation.Channels.Contains("suitcaseOwners")
where installation.DeviceType == "ios"
select installation;
await iosPush.SendAsync();
// Notification for Windows 8 users
var winPush = new ParsePush();
winPush.Alert = "Your suitcase has been filled with tiny glass!";
winPush.Query = from installation in ParseInstallation.Query
where installation.Channels.Contains("suitcaseOwners")
where installation.DeviceType == "winrt"
select installation;
await winPush.SendAsync();
// Notification for Windows Phone 8 users
var wpPush = new ParsePush();
wpPush.Alert = "Your suitcase is very hip; very metro.";
wpPush.Query = from installation in ParseInstallation.Query
where installation.Channels.Contains("suitcaseOwners")
where installation.DeviceType == "winphone"
select installation;
await wpPush.SendAsync();
Sending scheduled push notifications is not currently supported by the .NET SDK. Take a look at the REST API, JavaScript SDK or the Parse.com push console.
If your app is running while a push notification is received, the ParsePush.ParsePushNotificationReceived
event is fired. You can register for this event. This event provides ParsePushNotificationEventArgs
. When Parse sends a toast notification, it embeds the JSON payload in the notification.
ParsePush.ParsePushNotificationReceived += (sender, args) => {
var payload = args.Payload;
object objectId;
if (payload.TryGetValue("objectId", out objectId)) {
DisplayRichMessageWithObjectId(objectId as string);
}
};
In Xamarin iOS, you need to call ParsePush.HandlePush
inside AppDelegate.ReceivedRemoteNotification
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) {
base.ReceivedRemoteNotification(application, userInfo);
// We need this to fire userInfo into ParsePushNotificationReceived.
ParsePush.HandlePush(userInfo);
}
In Windows 8, you may also receive the JSON payload from the LaunchActivatedEventArgs
passed to your application's OnLaunched
event.
protected override void OnLaunched(LaunchActivatedEventArgs args) {
var json = ParsePush.PushJson(args);
object objectId;
if (json.TryGetValue("objectId", out objectId)) {
DisplayRichMessageWithObjectId(objectId as string);
}
};
In Windows Phone 8, this code would instead be in your page's OnNavigatedTo event:
public override void OnNavigatedTo(NavigationEventArgs args) {
var json = ParsePush.PushJson(args);
object objectId;
if (json.TryGetValue("objectId", out objectId)) {
DisplayRichMessageWithObjectId(objectId as string);
}
}
To track your users' engagement over time and the effect of push notifications, we provide some hooks in the ParseAnalytics
class. In the example above, add the following to your Launching event handler to collect information about when your application was opened, and what triggered it.
ParseAnalytics.TrackAppOpenedAsync(launchArgs);
To track push opens, you should always pass your event handler's input args to TrackAppOpenedAsync
. A null or empty parameter to TrackAppOpenedAsync
will track only a standard app-opened event, not the push-opened event. If you don't track the push-opened event, you will not be able to use advanced analytics features such as push-open graphs and A/B testing.
Please be sure to set up your application to save the Installation object Push open tracking only works when your application's devices are associated with saved Installation
objects.
You can view the open rate for a specific push notification on your Parse.com push console. You can also view your application's overall app open and push open graphs on the Parse analytics console. Our push open analytics graphs are rendered in real time, so you can easily verify that your application is sending the correct analytics events before your next release.
On Windows 8, a toast notification can pass a small payload to the launch handler. We take advantage of this to pass a small Parse payload to the app, in order to correlate an app launch with a particular push.
// Override Application.OnLaunched
virtual void OnLaunched(LaunchActivatedEventArgs args) {
// 'args' contains arguments that are passed to the app
// during its launch activation from a Toast.
// More on Toasts: http://msdn.microsoft.com/en-us/library/windows/apps/hh779727.aspx
ParseAnalytics.TrackAppOpenedAsync(args);
}
You can also track application launches from toast notifications in Windows Phone 8. To track application launches from toasts and tiles, add the following to your App constructor:
this.Startup += (sender, args) => {
ParseAnalytics.TrackAppOpens(RootFrame);
};
This method will set up event handlers necessary to track all app launches; you should not use TrackAppOpenedAsync
if you register event handlers with TrackAppOpens
.
This feature is not supported yet in Xamarin Applications.
You can A/B test your push notifications to figure out the best way to keep your users engaged. With A/B testing, you can simultaneously send two versions of your push notification to different devices, and use each version's push open rates to figure out which one is better. You can test by either message or send time.
Our web push console guides you through every step of setting up an A/B test.
For each push campaign sent through the Parse web push console, you can allocate a subset of your devices to be in the experiment's test audience, which Parse will automatically split into two equally-sized experiment groups. For each experiment group, you can specify a different push message. The remaining devices will be saved so that you can send the winning message to them later. Parse will randomly assign devices to each group to minimize the chance for a test to affect another test's results (although we still don't recommend running multiple A/B tests over the same devices on the same day).

After you send the push, you can come back to the push console to see in real time which version resulted in more push opens, along with other metrics such as statistical confidence interval. It's normal for the number of recipients in each group to be slightly different because some devices that we had originally allocated to that experiment group may have uninstalled the app. It's also possible for the random group assignment to be slightly uneven when the test audience size is small. Since we calculate open rate separately for each group based on recipient count, this should not significantly affect your experiment results.

If you are happy with the way one message performed, you can send that to the rest of your app's devices (i.e. the “Launch Group”). This step only applies to A/B tests where you vary the message.

Push experiments are supported on all recent Parse SDKs (iOS v1.2.13+, Android v1.4.0+, .NET v1.2.7+). Before running experiments, you must instrument your app with push open tracking.
Parse provides guidance on how to run experiments to achieve statistically significant results.
When you setup a push message experiment, we'll recommend the minimum size of your test audience. These recommendations are generated through simulations based on your app's historical push open rates. For big push campaigns (e.g. 100k+ devices), this recommendation is usually small subset of your devices. For smaller campaigns (e.g. < 5k devices), this recommendation is usually all devices. Using all devices for your test audience will not leave any remaining devices for the launch group, but you can still gain valuable insight into what type of messaging works better so you can implement similar messaging in your next push campaign.
After you send your pushes to experiment groups, we'll also provide a statistical confidence interval when your experiment has collected enough data to have statistically significant results. This confidence interval is in absolute percentage points of push open rate (e.g. if the open rates for groups A and B are 3% and 5%, then the difference is reported as 2 percentage points). This confidence interval is a measure of how much difference you would expect to see between the two groups if you repeat the same experiment many times.
Just after a push send, when only a small number of users have opened their push notifications, the open rate difference you see between groups A and B could be due to random chance, so it might not be reproducible if you run the same experiment again. After your experiment collects more data over time, we become increasingly confident that the observed difference is a true difference. As this happens, the confidence interval will become narrower, allowing us to more accurately estimate the true difference between groups A and B. Therefore, we recommend that you wait until there is enough data to generate a statistical confidence interval before deciding which group's push is better.
Localizing your app's content is a proven way to drive greater engagement. We've made it easy to localize your push messages with Push Localization. The latest version of the Parse .NET SDK will detect and store the user's language in the installation object, and via the web push console you’ll be able to send localized push messages to your users in a single broadcast.
To take advantage of Push Localization you will need to make sure you've published your app with the Parse .NET SDK version 1.5.5 or greater. Any users of your application running the Parse .NET SDK version 1.5.5 or greater will then be targetable by Push Localization via the web push console.
It's important to note that for developers who have users running apps with versions of the Parse .NET SDK earlier than 1.5.5 that targeting information for Localized Push will not be available and these users will receive the default message from the push console.
Our web push console guides you through every step of setting up a Localized Push.
Setting up Push Notifications is often a source of frustration for developers. The process is complicated and invites problems to happen along the way. If you run into issues, try some of these troubleshooting tips.
- Make sure you are using the correct Package SID and client secret, as shown in Step 3 of the Windows 8 Push Quickstart.
- Clean and build your project.
- Check the number of recipients in your Parse Push Console. Does it match the expected number of recipients? Your push might be targeted incorrectly.
- Open your project's
package.appxmanifest
file and make sure "Toast Capable" is set to "yes."* If your app has been released for a while, it's possible for the recipient estimate on the push composer page to be higher than the pushes sent value on the push results page. The push composer estimate is generated via running your push segment query over your app's installation table. We do not automatically delete installation objects when the users uninstall your app. When we try to send a push, we detect uninstalled installations and do not include them in the pushes sent value on the results page. - If you're receiving push from Unity iOS, refer to iOS Push Troubleshooting Guide.
- If you're receiving push from Unity Android, refer to Android Push Troubleshooting Guide.