Customer.io and the Super Awesome Store


‘Push’-ing the limits of inter-disciplinary collaboration

“Should designers code?”

No.

but successful designers do need to understand how code functions — its constraints, its quirks, its unique capabilities — in order to build experiences which enable users to easily get things done. Similarly, developers don’t need to know how to design, but the ability to adopt a user-centric designer’s mindset makes collaboration far easier.

Code impacts design, and vice versa — being able to work at the edges of our discipline enables innovation; a sweet spot where we each know just enough not to waste anyone’s time, but not so much so as to avoid pushing each other.

Our push notification preview, and the result!

At Customer.io, we recently tested this idea. In a nutshell, our app allows our customers to create automated messaging experiences, and we recently added the ability to send push notifications as part of those experiences.

For me as a designer, this was a new kind of technical challenges. I needed to understand how a push notification worksfrom all its different sides, human and otherwise (sender, recipient, device, platform), in order to even begin addressing the seemingly-simple user goal: “I want to send a relevant push notification through Customer.io to my end-users.”

To build this successfully, our team had to untangle design and code and step into each other’s shoes in a way that is far more taxing than normal. But we did it. We built a beta feature that we’re proud to roll out. We learned how difficult but rewarding this process can be, and how we want to improve on it in the future. So here are some of those challenges, and some of the learnings.

The challenges & the design problems

I just said that designers should know just enough about code to understand how to solve problems. But in the case of Push, there was no just enough. Massive UI ramifications hung on the smallest of technical details. How we structured the code would affect the interface, and how we wanted to build the interface would impact the structure of code — where do you even start?

How does that push notification actually work?

Simple…right?

Of course, everything in software is more complicated than it seems. But while we all know what a push notification looks like, this particular iceberg was…surprisingly large, and got larger when Customer.io was added.

Basically, to send a push notification:

  1. I (the end-user) must install the app and consent to notifications.
  2. The company sending it needs to be authorized by Apple to even attempt do so.
  3. The push is composed and sent via a request to Apple to send the notification. This request has the notification’s intended recipient, the content, and authorization from step 2.
  4. If that authorization checks out, it sends.

To allow people to do this in Customer.io, we’d have to add layers:

  1. I (the end-user) must install the app and consent to notifications.
  2. The company sending it needs to be authorized by Apple to even attempt do so.
  3. The company has to verify the authorization with Customer.io
  4. The push is composed in Customer.io
  5. Customer.io then sends the request to Apple to send the notification. This request has the notification’s intended recipient, the content, and the authorization from step 2.
  6. If that authorization checks out, it sends.
  7. Customer.io finds out of the push notification reaches the device, receives tracking data back. We display this data to our customer.

So we add layers, but don’t want to add complexity. We needed to enable a customer to write a push notification, but also to facilitate authentication, managing devices (omg, what if a customer has the app installed on multiple devices?!), and viewing tracking information.

Getting set up

Did I mention that this changes between platforms? We needed to enable people to connect both their iOS and Android app with Customer.io, compose a notification that displays well on both of them, and display delivery and interaction analytics appropriately.

And how would we handle the above authorization? This is what we ended up with for the beta version:

Push configuration in Customer.io

To do this, I needed to understand, among other things:

  • Which credentials were required (and why) for each platform.
  • Potential errors when trying to authenticate, why, and how to fix them.
  • Customer.io accounts can have multiple users: who should be able to see and manipulate these credentials?

…and so on.

Phew, you’re finally ready! Let’s send some push notifications!

On to the next challenge: where are we actually sending this thing? When you install an app on a device, it gets a token. For example, I have the ESPN app on my phone and iPad; both devices have a token which identifies that particular app instance.

This is new territory for Customer.io. An email, for example, will send to one address. An SMS message will send to one phone number. Push notifications are different. After all, if we want to help our users send relevant, timely messages, this means sending a push to the right device in a world where most people have more than one.

The challenge was how we store these tokens to enable our users to see and utilise them. To answer this, we had to consider many aspects of the customer (and end-user) experience.

  • How is it easiest for our customers to send theirusers’ device data into Customer.io?
  • How do we want to display this data? Does it fit with the mental model that customers have of it — is it easy for them to act on, and build messages with?
  • How can we store it? How should we store it? What standards do we want to set?

