Improved Vanity URL System

 | 

At the Front End team, we are constantly looking at ways to update page content with ease. A big part of that is vanity URL which is a redirecting mapping system that helps finding correct URLs. The vanity URL will be used for our marketing and communication team to spend their time wisely on A/B test experimentation.

This blog post takes a deeper look at the vanity url system improvement that creates greater flexibility into our way to update new key URLs.

Vanity URL Schema

config = {
  "join": {
    "share": "ccid=DBT&utm_medium=referral&utm_source=physician&utm_campaign=enr-referral&utm_term=und&utm_content=und",
    ...
}

“join” → subdomain

“share” → pathname

“ccid=DBT&utm_medium=referral&utm_source=physician&utm_campaign=enr-referral&utm_term=und&utm_content=und” → replacement for pathname “share” as query parameters

Example

Although there are some cases where registration code is not required, the valid vanity URL requires to include registration code in the URL pathname. See exception below.

The valid vanity URL will be https://join.livongo.com/LIV-ALL/share. Entering that valid vanity URL should redirect to https://welcome.livongo.com/LIV-ALL?ccid=DBT&utm_medium=referral&utm_source=physician&utm_campaign=enr-referral&utm_term=und&utm_content=und.

Exception

There are some different behaviors on these subdomains: sms, goto and nudges. These subdomains don’t need to include registration code. For example, https://goto.livongo.com/account or https://nudges.livongo.com/mealplans.

Legacy Vanity URL System

It is a long journey when attempting to update a new vanity URL. We need to go to server/config/redirect/vanityURL.js where you will find config key-pair value of vanity url mapping object. After that, we still need to go through the whole SDLC process until the new added keywords release to production.

At Livongo, we have three environments: PROD, PREPROD, and INT. PROD is where the website lives. PREPROD is the mirror of PROD serving as the last step to conduct testing before going to PROD. Lastly, INT is the testing and development environment. If we would follow SDLC, we would need to go INT to be tested, then going to PREPROD to be verified for the last time, and finally it landed on PROD. As we release bi-weekly, the process occurs once every 2 weeks. As a result, it takes 2 weeks for marketing and communication to be able to start their A/B test experimentation. Note that we are still following SDLC. In fact, this isn’t a code update; thus, we need to make the vanity URL system more flexible, adjustable, and adaptable to any urgent changes. 

Add New Vanity URL on Legacy Vanity URL System

To update, we will add a new key URL on the correct subdomain to the config key-pair value object. Not to mention that there are sometimes last minute vanity URL requests. In that case, we need to see if we can still manage to add them before code cut-off. In the worst case situation where things break, we need to request for hotfix.

Improved Vanity URL System

Instead of placing the config mapping URL in server/config/redirect/vanityURL.js, we mirror them to Livongo content server. That way, the config mapping URL will be retrieved from Livongo content sever instead of server/config/redirect/vanityURL.js. Since any updates on the vanity URL will take place on the Livongo content server, it gives us more flexibility to update the vanity URL at any moment. Once changes occur, they will not be available right away; instead, we can target specific development environments (PREPROD and INT) to test and approve these changes before we finally allow them to happen on PROD. We are not bound by the 2-weeks sprint anymore; instead we can test, ship, and iterate vanity URL updates faster.

We rely on Redis cache to preserve vanity URL. The important thing to keep in mind is that Redis cache sets to 7 days auto-refresh since its last refresh; therefore, we need to always make sure that current Redis cache does not stale anytime soon. We also have Redis cache refresh function available to force refresh before 7 days. In the worst scenario where things break, we can roll back the vanity URL and trigger Redis cache refresh function without having to request for hotfix. We also preserve a copy of vanity URL in server/config/redirect/vanityURL.js as a backup to the content server in case Redis is failing.

Access Vanity URL file on Livongo Content Server

To get a vanity URL file, We will need FileZilla to access the content server with credentials. Once logged in, go to /config where you will find vanityURL.json file.

Add New Vanity URL on Improved Vanity URL

  1. Make a copy of vanityURL.json to your Desktop.
  2. Open the file and add a new key URL on the correct subdomain to the config key-pair value object.
  3. Save file and replace the updated vanityURL.json file on the Livongo content server
  4. Depending on which environment (PROD, PREPROD, or INT) that the update wants to happen immediately, go to your browser and enter a valid vanity URL. Finally, make a function call to trigger Redis cache refresh on the targeted environment. Note: Redis cache will preserve current vanity URL up to 7 days as default config. After that, Redis cache auto-refresh will be triggered
  5. At this point, it should be able to access the new added vanity URL.

Congratulations! We just updated our vanity URL. Updating vanity URL will be reflected immediately after Redis cache refresh. In fact, any vanity URL request can be added outside code cut-off, test, and release on the specific environment.

Code

Whenever we want to access vanity URL, we check for any available vanity URL in Redis cache. If available, we will use the cache data; otherwise, fetch from the content server and set data result into Redis cache.

client.get(key, function (err, reply) {
  if (reply) {
    // cache available
  } else {
    // fetch from content server
    downloadVanityUrl(key, cb);
  }
}

downloadVanityURL(key, cb) {
  request(content_server_url, function(error, response, body) {
    // parse body to object
    // set body to Redis cache.
    // Note: Redis only accepts valid JSON string
  }
}

When refresh cache is called, it will make a request to the content server url until it finally saves the fetched vanity URL into Redis cache.

function refreshCache() {
  downloadVanityURL(key, cb);
}

Redis Cache Refresh

There are two ways to refresh Redis cache depending on the server environment.

Purge Cache

Purging cache takes effect when we put specific keywords in our system to trigger Redis cache refresh. It allows us to target a specific non-production environment (PREPROD or INT) for validating and testing. Note that purging cache only applies to a single non-production server.

Cron Job

Because our production Redis cache system is distributed across multiple servers, purging cache 1-by-1 on each server is no longer an effective solution. Instead, we set a cron job to automatically refresh Redis on the production environment only when there’s an update on the vanity URL JSON file and distributed it to all production servers. In fact, there’s a time duration before the cache refresh takes effect so that we have enough time to test and validate.

Summary

The improved vanity URL system provides more update flexibility. We can update and target where the updates want to happen immediately on the specific environment. One thing to keep in mind is that Redis cache is set to 7 days as default config period for auto-refresh. Depending on the server environment, PREPROD and INT cache can be updated by directly purging cache whereas we set cron job on PROD to do the cache refresh across multiple servers.  Hence, make sure that the cache is still fresh which allows us to have some room for testing and avoid unexpected behavior.

With thanks to Max Vuong, Chris Toomey, Derek Xie, and Kaiyu Kang for their reviews and contributions.