Crowd-sourced recommendation service Yelp has replaced its legacy Cheetah email template language with React without adding any additional maintenance requirements.
Since its general release, the system has developed more than a dozen new email types and sent millions of emails, according to Yelp software engineer Jack Guy in an interesting blog post that went into great detail about the process.
Whatever your personal feelings about email marketing campaigns, you can see that Yelp has done something very cool with their email campaign platform. Knowing that part of the business involves email marketing, and rather than continue using an outdated system, the engineering team addressed the issues of inconsistent email workflow, difficult onboarding and testing, and a poorly maintained system by using a “same but different approach”
Yelp repurposed its Web React components and used server-side rendering for its email platform without adding any additional maintenance or engineering costs. The new system improved the developer experience by bringing the familiar workflow from the web to email campaigns.
React, reduced to its most basic functionality, is a templating language. It performs many custom functions, but can also render a template. Yelp takes this idea, the template aspect, for the components, changing some details and repurposing them to address the specific needs of email campaigns. What does that mean and how is it done?
Repurposing Web Components
- Step 1: Add component wrappers with the email prefix to make email-specific changes
- step 3: Create custom email components for outliers
Step 1: Component Packaging
The e-mail functionality is significantly less robust than the web functionality. Click or change events such as hover, animation, or highlight are typically not included in emails. To distinguish between web and email components, email components are enclosed with the “email” prefix (e.g. Text -> EmailText, Container -> EmailContainerEtc.).
The image below shows an example of the email version of a Button component. Its web counterpart supports a onClick Handler not passed to the email due to a restricted component API (Yelp uses flow props type).
Email compatibility standards are pretty relevant to this section, so for a quick introduction, consider email clients (Gmail, AOL, Yahoo) as you would for different browsers. Each email client has different compatibility standards, and developers may choose to comply with these requirements or decide that trying to comply is not worth their time (hello Internet Explorer 11).
Since each client has their own standards and the services that manage the sending of email campaigns also have their own standards, the conditional rendering feature of CSS in JS is of great benefit.
The following image is an illustration of the Stylis plugin that helps resolve a compatibility issue when using “Var‘ in real estate values.
Without CSS in JSS’s ability to conditionally render the CSS, Guy believes Yelp “would probably be forced to add an email-specific support with some branching logic to conditionally remove the CSS.” And that would “introduce a maintenance overhead and introduce concerns about email playback that our web components wouldn’t otherwise have.”
Step 3: Create custom email components
There are cases when there are fundamental incompatibilities and email components are rewritten from scratch. An example of this is the Rating Selector. On the website, the review selector allows users to flag a review
In email campaigns, Yelp still wants users to tap a star rating to start a review, but they can’t replicate hover highlight behavior in email clients. CSS in JSS plugins or wrapping components doesn’t solve the problem, so Yelp created a custom one EmailRatingSelector Inspired by the original design but better suited for static rendering.
Once the components are created, server-side rendering is mission-critical as it converts the React component to HTML for sending. Email traffic, unlike web traffic, which follows predictable curves, is typically sent in planned campaigns consisting of thousands to millions of emails in a batch.
Initial testing of the legacy SSR system revealed a serious bottleneck, throttling emails down to just ten emails per second, which was unacceptable for a production-level campaign. Yelp had a lot of experience scaling server-side rendering elsewhere and had the experience to invest in a new server-side rendering system that could easily scale to thousands of emails per second.
The following diagram shows the email development process for backend developers.
Yelp’s step-by-step process for detailing the chart is as follows:
When a backend developer writes a batch for a massive email campaign (usually with spark), they make email send requests to Mercury, our internal notification system (powered by our data pipeline and Kafka). These broadcasts contain basic information such as the user to send to and the campaign it belongs to, as well as a payload with data needed to render the template. These send requests are picked up by workers in our email rendering microservice, which in turn triggers a request to our SSR service shard (the payload is turned into React props). The shard returns our rendered email in HTML, which is then forwarded to the rest of the email delivery pipeline.
An additional benefit of rendering emails using the existing SSR infrastructure is the optional GraphQL query. Because React is already connected to Apollo, no additional work is required to include data in online queries from email templates.
post-processing and shipping
This is the final step in this process and involves cleaning up the SSR HTML as it is tailored in its raw state to be rendered and hydrated in a web browser. Yelp uses Pyquery to optimize the superfluous script tags and attributes. The following code:
Email clients have limitations like
Yelp engineers found that this new React-based email system meets their goals of keeping maintenance costs down while providing a new system that’s easy to use for developers with current designs. While some of these details are specific to Yelp, the system can be replicated. See the original article for more details on this process.