Engineering the Launch of a New Brand for Betterment

In 2017, Betterment set out to launch a new brand to better define the voice and feel of our product. After months of planning across all teams at the company, it was time for our engineering team to implement new and responsive designs across all user experiences.

The key to the success of this project was to keep the build simple, maintain a low risk of regressions, and ensure a clear path to remove the legacy brand code after launch. Our team learned a lot, but a few key takeaways come to mind.

Relieving Launch Day Stress with Feature Flags

Embarking on this rebrand project, we wanted to keep our designs under wrap until launch day. This would entail a lot of code changes, however, as an engineering team we believe deeply in carving up big endeavors into small pieces. We’re constantly shipping small, vertical slices of work hidden behind feature flags and we’ve even built our own open-source system, TestTrack, to help us do so. This project would be no exception.

On day one, we created a feature flag and started shipping rebranded code to production. Our team could then use TestTrack’s browser plugin to preview and QA the new views along the way. When the day of the big reveal arrived, all that would be left to do was toggle the flag to unveil the code we’d shipped and tested weeks before. We then turned to the challenge of rebranding our entire user experience.

Isolating New Code with ActionPack Variants

ActionPack variants provide an elegant solution to rolling out significant front end changes. Typically, variants are prescribed to help render distinct views for different device types, but they are equally powerful when rendering distinct HTML/CSS for any significant redesign. We created a variant for our rebrand, which would be exposed based on the status of our new feature flag. Our variant also required a new CSS file, where all our new styles would live. Rails provides rich template resolver logic at every level of the view hierarchy, and we were able to easily hook into it by simply modifying the extensions of our new layout files. The rebranded version of our application’s core layout imported the new CSS file and just like that, we were in business.

Implementing the Rebrand without a Spaghetti of “IF” Statements

Our rebranded experience would become the default at launch time, so another challenge we faced was maintaining two worlds without creating unneeded complexity. The “rebrand” variant and correlating template file helped us avoid a tangled web of conditionals, and instead boiled down the overhead to a toggle in our ApplicationController. This created a clean separation between the old and new world and protected us against regressions between the two. Rebranding a feature involved adding new styles to the application_rebrand.css and implementing them in new rebrand view files. Anything that didn’t get a new, rebranded template stayed in the world of plain old production. This freedom from legacy stylesheets and markup were critical to building and clearly demonstrating the new brand and value proposition we wanted to demonstrate to the world.

rebrand if statements

De-scoping with a Lightweight Reskin

To rebrand hundreds of pages in time, we had to iron out the precise requirements of what it meant for our views to be “on brand”. Working with our product team, we determined that the minimum amount of change to consider a page rebranded was adoption of the new header, footer, colors, and fonts. These guidelines constituted our “opted out” experience — views that would receive this lightweight reskin immediately but not the full rebrand treatment.

This light coat of paint was applied to our production layer, so any experience that couldn’t be fully redesigned within our timeline would still get a fresh header and the fonts and colors that reflected our new brand. As we neared the finish line, the rebranded world became our default and this opt-out world became a variant. A controller-level hook allowed us to easily distinguish which views were to display opt-out mode with a single line of code.

controller-level hook

We wrote a controller-level hook to update the variant and render the new layout files, reskinning the package.

Using a separate CSS manifest with the core changes enumerated above, we felt free to dedicate resources to more thoroughly rebranding our high traffic experiences, deferring improvements to pages that received the initial reskin until after launch. As we’ve circled back to clean up these lower-traffic views and give them the full rebrand treatment, we’ve come closer to deleting the opt_out CSS manifest and deprecating our our legacy stylesheets for good.

deprecating legacy stylesheets

Designing an Off Ramp

Just as we are committed to rolling out large changes in small portions, we are careful to avoid huge changesets on the other side of a release. Fortunately, variants made removing legacy code quite straightforward. After flipping the feature flag and establishing “rebrand” as the permanent variant context, all that remained was to destroy the legacy files that were no longer being rendered and remove the variant name from the file extension of the new primary view template. Controllers utilizing the opt_out hook made their way onto a to-do list for this work without the stress of a deadline.

The Other Side of the Launch

As the big day arrived, we enjoyed a smooth rebrand launch thanks to the thoughtful implementation of our existing tools and techniques. We leveraged ActionPack variants built into Rails and feature flags from TestTrack in new ways, ensuring we didn’t need to make any architecture changes. The end result: a completely fresh set of views and a new brand we’re excited to share with the world at large.