Yelp Modernizes Email Marketing Platform with React
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 on the process.
Whatever your personal feelings about email marketing campaigns, you can see Yelp did something very cool with its email campaign platform. Knowing that part of the business does include email marketing, and rather than continue to utilize an outdated system, the engineering team tackled the problems of inconsistent email workflow, challenging onboarding and testing, and a poorly maintained system, all 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 as it brought the familiar workflow from the web into email campaigns.
React, stripped down to its most basic functionality, is a templating language. It performs many custom functions but it can also represent a template. Yelp takes this idea, the template aspect, for the components, changes some of the details, and repurposes them with the specific needs of email campaigns in mind. What does this mean and how is it done?
Repurposing Web Components
- Step 1: Add component wrappers prefixed as email to make email-specific modifications
- Step 3: Create custom email components for outliers
Step 1: Component Wrappers
Email functionality is significantly less robust than web functionality. Click or change events such as hover, animation, or highlight are usually not included in email. In order to distinguish between web and email components, email components are wrapped with the prefix “Email”(e.g., Text -> EmailText, Container -> EmailContainer, etc.).
The image below represents an example of the email version of a Button component. It’s web counterpart supports an onClick handler that is not passed into the email because of a restricted component API (Yelp uses the Flow props type).
Email compatibility standards are pretty relevant to this section so for a quick intro, consider email clients (Gmail, AOL, Yahoo) like you would for different browsers. Each email client has a different set of compatibility standards and developers can decide to work within those requirements or decide it’s not worth their time to try to meet them (hello Internet Explorer 11).
Since each client has its own set of standards and the services that manage email campaign sends also have its own set of standards, the conditional rendering functionality of CSS in JS is hugely beneficial.
The image below is a representation of the Stylis plugin helping address a compatibility issue with the usage of “var” in property values.
Without CSS in JSS’s ability to conditionally render the CSS, Guy believes Yelp would “likely be forced to add an email-specific prop with some branching logic to conditionally remove the CSS.” And that would add “a maintenance burden and introduces a concern with email rendering that our web components would not otherwise have.”
Step 3: Create Custom Email Components
There are cases where there are fundamental incompatibilities and Email components are written from scratch. One example of this is the Rating Selector. On the website, the Rating Selector allows users to star a review
In email campaigns, Yelp still wants users to tap a star rating to begin a review but they are not able to replicate the highlighting behavior on hover in email clients. CSS in JSS plugins or wrapping components don’t solve the problem so Yelp created a custom EmailRatingSelector inspired by the original design but better suited for rendering statically.
Once the components are created, Server-side rendering is mission critical because it turns the React component into HTML for sending. Email traffic, unlike web traffic which follows predictable curves, is usually sent in scheduled campaigns that consist of thousands to millions of emails in one batch.
Initial tests on the legacy SSR system highlighted a serious bottleneck that throttled emails at just tens of emails per second, unacceptable for a production-level campaign. Yelp had much experience with scaling Server-Side Rendering elsewhere and had the experience needed to invest in a new Server-Side Rendering system that could easily scale to thousands of emails sent per second.
The diagram below details the email development process for backend developers.
Yelp’s step-by-step process detailing the diagram is as follows:
When a backend developer writes a batch for a massive email campaign (typically using Spark), they queue email-send requests to Mercury, our internal notifications system (powered by our data pipeline and Kafka). Those sends contain basic information such as the user to send to and the campaign it belongs to, as well as a payload containing data that’s required to render the template. These send requests are ingested by workers in our email-rendering microservice, which in turn triggers a request to our SSR service shard (the payload gets turned into React props). The shard returns our rendered email in HTML, which is then forwarded along to the rest of the email-sending pipeline.
An added benefit of rendering emails with the existing SSR infrastructure is the optional GraphQL query. Since React is already connected to Apollo, no additional work is needed to include data in any email template online queries.
Post-Processing and Sending
This is the last step in the process and it includes cleaning up the SSR HTML as in its raw state it’s tailored to be rendered and hydrated in a web browser. Yelp uses pyquery to lean up the extraneous script tags and attributes. The following code:
Email clients have limitations like <style> tag byte limits that make it necessary to move <head> tag CSS into HTML element style=”” attributes. There are many open source options that help with this task.
Yelp engineers found this new React-based email system aligns with their goals of keeping maintenance costs low while providing a new system that was easy to use for developers with up-to-date designs. While some of these details are Yelp-specific, the system can be replicated. For more specific details on this process, please check out the original article.