Creating EveryMundo’s latest feature in airTRFX Control Platform wasn’t easy. It required a lot of strategic planning, research, coding iterations, and time. As a developer, building a successful product feature with high visibility can be nerve-wracking– So how did the airTRFX Maximization Score come to life?


1. The Planning Phase

What is the airTRFX Maximization Score? As indicated in its name, the Maximization Score provides users a score ranging from 0-100%. This overall score indicator provides an estimate to users on how well their accounts are performing. Users receive recommendations on ways to improve their accounts in order to get the most out of their airTRFX Products. Users can raise their overall score by completing recommended tasks that pair with an uplift score. These recommendation cards are specific to the user and can be freely dismissed by the user if they are not relevant.

What is the purpose of creating the Maximization Score, and how will success be measured for this feature? are questions that arose during the planning phase. This phase required the most research and analysis to identify if this feature is viable. For example, to determine how well the Maximization Score is performing, we consider the following KPIs:

  1. Amount of recommendations applied per user
  2. Amount of recommendations archived per user
  3. Amount of product upgrade requests
  4. Amount of non-applicable product upgrades

At its core, the Maximization Score provides users with an overview of their accounts and optimization strategies to generate the most value out of their airTRFX products.


2. The Development Phase

Once the technical requirements were listed in the planning phase, it was time to begin development. The Maximization Score is structured to release in multiple development phases, the initial development phase, the recommendation cards, and the progress bar.

The following tech stacks were used to implement the following components: AngularJS (now Angular 9), Node.js, JavaScript, MongoDB, and AWS serverless.

Let’s take a look at a recommendation card. We can see that the card consists of a title, a description, an impact category (conversion rate), a score uplift, and a link. We also know that there will be different recommendations and may differ per user.

Here is where we determine where we want our data to reside. Due to its ease of use, scalability, and flexibility, we chose MongoDB over a traditional RDBMS. Since each card consists of multiple parts, we create an initial schema consisting of the following fields:

The aforementioned schema serves as an example for Air Canada with fields that pertain to the previously shown recommendation card.

Now that the schema is defined, how do we determine when a card should be recommended?


2.1 Implementation

Since the Maximization Score will reside in Everymundo’s airTRFX Control platform, we will need to create a service that can be readily integrated within that platform– this is where Serverless Computing comes into play. In our case, we will use AWS Lambda to provision our code. This reduces latency, avoids server management, and is inheritably scalable.

To determine how and when a card should be recommended, we gather data from different sources such as Google Analytics. Using the example recommendation card above, we see that the trigger in the schema is defined as: “Triggered because there are less than 100 sessions from Display, Paid Search, Email and/or Social to airTRFX template and/or custom pages in the last 30 days.”

This means that this card should only be recommended to the user if their session data in Google Analytics are less than 100. In order to query these results, we will need to create a function that uses the Google Analytics API within our serverless project.

After the Google Analytics API requirements are added to the project, we will need to query the API to gather the results for the trigger:

This function takes in an airlineId, defined as IATA code in our MongoDB schema, and ids, which are the Google Analytics account ids. In filters, the criteria for the trigger is defined by– we want to see less than 100 sessions from Display, Paid Search, Email, or Social Channels.

Referring back to MongoDB schema, there is a field called triggered. This field is a boolean value toggled by query results– meaning if data is received from the Google Analytics query, this field will be set as true. Essentially, we want triggered: true only if our query results are not empty. To update our MongoDB document accordingly, we call a function that will update this field in line 15; updateCollections().

update collections

The data flow is now: define MongoDB schema → create serverless project → import necessary packages/APIs → create query function.

Finally, we create a handler that is used to export our queries to our AWS Lambda. In the handler, we will call the query function and send the response to AWS. As an example:

Once the handler is exported and defined in the serverless.yml file, it can deploy to the AWS Lambda service. If the deployment is successful, functions can be found under the functions tab in AWS Lambda.

Since this lambda is used in the airTRFX CMS, we created endpoints for our lambda functions. To have the data appear on the frontend, we want to view the resulting MongoDB document per user. Thus, we define a GET request in the serverless.yml. AWS Lambda generates an API URL endpoint that can be used in our frontend application.


2.2 airTRFX CMS

After importing the endpoints within the airTRFX CMS, we can now use them throughout our application. To create the base for the card component we used HTML/CSS and a component.js file. As mentioned above, we saw that the card component consisted of multiple parts. Using Angular templating concepts, we can use our endpoint data by creating bindings and interpolating those values within our HTML. Since there are multiple cards, we can loop over our endpoint data using ng-repeat or *ngFor (in Angular) for every index. In our component file, we define an OnInit method to populate our page with endpoint data upon initialization. This will help us avoid writing duplicate code and slow page loads. To ensure that our feature loads only once we receive the endpoint data, we can make use of resolvers in Angular. Resolvers are defined in the feature’s state config files.

The base of the Maximization Score feature is now complete.


3. Release

Once the planning and development phase is completed it is time to launch the Maximization Score. There were multiple iterations during the development phase, which is common when creating features from scratch. In this phase, all of the items necessary to support the feature have been implemented. The user interface is designed, and the feature is built and tested. The Maximization Score Beta was released to the public on May 5th. Customer feedback is important in this phase, as this feature requires ongoing development to further improve the state of the Maximization Score