Migrating from Parse Push Notifications

Several months ago Parse took everyone by surprise and informed developers that they would shut down all of their services by the end of January 2017. While the news initially seemed like an April Fool’s joke similar to their public announcement of Parse Pigeon, we disregarded the migration message that appeared in on the screen every time you logged into your Parse Dashboard:

The Parse hosted service will be retired on January 28, 2017. If you are planning to migrate an app, you need to begin work as soon as possible.

However after countless logins into the Parse Dashboard the message kept appearing in the topmost banner, almost as if laughing at us, and gradually we began coming to terms with the harsh reality – Parse was indeed shutting down and we were (again) forced to migrate our apps to a different Push Notifications provider. This is not new to us – we’ve been dealing with these kinds of migrations since early 2015 when we migrated one of our apps from Urban Airship to Parse.

Back then we had a single Android app that used Urban Airship to receive push notifications from a web application written in Rails. The notifications workflow was simple – the app user would receive a push notification every time an order was placed by a customer through the YouOrderIt platform. The Android app was intended for an administrative audience such as restaurant managers and admin staff and the push notifications simply contained basic order details. We built the app in October 2014 and selected Urban Airship as the push platform of choice because it was free and because we refused to evaluate other options – Urban seemed like a tried and tested choice so we picked it.

And then sometime in January 2015 Urban Airship began charging monthly fees for their services. We had been all along in the beggar’s free tier, which they couldn’t support anymore (I don’t think any provider truly achieves high margins in this push notifications business) so we got an email from Urban Airship Support to the effect that we had to pay a $200 monthly fee going forward. We didn’t have that kind of money to spare so we had to switch to something else (free) immediately.

A friend recommended Parse so we started looking into it. The platform seemed solid, very well documented and their Dashboard was more user friendly than Urban Airship’s. They also had a beggar’s free tier throttled up to 30 requests per second (RPS) and we were confident we would fall beneath that threshold since our apps were not experiencing load above 30 RPS. We migrated the Android app to Parse and experienced good push notifications performance and decent reliability. After this experience we decided to use Parse for our complete app portfolio.

So a couple of months ago while mourning Parse’s looming demise we were faced with a tough question: migrate to what? We were back again to the drawing board just like in the pre-Urban Airship days. For a complete month we deliberated the idea of implementing our own platform based on Amazon SNS, and we even studied technical guides on how to migrate from Parse to Amazon SNS (gruesome process), but we didn’t wish to become a push notifications technology provider. That would have further derailed us from our core focus.

We realized that no matter what we wouldn’t be able to come up with a flawed assessment that identified a perfect, always-free and long-lived push notifications platform. The #1 push notifications platform today might be dead one year from now (even if it’s backed by Amazon, Google or even Facebook – ironically, before announcing their shut-down Parse had been engulfed by Facebook), and that’s just a fact of the brutality of technology. Even if it doesn’t die the platform’s creator might wake up annoyed one day and decide to start charging monthly fees, giving you only two viable options – pay or get the hell out and migrate.

Given the fast-changing technology landscape we are constantly subjected to, we have to be willing to switch platforms ever year if possible and be prepared for the changes entailed with these migrations. We decided to switch to the next best FREE choice that catered to our requirements. So when another colleague recommended OneSignal, we checked it out and after noticing it was free and had a decent breadth of features, we decided to migrate to that.

Android Setup

From an Android standpoint migrating to OneSignal only entails a couple of code changes. Besides the OneSignal SDK setup, generation of a Google Server API Key and Gradle changes mentioned in the OneSignal documentation, you just need to add the following initialization method. Make sure this is called in your main Application’s onCreate() method:

void initOneSignal() {
    OneSignal.startInit(this).
              setNotificationOpenedHandler(notificationsHandler).
              setNotificationReceivedHandler(notificationsHandler).
              init();
}

In this example we are using a custom notifications handler but this is optional. For instance if your app only needs to display the push notification using the built-in behavior a custom notifications handler is not required. However if you need your app to perform custom logic every time a notification is received or opened, we recommend using a notifications handler:

public static PushNotificationsHandler notificationsHandler;

If you decide to use a custom notifications handler make sure you override the notificationReceived() and notificationOpened() methods depending on your notification handling requirements.

public class PushNotificationsHandler implements OneSignal.NotificationOpenedHandler, OneSignal.NotificationReceivedHandler {

    public PushNotificationsHandler() {
        super();
    }

    @Override
    public void notificationReceived(OSNotification notification) {
        // Handle notification received event here
    }

