How We Supercharged Chat

The nuts and bolts of the framework that allows other Gojek products to leverage our chat platform via extensions.

How We Supercharged Chat

By Benzi Ahmed

The Gojek consumer app comes with a chat feature. This allows users to have conversations with:

  • The currently assigned driver partner in relation to a booking.
  • Other Gojek users, provided they are known contacts in your address book. These can be either personal or group chats.

In order to use the chat platform as springboard to other services within Gojek’s vast ecosystem, we wanted to expose some features that integrate with our other offerings — within the convenience of a chat window.

One of the first service options we wanted to focus on was payments — paying and requesting for money between individuals and groups. Chat had the platform to create connections between people, GoPay had payments — it was time to marry the two.

Architecture

To start with, as a chat platform team, we did not really know anything about the payments domain. In fact, most of the integrations we planned for required collaborating with other product teams within Gojek.

We decided early on that we needed a plugin-based framework that other product teams (and even chat team’s core services) could use. We also decided that the API surface area for this new framework should have as much as possible in common between the Android and iOS implementations.

The first use case we focused on was integrating payment options within chat — which would help us kickstart our design and feature rollout.

Approach

In the vein of keeping things as simple as possible, we came up with the following set of guidelines:

  • The chat subsystem can expose add-on features to the user
  • These features will not be part of the core chat offering, but can be plugged-in externally
  • These plugin-based entities — chat extensions — can have mainly two capabilities
  • Display a button (widget) in a chat window to trigger the chat extension’s functionality
  • Display chat extension messages that can support rich text, images, call-to-actions

Chat extension messages are merely text messages with additional metadata. While plain text-based messages are rendered by the core chat rendering system, chat extension messages need to be rendered by the chat extension that created the message.

Chat Extension Framework — Key Actors

The illustration above depicts the final framework components we came up with.

  • Chat Extension Providers are responsible for vending Chat Extensions based on the active Chat Session (there might be cases where we want to enable a certain feature only for certain types of chats e.g. those between our drivers and customers).
  • Chat Extensions are the components responsible for vending trigger points (Widget Views) and custom message views (Extension Message Views).

While the core subsystem takes care of managing life cycles of the chat extensions, widgets, and message views, it is the responsibility of extension authors to purely focus on the implementation details of their feature.

With the above design in place, we were ready to start collaborating and start implementing features.

Let’s take a look at some integrations we were able to build collaboratively.

Sample Integrations

Payments

The first integration we did was Request and Pay flows. Utilising GoPay, customers can make payments and request for money from friends.

Here’s the Request Flow in action, within a personal chat:

Request Money from an Individual

In a group chat, Request Flow translates to a Split Bill flow:

Request Money in a Group

Here’s the Pay flow in action:

Pay via GoPay, continue conversation in Chat

In the Pay Flow, we start with making a payment from the home-screen of the Gojek App. Once a payment is done, you have an option to continue to chat with the person you made the payment to. This flow is of course in addition to similar flows for Request where you can trigger a payment within chat itself.

The payments team were able to create a UX flow that could be triggered either from the home screen or the chat window.

Restaurant Sharing

Next up, our GoFood team wanted to explore sharing restaurant information via chat. Since we already had support for extensions at this point in time, we created a generic Share Via Chat flow that supports sharing simple text messages or custom extension message content.

In the Pay Flow, we start with making a payment from the home-screen of the Gojek App. Once a payment is done, you have an option to continue to chat with the person you made the payment to. This flow is of course in addition to similar flows for Request where you can trigger a payment within chat itself.

The payments team were able to create a UX flow that could be triggered either from the home screen or the chat window.

Restaurant Sharing

Next up, our GoFood team wanted to explore sharing restaurant information via chat. Since we already had support for extensions at this point in time, we created a generic Share Via Chat flow that supports sharing simple text messages or custom extension message content.

Share Restaurant Details via Chat

What’s interesting is that once a Restaurant Card has been shared via chat, a recipient clicking on that card can proceed to make a food order, directly from the chat window itself. This is made possible by the fact that Extension Message Views can be fully interactive (e.g. detect user taps), and the chat window provides contextual navigation controls to them.

Image Sharing

Lastly, let us take a look at the most recent feature we rolled out to production — image sharing in our customer-driver chats.

Image Sharing via Chat

During the implementation of this feature, we recognised that image sharing would be better triggered from the chat window if there was a direct shortcut button (e.g. a camera icon) within the bottom text input area of the chat window.

This leads us to enhance our extension framework to allow Chat Extensions to provide Chat Extension Shortcuts as well. Our updated framework looks like below:

Lessons Learned

It has been a great journey so far exploring various kinds of integrations in a simple chat window. We have a lot more planned, but in the meanwhile, here are a few key things we learned along the way

  • When you are developing a platform, evangelising what your platform provides is key. This is equally relevant if you are a platform-product company, or a platform team within a company. We conducted an internal chat extension hackathon which helped broaden our outreach, and saw some pretty cool ideas implemented including Live Location Sharing, Booking Sharing, Games, Sticker Packs etc.
  • Document your public API! Teams are more willing to collaborate if you have proper, up-to-date documentation in place. We created detailed technical documents, integration guides, and even provided a sample chat extension (a starter-pack, if you will) — these greatly helped teams adopting these new features. Also, the feedback we got during the internal hackathon fed directly back into improving our documentation.
  • Having a common design language helped our Android and iOS engineers to collaborate more closely. It was easier for the team to work on implementing the feature by focussing on the common characteristics during tech discussion, design ratification sessions etc. and leaving the nuances of each platform to respective teams during development. Having a common language that engineers can speak (irrespective of their specialisations) improves cross-communications and collaboration.
  • It is important to design solutions exercising self-imposed constraints. These constraints should directly limit the engineering scope of the solution. As engineers, we are all too comfortable going down the technical analysis rabbit-hole in our pursuit of coming up with a well rounded, albeit (possibly) over-engineered solution. This usually ends up in complicated designs, which translate into complicated code. It is better to design simpler systems and iteratively add smaller features, where each iteration cycle should also incorporate refactoring every step of the way. Even though we knew having something like Extension Shortcuts was nice to have from the get go, we had to exercise restraint and only implemented the feature when it was actually required.
  • We cannot stress this enough, but continuous refactoring (whenever required) is one surefire way to reduce the build-up of tech debt in any codebase. Improve a function here, rename a variable there, refactor a class into two — every little bit helps. It is the responsibility of the entire team to be engaged in this exercise.

So there you have it, a quick look at the way the core chat team developed a base extension framework that is currently being used to build richer integrations into chat.


Want more where that come from? Have our updates delivered straight to your inbox by signing up for our newsletter!