Preview….what, exactly?

Whenever someone composes an email in Customer.io, we show how that email will look — especially useful when there are lots of data variables. We wanted to do the same for push notifications. But once I started thinking about the end-user, this got complicated real quick:

  • Is the device in portrait or landscape mode?
  • Is the push an alert, banner, in the notification center? Do we even know?
  • Does it contain an image? Or personalization data?

…oh, and what platform is this going to?

After a lot of back-and-forth and trying various middle-grounds, we decided on a very generic preview:

In the future, we want to build something more dynamic that allows the user to select different orientations and devices, and get an accurate preview.

Message successfully sen — wait, what?

When our users send emails Customer.io displays all sorts of delivery data: received, opened, clicked, converted, etc. We wanted to do something similar for push notifications in our UI, while making sure the displayed metrics were meaningful.

To understand the potential complexities here, consider the following feedback given after a new UX iteration, by our Director of Product:

Brian making things Difficult, how rude

Here, the concept of “a delivery” and “delivered” and “sent” can be endlessly confusing. Because one push can be sent to multiple devices, a single push “delivery” can contain multiple instances of the same message.

For now, all we show is if that message sent or failed, no matter the device. This is based on the assumption that our customers care that they reached their end user successfully, no matter the device. In the future, we want to show a more comprehensive history of any delivery — which devices we tried to send it to, when, and what the result was.

Important collaboration learnings

At the beginning of this project, I didn’t even know what I didn’t know about Push. The initial discovery steps are often the most difficult but also where open, honest inter-disciplinary collaboration is most important — a far more interesting comment on the “should [design/engineering] [code/design]” debate. Here’s how we tackled that:

Proactively using our specialties to promote understanding

The title of this post is the “Super Awesome Store” — the name of the iOS and Android app that our back-end engineer, Jatin, created from scratch for us. He became our customer and literally created an entire app to help facilitate design, testing, and validation.

Remember the “How push notifications work” above? Our front-end engineer, Kevin, took the time to write a massive Basecamp post outlining it in plain language, with linked documentation for us to dig into once we understood the basics.

Finally, if Kevin hit UX issues during front-end implementation, we would jump on a screenshare ASAP to work out the details, or I would make a wireframe prototype for us to hash through, to make sure we got the nuance right.

Engineering involvement in interviews

Product drove customer interviews, but Kevin and/or Jatin were always present. This way, they could understand customer goals without losing anything in translation. I wrote open-ended questions to facilitate discussion and description of those goals, but left room for technical follow-up questions.

Visualize to understand, wireframes as questions

Despite customer interviews and competitive research, there’s always an element of the unknown. I started sketching and making wireframes early, with the anticipation that most would be thrown away. Each of these was not a recommendation, but a question of its own. Until I built the vocabulary to vocalize the questions, I used low-fidelity iteration to ask them.

These were constantly shared with Kevin, Jatin, and Brian: “Does this look feasible? What have I missed? Can we do [insert insane idea here]?” The resulting discussions helped me question assumptions and gain domain knowledge, rooted in a familiar visual format.

Words are important

This point has been belaboured, but it’s worth repeating. Words like “delivered” can mean or imply different things to a designer, developer, and customer. This is why the question “what does delivered mean?” isn’t a stupid one, and even the most basic words need to be redefined and documented.

No question is stupid

Never assume that everyone “Gets It”. I felt free to create those first wireframes because I knew that my competence wasn’t judged on them — I was building knowledge in an unfamiliar domain, using a familiar method. Treating discussions and documentation in this way ensures that all questions (no matter how fundamental) get asked and addressed.


Overall, the most interesting takeaways for me weren’t about push notifications at all, but about how we built that understanding, together. Jatin and Kevin stepped out of their day-to-day and into the shoes of our users, and I did the same for engineering.

I still have no idea how to code any of this. But this isn’t what “should designers code/should developers design” means. It’s not about doing, but understanding the goals of the disciplines, and building vocabularies that facilitate collaboration on the feature we’re building. I had to learn to talk about push like an engineer, and Kevin and Jatin did so like our customer. That meant that we built something we’re proud of and know how to improve upon, tomorrow and months down the line.

Also, I’m not at all sorry about the pun in the title.

Join our mailing list for updates on our content and more!