Building Postcards for “Airbnb” Scale
By: Leo Wong, Henry Johnson
How the Airbnb Media team built group travel Postcards for the 2024 Summer Release by leveraging a novel destination matching algorithm while advancing the platform’s image & localized text processing capabilities.
Introduction
For Airbnb’s 2024 Summer Release, the Media Ingestion team at Airbnb took on the exciting challenge of creating a reliable postcard generation system to generate unique, hand-crafted Postcards. Postcards are a beautiful way to invite guests on a trip while keeping friends and family in the loop (see announcement). This feature required a novel solution to match relevant postcards to every possible destination that guests booked on Airbnb. It needed to render performantly not only on all our client platforms (iOS, Android, and Web), but also on different messaging platforms outside the Airbnb app, all while maintaining Airbnb’s high design standards.
Challenges
- Localized Text Layout: Postcards have strict design guidelines around character count per line, font leading & kerning per language, pixel perfect typography, line break rules, and language-specific styling.
- Design & Product Flexibility: Text layout, color, fonts, text drop shadows and image transformations need to be flexible for product & design changes.
- Destination Matching: Postcards need to match the destination by including relevant artwork and localized destination names.
- Availability On and Off Platform: Assets need to be surfaced on and off the platform, which necessitated a pre-generated server-side solution; client-only solutions wouldn’t work since we needed Open Graph compatible links for assets to render properly in iMessage and Instagram, for example.
- Performance: Postcard presentation shouldn’t interrupt the product UX by taking significant time to render.
Solution
Postcard Setup
A Trips Postcard is the combination of (1) an artwork illustration, (2) a postcard template, and (3) a localized destination. A Postcard “template” is a data entity with a reference to the artwork illustration plus some additional metadata to describe how to render it. To render a Postcard in product, we need to have all artwork illustrations, postcard templates, and formatted localized destinations set up before a visitor sees the product flow.
In the example below, we have an illustration of a cliff side, a postcard template, and an English language variant of the destination name “Galway”. The Postcard template includes parameters to specify how to create the postcard, like text and Belo (Airbnb brand icon) color and positioning. In the example, the text and Belo are rendered in gray color and positioned at the bottom and top left, respectively.
Design Flexibility — Postcard Templates
To accommodate changing design requirements, we built a flexible template data model that empowers our design team to configure various parameters like text positioning and text color while iterating on the designs. The postcard templates include all the metadata required to generate a Postcard and its surrounding presentation elements. It also includes a versioning capability so that we can publish changes to all users with a version bump whenever we have a design revision or visual defect.
Template & Artwork Upload, Management & Preview
To make it easy for the creative team to self-serve and debug issues, we built a web-based internal tool for creating and managing templates, previewing postcards, and uploading artwork. This tool made it significantly easier to manage templates, and was especially useful during the team’s peak iteration period where we were constantly fixing bugs and changing designs.
Localized Text Layout
We wanted accurate translations of destinations that were properly formatted for each localized postcard. A programmatic solution for localized text layout would require, at the very least, language specific rules (right to left, word wrapping, etc.), knowledge of cultural conventions, accessibility considerations, and text rendering for special characters (diacritics, etc.). This would make business logic complex and brittle.
We compromised on this solution with the localization (l10n) team by manually formatting translations for destinations that made up our top booking destinations. These manually formatted translations involved getting our l10n scaled operations team to translate and format (line breaks, layout spacing, etc.) a shortlist of localized destinations, which we helped ingest into our typical i18n platform translated text workflow with some scripting. After ingestion, the Postcard generation system pulls from our i18n platform to get the desired localized formatted text layout for each Postcard.
The destinations shortlist was informed by our data science team, who helped gather the top booked destinations by language. This reduced the scale of required postcards to generate from all destinations in the full set of language locale destination combinations on the platform, to a magnitude of scale smaller destination subset. As a result, postcard QA was significantly easier. More importantly, it kept the overall system code and maintenance simple; no need for thousands of lines of language specific business logic!
The rest of the postcards that didn’t make the top destinations list followed a simple formula of word count and line breaks per language (e.g. Chinese, Korean, and Japanese had smaller word count limits because of the character size and no line break on spaces because it changes the meaning of the destination).
Postcard Generation
Destination Matching
To find the best-matching postcard template for each destination, we have a matching algorithm that matches templates to reservations at booking time using four different criteria:
- By listing — We wanted to be able to support listing-specific artwork. E.g. Our Icons listings show a golden ticket to commemorate the special moment when a guest wins the lottery for staying at an Icons listing.
- By destination — For popular destinations (matching by city and country), we have curated artwork that showcases both a local artist and the destination. E.g. Trips to Santorini present the iconic Cycladic domes of Santorini as artwork (see diagram below).
- By taxonomy — For all other artwork, we match destinations based on a set of taxonomy tags. We partnered with the knowledge graph team to apply taxonomy attributes to all of our listings in a few different categories: density (i.e. metropolitan, urban), climate (i.e. tropical, temperate) and geography (i.e. coastal, mountain, river). We ensured the taxonomy was accurate by cross referencing existing internal data and the expertise of our regional representatives teams. They then exposed an API that we called to fetch taxonomy by listing. On the operations side, our production team created taxonomy tagged artwork (e.g. an artwork tagged to be used for a coastal, temperate, metropolitan postcard). When generating postcards, we match the listing to the artwork with the highest number of overlapping tags.
- By default — If a destination isn’t covered by the above categories, we show a fallback default artwork.
Formatted Translations
We take the listing of each booking request and fetch the city and country from the listing service and check to see if that destination was in our curated set of formatted destinations loaded into our i18n service. We then take the best fitting artwork and embed the localized destination text on it to generate the final postcard. If we don’t get a translation back, we fall back to serving the postcard without text.
Performance — Async Postcard Creation Flow
Putting a localized destination and a Belo icon onto artwork is a time-consuming operation given the high resolution artwork we used. We knew the image processing flow could take over 8 seconds on average to process an image so we needed to come up with a way to make our postcard API respond quickly. We also wanted to transfer these generated postcards into our primary image storage so we could leverage our existing media serving infrastructure, which introduced an additional 1–2 seconds of latency.
In order to still be performant, we went with a partly asynchronous approach where, during the live in product request, we only serve postcards that we’ve already generated and stored internally. If there was a request for a new postcard, we would instead return a fallback postcard and publish an event to a Kafka queue where an async consumer would call the processing service, wait for the asset to be generated and then transfer it into our system to be used for future requests.
As shown in the diagram below, we fetched the listing information and taxonomy information in parallel before computing the best matching artwork for the trip. Based on a pattern in how the postcards are stored, we would check in our media service to see if the postcard was generated already before either returning the card if it was found or kicking off the asynchronous flow if it was not found. At that point, our media service’s Kafka consumer would complete the flow by transforming the asset into a postcard and storing it in our system.
Pre-generation
We wanted to generate as many of the postcards as possible before the launch. If the postcard hasn’t been generated when a guest books a group trip, everyone on the booking will see the default, generic postcard. Our data science team helped determine top destinations, and we ran those inputs through our postcard generation pipeline to pre-generate as many postcards as possible and minimize the chance of falling back to a default postcard. Within a week of launching, more than 90% of trips had a custom postcard instead of a default and we inched closer to generating a postcard for all trips in the months after.
Conclusion
Creating postcards was a massive effort that required collaboration across multiple engineering, product, design, and data science teams to improve Airbnb’s group travel feature. Our frontline insights team continues to receive positive social media and external feedback on this update that adds delight to joining a group trip.
The solution highlights the importance of having the right internal tooling, image and text processing capabilities, and destination matching logic for solving something at Airbnb’s scale.
Postcards is one of the first major image processing use cases that the Media team built to support a new Airbnb feature. It highlights the power of media capabilities and innovative features we can build with them. If you like the type of work we do at Airbnb, please contact us & check out our careers page!
Acknowledgments
Thanks to the following engineers who helped to build this feature: Alan Wright, Aditya Punjani, Bill Lovotti, Jessica Chen, Miguel Jimenez