    @Override
    public void notificationOpened(OSNotificationOpenResult result) {
        // Handle notification opened event here
    }

}

That’s all for the basic code changes. However these code changes might not be enough to fully migrate your app and platform to the new notifications service. Consider the following situation – you make your code changes in your Android app to migrate from Parse to OneSignal and push the changes to Google Play Developer Console. If you already have users using a previous version of your app (the codebase of the previous version uses Parse or some other platform), they might opt to NOT update the app (which contains the new OneSignal code changes) for a while. You will be faced with a situation where different users are running different versions of your app – one Parse enabled and the other OneSignal enabled, and you have to support them both for business continuity’s sake.

As part of your business, if you are sending notifications to apps directly from the Admin Dashboard, this is simple since you can manually target these two audiences separately. However if you have a complex platform where notifications are sent from a web application that sends notifications to devices using the OneSignal API, you need to write logic to handle these 2 separate paths – the path to send notifications to devices using Parse and the other path where you send notifications via OneSignal. However this code will be temporary, once all of your users update their apps to the newest version using OneSignal, you just need to handle the OneSignal path.

We faced this situation with one of our apps. We have an e-commerce app that can be used to place orders. It is currently used by thousands of customers and was originally Parse-enabled. With the Parse implementation, when users placed orders the Android app would send order details to our platform’s RESTful JSON API, including the Parse device token of the user’s device placing the order. This info would be saved in a database server-side for later use. If an order was confirmed, the web app would read the order details (including the device token), and send a push notification to that specific device token using the Parse API. This was the Parse path. To handle OneSignal we made one small code change in the Android app – the app would send the device’s OneSignal userId instead (also known as playerId) to our platform’s API when sending order details. Retrieving the userId is simple, but you have to make sure you retrieve it after OneSignal successfully initializes. Also the implementation is asynchronous so your Android app needs to handle this non-blocking behavior gracefully:

// Call this inside your Android app if you need to retrieve the device's userId for later use

OneSignal.idsAvailable(new OneSignal.IdsAvailableHandler() {
    @Override
    public void idsAvailable(String userId, String registrationId) {
        if (userId != null) {
            // Save userId or registrationId
        }
    }
});

When we introduced OneSignal we had to create a separate path server-side to handle the OneSignal-enabled apps. The server-side pseudocode to handle both paths ran something like this:

// The code below runs when the server needs to send a push notification to a device

Order order = getOrderById(orderId);

// Parse path
if (order.hasParseDeviceToken()) {
    String deviceToken = order.getDeviceToken();
    Notifications.sendPushUsingParse(deviceToken);
}
// OneSignal path
else if (order.hasOneSignalUserId()) {
    String userId = order.getUserId();
    Notifications.sendPushUsingOneSignal(userId);
}

Once all of your users update their Android apps to the latest version running OneSignal, you no longer need the first IF statement in the server-side code to handle the Parse path. You can remove it and your notifications platform will continue uninterrupted.

Track Squarespace form submissions with Google Tag Manager

I use Squarespace to build fast and beautiful marketing sites to attract customers to any product or service. Usually, these marketing sites include a contact form which you can use to track leads.

Squarespace offers poor documentation on how to track these form submissions with Google Tag Manager. I’ll explain how to do it assuming you already have an account with Squarespace, Google Adwords, Google Analytics and Google Tag Manager.

First, copy your Google Tag Manager code into Squarespace:

  1. Login into your Squarespace account.
  2. Click on “Settings”.
  3. Click on “Advanced”.
  4. Click on “Code Injection”.
  5. Copy your Google Tag Manager code in the header section.

code_injection

Now, let’s copy the following the code in the footer section.

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
  
var formSubmitted = false;

$(document).ready(function(){
    $('input.button').click(function() {
        window.setInterval(checkFormSubmission, 100);
    });
});

function checkFormSubmission(){
  if(($(".form-submission-text").is(':visible')) && (formSubmitted == false)){
    dataLayer.push({'event': 'formSubmission'});
    formSubmitted = true;
  }
}  
  
</script>

This code checks if the form is submitted without any errors and fires an event called formSubmission. We need to create a trigger in Google Tag Manager that fires when the formSubmission event is fired. That’s how we’ll track when a form is submitted.

  1. Go to the Triggers menu on your Google Tag Manager account.
  2. Click on “New”
  3. Write a name for this trigger. It could be “Web Contact Form Submission”.
  4. Select the “Custom Event” event.
  5. On the event name field write “formSubmission”.
  6. Click on “Create Trigger”.

web_contact_form_submission_trigger

