Embedded Reviews at Yelp
-
David W., Software Engineer
- Oct 4, 2016
Yelp is known for useful, funny, and cool reviews of all kinds of businesses, so it’s no surprise that they often get shared in other places. While we love seeing screenshots of these reviews shared on other websites, they don’t make for a great user experience. Their image formats make it easy to create and share but they become outdated, load slower than text, and make it hard for users to find out more about the business. We wanted to build something that retains screenshots’ ease of sharing while solving some their biggest shortcomings, so we created embedded reviews. Now, content creators and business owners can directly embed Yelp reviews on their websites. Embedded reviews are always up-to-date, load as HTML, and link back to the business.
Read Krsna V.’s review of Badlands National Park on Yelp
What makes a good embed widget?
The HTML snippet is what content creators and business owners copy and paste onto their websites, so it should have the minimal amount of HTML code necessary to achieve an embedded review. It should also be consistent so that it doesn’t need to be changed every time the review widget is updated with new contextual information.
The HTML snippet renders and displays fully styled embedded review widgets which should be responsive, so that it looks good on any website or any device. The content should also stay up-to-date with contextual information like the latest rating of the business and the reviewer’s most recent edit of their review.
To better understand how embedding is being used, and to inform future improvements, we should also record accurate analytics on the widgets to see where reviews are being embedded and which reviews are being embedded.
Performance is a major consideration for the embed widget. Embedded reviews need to load fast alongside the content on the embedding page. Embedded reviews also need to gracefully handle traffic spikes from popular websites.
Minimizing HTML and Maximizing Functionality
With our embedded content, we took the approach of minimizing the HTML snippets that content creators and business owners embed on the web page, and dynamically loading in a fully styled widget when users view the page the widget is embedded on. This lets us keep the content up to date and roll out changes to our embed widget without requiring updates to the HTML snippets. The embed HTML we provide uses a script tag that loads JavaScript called widgets.js. All of the functionality of styling and dynamically loading in a full embedded review resides in widgets.js. Here’s what our HTML snippet looks like:
This is what users see before widgets.js runs:
Read Jr P.’s review of Kelly’s Cove on Yelp
Good candidates for the HTML snippet are static, unstyled, or empty elements such as the script tag. For our HTML snippet, we included some static links in case the JavaScript couldn’t load. All of the functionality of loading in the fully styled embedded content is contained in widgets.js. Widgets.js consists of pure JavaScript with no dependencies on libraries so it can run on any website.
Dynamically Creating the Fully Styled Embedded Review
Once the page loads, widgets.js executes. Widgets.js does a bit of magic to create a fully styled embedded review. We decided to have widgets.js create the fully styled embedded review widgets within iframes, rather than directly in the containing page. Review widgets are served as Yelp pages within iframes, adhere to the Yelp Styleguide, and show the most up-to-date review.
iframe embeds are preferable to direct embeds in these ways:
- iframe embeds allow for a simpler widgets.js. widgets.js only needs to construct the iframe and it defers rendering and styling the review widget to the iframe. In order to display the same review widget with direct embeds, widgets.js needs to retrieve review data from Yelp, construct the markup for the content, and style the markup.
- iframe embeds make development easier. The review widget can be developed and tested as its own Yelp page instead of as part of widgets.js, which also contains the embedding functionality. Yelp pages also come with Yelp Styleguide resources built in. Direct embeds would have to duplicate these resources inside widgets.js.
- iframe embeds can take advantage of HTML caching. When served as a Yelp page inside an iframe, review widgets are static and therefore the entire page can be cached. Directly embedding the review widget requires JavaScript code to generate and insert the markup, losing caching ability. We’ll go over this in a later section.
The review widget is built so that it displays nicely inside the iframe. Initially, the iframe has 0 height and width. After the review widget is loaded, the iframe height and width changes to fully display the review widget. This requires the review widget hosted on Yelp to pass sizing information to widgets.js running on the embedding page. Communication between scripts hosted on different domains are restricted due to the same-origin policy. window.postMessage() enables us to safely do cross-origin communication.
Read Jr P.’s review of Kelly’s Cove on Yelp
Accurate Analytics in Embedded iframes
So far, our responsive embedded review widget consists of the widgets.js controller, iframes for review widgets, and postMessage to communicate between the two. We realized that we could overcount page impressions for embedded reviews if a user embedded multiple reviews on the same site. To handle this we architected our analytics to serve Google Analytics (GA) on a Yelp domain in a separate, standalone iframe on the embedding page. We call this the GA iframe. We create one instance of the GA iframe per embedding page to handle sending events: one ‘pageview’ event when the user loads the embedding page and a separate ‘load’ event for every review widget iframe on the embedding page. These events are all sent through the single GA iframe. Review widget iframes and the GA iframe communicate with postMessage with widgets.js as the hub. Once a review widget loads inside the iframe, it notifies widgets.js via postMessage. widgets.js then resizes the review widget’s iframe and sends a GA event. Putting it all together, this is what the architecture looks like:
Speedy and Scalable
Now that we have all the functionality of a good embedded review widget, we need to look at performance. Embedded reviews were designed with speed and scalability in mind. We wanted our embedded review widgets to load fast to be as seamless as possible with the web page content. We also wanted our embedded reviews to be scalable to handle traffic spikes so that viral web pages loading multiple embedded reviews wouldn’t overload our servers. We identified two parts of the embed flow that could be optimized to be speedy and scalable: widgets.js and the iframes served by Yelp.
We wanted to ensure that we could update widgets.js in the future without content creators and business owners having to push new embed snippets. If we had hosted widgets.js on a static CDN site, we could not have fulfilled this requirement. Instead, we serve it through our web app, much like how a regular Yelp page is served, allowing us to serve different versions of widgets.js. The problem is that a centralized web app serving JavaScript represents a single point of failure and slower load times for users far away from the web app. We use our web app to redirect to a static JavaScript file hosted on a CDN to serve widgets.js faster to users around the world.
Since the review widget iframe and GA iframes are static pages served by Yelp, we use full page HTML caching. This way, most of the user traffic sees the cached page and our servers won’t even be contacted from traffic spikes from particularly viral web pages.
In summary, here is how we designed a good embed widget:
- The embed HTML snippet consists of unstyled and empty elements so that the HTML snippet is minimal and durable.
- We use a controller loaded via script tag to create and load iframes. The controller consists of pure JavaScript and doesn’t use any libraries. The controller communicates with the iframes using postMessage.
- We use a Google Analytics iframe served by Yelp to handle sending events for multiple review widget iframes on a single page. Resources served by Yelp, such as the controller and the iframes are either cached or served via CDN.
Check out Embedded Reviews on Yelp Business Pages!