Building and scaling different travel websites with one codebase

White-labelling (Part 1): the secret tool that enables Agoda to build multiple travel websites for our partners

Thammarith
8 min readFeb 21, 2022

--

Did you know that Agoda uses its code to create websites for other online travel agencies as well? We do this by using a process called white-labelling. When Agoda decided to white-label our website, we faced numerous challenges like — maintaining differences between websites, creating environments for different development stages, and more.

I have been working as a full-stack engineer at Agoda for around two years working on several white label projects on the accommodation, YCS, and flight funnels. I take the opportunity to share my experience in this two-part series of Agoda's successful model of white-labelling. By the end of this blog, you will have a clear understanding of how white-label looks from the inside, how it works on the code level, application, and different environments. I will do this by taking real-life examples of Agoda’s challenges with white-label and how we tackled them. Feel free to adapt the techniques I share with your team and organization.

What is White-Labelling?

Not only does white-labelling exist in the software world, but the hardware world also has the approach as well. Some phones have surprisingly similar designs and specifications because they use the same model.

While shopping online, have you noticed that some products are surprisingly similar? The similarities might be in terms of features or looks and feel. One of the most straightforward examples is mobile phones. Remove the labels, and the products look the same! Some brands use the same model of devices from the same assembly line but customize the User Interface to fit their branding. This process is called white-labelling.

In the software world, white-labelling is common. It is born from the idea that you make a product once and help your partners build their products by sharing your existing code with them and adjusting your product’s characteristics such as features, themes, etc., to suit their needs. Agoda saw this as an opportunity and decided to make our website a white-label ready brand.

Now that we understand white labelling and its importance let me show you how we implement it.

Agoda's Architecture Simplified

The first step is understanding Agoda's architecture. When a user lands on agoda.com, the reverse proxy resolves and maps the URL to determine the downstream systems or services to direct the request. For example, if a user requests agoda.com from their mobile device, it determines that the phone web server responsible for downstream service should receive this request.

After the request has reached either the desktop or mobile webserver, the webserver takes the information from the request to build and render the client-side. The webservers also connect to the white label service, which we are going to look into the details later on, and other backend APIs.

A simplified diagram of Agoda's frontend architecture

Resolving a White Label from a URL

Our white labels (partner websites) use the same infrastructure and codebase as Agoda. How can our system figure out which white label it is when a user visits one of the white labels?

The reverse proxy spearheads the responsibility after the DNS points the website to one of our servers. When a user visits whitelabel42.com, the request hits the reverse proxy, and it checks WhiteLabelConfiguration which contains an array of the list of our websites. Once it finds the matching white label information from WhiteLabelConfiguration, it passes the white label ID and other information downstream to the webserver and other downstream APIs and services with a white label header.

The reverse proxy matches the request URL with the array that contains the list of our websites.

Managing Feature Configurations

Each white label has a set of features. The feature can be coupons, sign-up/log-in, or some regulatory requirements, such as the prices on the search page inclusive or exclusive of tax.

Agoda (top) doesn't have the prefecture map which is present on our Japanese partner's website (bottom). In contrast, the language and currency menus, which are on Agoda, are disabled on this partner's website.

The above images are white labels. Notice the Japanese partner's website has a map of Japan's prefectures, which people can use to search for accommodations in the user-selected region. However, on Agoda, we do not have that map. Another example would be on the top navigation bar. On Agoda, we have language (shown as the flag of Japan) and currency (shown as $) settings which our Japanese partner disabled.

There are two types of features, boolean and configurable. The Japan prefecture map is an example of a boolean feature. We can either turn it on or off. On the other hand, we can configure the list of supported currencies for a white label. Which makes currencies a configurable feature. When there is no configuration for this type of feature, it means that it is disabled.

The differences in the header for Agoda (top) and the Japanese counterpart (bottom). The language and currency options are not enabled on the Japanese partner's website.
Apart from boolean (on/off) features, we can also have configurable features as well. In this example, Agoda (top) offers over 30 languages but a white label (bottom) can limit supported languages as well.