Track contact form submissions on Google Analytics

  1. Go to the Tags menu on your Google Tag Manager account.
  2. Click on New.
  3. Write a name for this tag.
  4. Select product “Google Analytics”.
  5. Choose tag type “Universal Analytics”.
  6. Write you Tracking ID on the given text field (this is id is given by Google Analytics). Select “Event” in the Track type list and then click on Continue.
  7. On the Fire On step click on “More” and select the trigger you just created from the list and click Save.
  8. Click on”Create Tag.

web_contact_form_submission_tag

That’s it. Preview your tag to see check that everything is working and publish your changes. You can now check for this form submission event in your Google Analytics account.

Track contact form submissions on Google Adwords

  1. Go to the Tags menu on your Google Tag Manager account.
  2. Click on New.
  3. Write a name for this tag.
  4. Select product “Google Adwords”.
  5. Select “Adwords Conversion Tracking”.
  6. Fill at least the Conversion ID and name fields (if you have not created any conversions, follow this link and learn how to do it https://support.bigcommerce.com/articles/Public/How-do-I-add-Google-Adwords-Conversion-Tracking) and then click on Continue.
  7. Write you Tracking ID on the given text field (this is id is given by Google Analytics). Select “Event” in the Track type list and then click on “Continue”.
  8. On the Fire On step click on “More” and select the trigger you just created from the list and click Save.
  9. Click on “Create Tag”.

adwords_conversion_tracking

That’s it. Preview your tags to check that everything is working and publish your changes. Feel free to ask any questions in the comments section.

Special thanks to:
http://www.silvabokis.com/squarespace-tips/tracking-squarespace-form-submissions-in-google-analytics-using-jquery

 

 

 

Setup Resque in Heroku to Manage Background Jobs for a Rails App

Ha! You thought we were just about games, didn’t you? The truth is that we spent lots of time working on web apps, much more than games. And a lot of times these web apps need to send an awful lot of bulk email to spam their users. So here it comes, Resque to the rescue, to aid on the process.

Configuring Resque in Heroku was a painful experience that you should avoid by reading the following instructions carefully. I’m going to be pretty specific and show the exact configuration that worked for me. I’m going to avoid the localhost configuration and only stick to how to do it on production. I’m also assuming you already have Sendgrid installed on your Heroku instance.

First things first, make sure you’re using Rails 4.2 or above and Ruby 2.2.0 or above.

Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later. As it needs Redis to work you should have the following in your Gemfile.

ruby '2.2.2'
gem 'rails', '4.2.3'
gem 'redis'
gem 'resque', "~> 1.22.0"

Why Resque 1.22.0? Because on the official Rails API it says that Active Job has adapters for Resque 1.x. This is key. Don’t use the latest version, it doesn’t work. Stick to what’s in the docs.

If you’re unfamiliar with Active Job, check out this Rails guide : http://edgeguides.rubyonrails.org/active_job_basics.html

Now, go to your application.rb file and add the following code:

# We're telling Rails that we will use Resque to process background jobs
config.active_job.queue_adapter = :resque

Next, set up Redis in your Heroku instance. I’m using rediscloud here. There are other services available, but as I told you, I’m sticking to what worked for me.

heroku addons:create rediscloud
heroku config:get REDISCLOUD_URL

Create a new redis.rb initializer in config/initializers/ and add the following code:

if ENV["REDISCLOUD_URL"]
  $redis = Redis.new(:url => ENV["REDISCLOUD_URL"])
end

Create a new resque.rb initializer in config/initializers/ and add the following code:

# Establish a connection between Resque and Redis
if Rails.env == "production"
  uri = URI.parse ENV["REDISCLOUD_URL"]
  Resque.redis = Redis.new host:uri.host, port:uri.port, password:uri.password
else
  # conf for your localhost
end

Go to your lib/tasks folder and create a new file called resque.rake and write the following code:

require 'resque/tasks'

task 'resque:setup' => :environment

Now you need to create a Procfile if you don’t have one. Just create a file called Procfile in your Rails app root folder. A Procfile is a mechanism for declaring what commands are run by your application’s dynos on the Heroku platform. Add this to your Procfile:

resque: env TERM_CHILD=1 RESQUE_TERM_TIMEOUT=7 QUEUE=* bundle exec rake resque:work

This process will run every time you push your code into production.

You’re almost set. Now Change your email deliver method from .deliver_now to .deliver_later and push your code to Heroku.

Finally, go into your app’s dashboard and make sure you see something like this:

skitch

So that’s it. Sending emails should be working as a background process. Hope this was helpful. Don’t forget to leave a comment below.