On the scale at which we are growing, Agoda has around 300 of these features. Each of these features may contain sub-configurations. This brings the total possible configurations to over 500 compositions and are growing by the day! Our challenge is how can we manage the configurations?

Let's explore some of the options we have tried.

Hardcoding

The most straightforward way to check if a feature is enabled or not is hardcoding. Something like:

However, this is neither scalable nor maintainable. Imagine having 100+, let alone 10+ white labels to manage. There will be 100+ if-else statements, enums everywhere, and another 100+ bugs as a result. We need to do better.

White Label Service: the Single Source of Truth

To have synchronized configurations across the system, we wanted to have a single source of truth for services from which to read. It should be easy to toggle and control the setting values.

As a result, we created a core service called White Label Service. This service serves the feature configurations for each white label. Most services in Agoda connect to and read the configurations from White Label Service.

Let's say a user visits a partner's website that has the same features as Agoda's, except sign-up/log-in. After the reverse proxy has resolved the URL and known that it is white label 42, it passes the information to the webserver. The web server reads the configuration from White Label Service and instructs the client-side that this white-label does not have log-in/sign-up. The client-side takes the parameters given by the webserver, realizing that it should hide all log-in/sign-up related features and renders the components accordingly.

Below is an example of our white label configuration:

which compiles to

This approach works well initially but is challenging to scale for more than ten partners. The more partners we have, the more configurations we have to take care of. We cannot rely on it to be the single source of every truth because it is hard to maintain, and some features are only helpful for the front-end. For example, the backend system ignores the links on the menu bar or the footer on the website. So, we came up with "client-side Behaviour Management".

Behaviour Management: the Client side's Source of Truth

Apart from the issues mentioned earlier, we found some challenges with making White Label Service the single source of truth. For example, it takes time to add and deploy a feature; it is difficult to have robust testing for a feature, etc.

We solved these challenges by introducing Behaviour Management which concerns client-side logic alone. With Behaviour Management, we define a behaviour, e.g., visibility of a button, the links in the footer, etc., in the client-side code itself.

A behaviour can be defined using a combination of conditions such as White Label ID, experiment ID, origin, etc. For example, we can create the HideFooterLinksBehaviour by checking if the White Label ID equals Agoda or is on the B side of an A/B experiment.

Below are examples of the behaviour:

Behaviour Management is not limited to just React, we can expand to other client sides as well. Our webserver, which is the client-side of the White Label Service and written in C#, can use Behaviour Management too.

In fact, Behaviour Management is a concept that can be adopted in any language as long as the necessary information such as White Label ID, origin, etc. can be resolved.

An example of behaviour management in C#

Some benefits of Behaviour Management are that we can use a code analyser and do unit testing; behaviour names are more related to the code itself, which is easier to identify, and we can create nested behaviours.

Two is Better than One

There are some situations that we want to take the configuration from the White Label Service to build a client-side specific behaviour. For example, we want to see if a White Label has Flights enabled, we can use the Flights configuration from the White Label Service to be a condition in a behaviour.

With the combination of the White Label Service, hosting the configurations for multiple services, and Behaviour Management, hosting the configurations for a single service, we have created a maintainable, extensible, and configurable system to build websites for our partners.

The combination can be visualized in the following diagram:

visualization of data flow for white label information

What did we learn from our approach?

To look back, we have come a long way and learnt a lot from the earlier easy-to-implement but hard-to-scale system to more sustainable and scalable architecture. We will test our solutions against new and unexpected requirements that adapt to support unique needs. We are confident that our solution is scalable and extensible when those changes are required.

Next Part: Development & Testing Environments

Now that white-label features and configurations are manageable, how about identifying solutions for each environment for various development stages? Buckle up to explore the last step before the deployment!

Read it now: Managing and scaling different white label development and testing environments.

Special thanks to Vlad Batushkov, Brinda Krishnan and Patthaphol Kulthawaiporn for their support and guidance.

--

--

Thammarith

Senior Software Engineer at Agoda・Coding and having existential crisis simultaneously・thammarith.dev