<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Dikla Cohen on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Dikla Cohen</name>
  </author>
  <link href="https://web.dev/authors/msdikla/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/b9zEc84wlzbNww2MKoBL.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Our latest news, updates, and stories by Dikla Cohen.</subtitle>
  
  
  <entry>
    <title>Luxury retailer Farfetch sees higher conversion rates for better Core Web Vitals</title>
    <link href="https://web.dev/farfetch/"/>
    <updated>2022-07-12T00:00:00Z</updated>
    <id>https://web.dev/farfetch/</id>
    <content type="html" mode="escaped">&lt;p&gt;Inside many companies, website speed performance and Core Web Vitals are still mostly seen as the responsibility of the engineering teams. Site speed can become invisible to other areas of the business if the business and customer experience worth is not understood. This can cause performance to be overlooked when key decisions are made and roadmaps are defined.&lt;/p&gt;
&lt;p&gt;To improve the performance culture across teams and drive significant improvements to their web experience, luxury e-commerce fashion retailer Farfetch launched a project to define and use true customer-centric performance metrics. They aimed to correlate these to business metrics as a way of illuminating how performance affects the company&#39;s KPIs.&lt;/p&gt;
&lt;p&gt;Their ambitions didn&#39;t end there, though. Ultimately, the project&#39;s objective was cultural change at scale—breaking down silos within the organization and introducing a new business-oriented language to give everyone a shared way to talk about what used to be considered technical topics. Farfetch wanted to have website speed performance as a shared responsibility, facilitate informed decision making and establish it as a main pillar of what makes a good web experience.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A diagram contrasting speed as a developer&amp;#x27;s responsibility versus speed as a shared responsibility. In the former case, each phase is siloed, whereas in the latter, each phase occurs within the same silo.&quot; decoding=&quot;async&quot; height=&quot;477&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/pRj3pK9qy1w3HRDNtcSE.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;To kick off, Farfetch realized a single department couldn&#39;t achieve this as before and assembled a core team of experts from various areas in the company—engineering, infrastructure, architecture, and product—that put in place a step-by-step strategy to revamp how the company looked at this topic.&lt;/p&gt;
&lt;h2 id=&quot;step-1-defining,-measuring-and-monitoring-metrics&quot;&gt;Step 1: Defining, measuring and monitoring metrics &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/farfetch/#step-1-defining,-measuring-and-monitoring-metrics&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First of all, Farfetch needed to have the right monitoring tools in place to understand current state and deviations across journey touchpoints and applications.&lt;/p&gt;
&lt;p&gt;They used both lab data and real user monitoring (field data) to track Core Web Vitals and additional &lt;a href=&quot;https://web.dev/user-centric-performance-metrics/&quot;&gt;user-centric performance metrics&lt;/a&gt; to analyze the current state of speed performance. They used JavaScript and the &lt;a href=&quot;https://github.com/GoogleChrome/web-vitals&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;web-vitals.js&lt;/code&gt; library&lt;/a&gt; to capture the data, which allowed the product analytics team to gain visibility of performance metrics alongside business metrics in the same session and thereby start examining how one affects the other.&lt;/p&gt;
&lt;p&gt;The multidisciplinary group set out to understand which metrics mattered most for the business. To do so, they looked at the critical journey path of Farfetch users and tried to link that journey with performance markers. In addition to the Core Web Vitals metrics that Google has outlined, each representing a distinct facet of the user experience, they also used custom JavaScript to track &lt;a href=&quot;https://web.dev/ttfb/&quot;&gt;Time to First Byte (TTFB)&lt;/a&gt;, &lt;a href=&quot;https://web.dev/fcp/&quot;&gt;First Contentful Paint (FCP)&lt;/a&gt;, First Paint and &lt;a href=&quot;https://web.dev/tti/&quot;&gt;Time to Interactive (TTI)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The metrics are collected using several methods of the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Performance&quot; rel=&quot;noopener&quot;&gt;Performance API&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Long_Tasks_API&quot; rel=&quot;noopener&quot;&gt;Long Tasks API&lt;/a&gt; and Google&#39;s polyfills. More details can be found in &lt;a href=&quot;https://www.farfetchtechblog.com/en/blog/post/one-less-second-for-the-page-one-giant-leap-for-the-business/&quot; rel=&quot;noopener&quot;&gt;this mid 2020 Farfetch Tech Blog post&lt;/a&gt; by Manuel Garcia, Senior Principal Engineer for the Web.&lt;/p&gt;
&lt;p&gt;On the data analytics side, Farfetch have their own multi-channel tracking solution used by front end applications called Omnitracking. It tracks the events generated by page views, user actions and system actions. The Omnitracking Data Model is Farfetch&#39;s solution for analytical, data exploration and reporting cases, made on the top of the events generated by trackers. The data model&#39;s objective is to help and support anyone who needs to understand:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User behavior&lt;/li&gt;
&lt;li&gt;User experience on Farfetch applications&lt;/li&gt;
&lt;li&gt;Applications usage&lt;/li&gt;
&lt;li&gt;Macro and micro conversions&lt;/li&gt;
&lt;li&gt;Cross channel and funnel analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The idea was then to add the performance data of each pageview on farfetch.com, captured by JavaScript, to this data layer. Following this model guaranteed a match between performance data and the main conversion funnel metrics for each session and the base for an analytical exploration on the topic.&lt;/p&gt;
&lt;p&gt;Finally, Farfetch established time-based &lt;a href=&quot;https://web.dev/performance-budgets-101/&quot;&gt;performance budgets&lt;/a&gt; for each metric across the main journey pages and a governance process to handle budget breaches. They&#39;ve also started incorporating performance metrics on CI pipelines to understand budget deviations as soon as possible in the development flow.&lt;/p&gt;
&lt;h2 id=&quot;step-2-communicating-via-business-language&quot;&gt;Step 2: Communicating via business language &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/farfetch/#step-2-communicating-via-business-language&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With performance data now available in Farfetch&#39;s internal business intelligence datasets, the analytics team started exploring mathematical models and patterns in the data that could indicate a correlation between performance metrics and business KPIs (for example, conversion rate and percentage of single-page visits), allowing a new view of the financial impact of site speed and UX for the business. This enabled performance to be discussed in a common language with the business decision makers. The analysis included all Core Web Vitals and the other metrics Farfetch deemed valuable. It revealed truly impactful insights.&lt;/p&gt;
&lt;p&gt;Having in mind that Google recommends &lt;a href=&quot;https://web.dev/lcp/&quot;&gt;Largest Contentful Paint (LCP)&lt;/a&gt; to stay below 2.5 seconds to provide an optimal user experience, Farfetch studied this threshold carefully and found meaningful results.&lt;/p&gt;
&lt;p&gt;Farfetch statistical correlation analysis showed that beyond that point, the conversion rate starts to drop, as well as the exit rate rises. This shows that users really start to feel the downside of a slow page load perception and conversion rate decreases on average -1.3% with each 100ms more of LCP.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A graph of LCP, where the Y-axis is conversion rate and percentage of page visits and the X-axis is LCP time. As LCP is faster, percentage of single page visits decreases, and conversion rate increases.&quot; decoding=&quot;async&quot; height=&quot;386&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/bdmOd1MUc6Wt4EUFRzUG.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Farfetch also verified an exit rate decrease of -3.1% for each 0.01 less on the &lt;a href=&quot;https://web.dev/cls/&quot;&gt;Cumulative Layout Shift (CLS)&lt;/a&gt; score, reaffirming the impact of page stability to keep users on a website.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A graph of CLS, where the Y-axis is conversion rate and percentage of page visits, and the X-axis is the CLS score. The lowest CLS scores show the highest percentage of single page visits, whereas conversions raise at lower CLS scores.&quot; decoding=&quot;async&quot; height=&quot;357&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/ijjXV4FFD5lyBYVFEBH2.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Regarding page interactivity and fluidity, although &lt;a href=&quot;https://web.dev/fid/&quot;&gt;First Input Delay (FID)&lt;/a&gt; is tracked and analyzed continuously, Farfetch also measures TTI, which proved to be a considerably impactful metric for the Farfetch business conversion funnel.&lt;/p&gt;
&lt;p&gt;For this, they injected &lt;a href=&quot;https://github.com/GoogleChromeLabs/tti-polyfill&quot; rel=&quot;noopener&quot;&gt;Google&#39;s TTI polyfill&lt;/a&gt; into the website to store this metric. Using the Long Tasks API to report long tasks (tasks taking longer than 50 milliseconds on the browser&#39;s main thread).&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; It&#39;s no longer recommended to measure TTI in the field, as user interaction can affect your page&#39;s TTI in ways that lead to variance in your reports! &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The analytics team was then able to find that the conversion rate increased 2.8% for each second reduction on TTI, making a strong case for better code efficiency and unclogging the browser&#39;s main thread.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A graph of TTI, where the Y-axis is conversion rate and percentage of single page visits, and the X-axis is TTI time. As the TTI time goes up, conversion rate decreases and percentage of single page visits increases.&quot; decoding=&quot;async&quot; height=&quot;381&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/p9tLq7SN6rGmJpvnoaoT.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;In the end, this analysis was also able to show that some metrics didn&#39;t have a significant impact on business KPIs, or some would be more relevant at different stages of the user journey. This allowed for a complete understanding of the opportunities at hand on each point of the conversion funnel.&lt;/p&gt;
&lt;h2 id=&quot;step-3-embedding-cultural-change&quot;&gt;Step 3: Embedding cultural change &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/farfetch/#step-3-embedding-cultural-change&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Showcasing the insights above alongside qualitative user research on user perception of site speed was paramount to establish alignment with company goals, secure executive-level awareness and buy-in for performance based decision making across product roadmaps. It was now possible to prove how much performance was worth for Farfetch.&lt;/p&gt;
&lt;p&gt;To streamline prioritization, Farfetch created a self-service tool they named the Site Speed Business Case Calculator, taking inspiration from &lt;a href=&quot;https://www.thinkwithgoogle.com/feature/testmysite/&quot; rel=&quot;noopener&quot;&gt;Google&#39;s Speed Impact Calculator&lt;/a&gt;. It allows any product manager to create a business case out of performance improvements by calculating the business impact on the fly. With a data model using the correlation between conversion rate and user experience metrics, it&#39;s flexible to adapt to different product scopes, devices and user journey touch points.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of Farfetch&amp;#x27;s Site Speed Business Case Calculator.&quot; decoding=&quot;async&quot; height=&quot;779&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/OcYv93SYnIg1kfTihK6xqRDebvB2/23elcWwZJW50ZSB9s5CB.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Meanwhile, a set of self-service analytical dashboards have created business-wide visibility of real-time performance indicators and their impact on the business. Performance is now becoming fully embedded in product development, and product teams enjoy easy access to metrics, auditing tools, and performance budget monitoring. Furthermore, because of the data layer integration, performance metrics are also available on Farfetch A/B testing tooling, giving product managers yet another powerful vector of insights.&lt;/p&gt;
&lt;p&gt;In recent months, the core team is also on track to establish this culture not only on front-end development teams but also within the platform domain, using similar methodologies to monitor and prove the impact of the main micro services and transactions.&lt;/p&gt;
&lt;p&gt;There have been a number of &lt;a href=&quot;https://www.youtube.com/watch?v=GD3tUD0Vm88&quot; rel=&quot;noopener&quot;&gt;Farfetch driven presentations&lt;/a&gt; on this topic but also external mentions. For example, a mention on &lt;a href=&quot;https://www.youtube.com/watch?v=nPmAE0YjGK0&quot; rel=&quot;noopener&quot;&gt;a 2021 Google I/O talk on the business impact of Core Web Vitals&lt;/a&gt;. This also contributed to giving continuous relevance to the theme and solidified the team&#39;s strategy on culture.&lt;/p&gt;
&lt;h2 id=&quot;step-4-improving-metrics&quot;&gt;Step 4: Improving metrics &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/farfetch/#step-4-improving-metrics&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the end, all of this work needed to contribute to Farfetch objectively improving their website speed metrics, and guaranteeing that their teams would follow best in class practices and pursue enhancement opportunities.&lt;/p&gt;
&lt;p&gt;One of the main opportunities detected in 2021 was the need to improve LCP on the two main page types of Farfetch—product pages and product listing pages.&lt;/p&gt;
&lt;p&gt;The teams addressed how they were loading the main content of those pages. Armed with a business case that showed the impact of chasing this opportunity, they were able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adapt the product image loading component from a JavaScript-based solution to a native implementation.&lt;/li&gt;
&lt;li&gt;Define the priority of the images and divide them into critical and non-critical assets.&lt;/li&gt;
&lt;li&gt;Load critical images early, with the source already inline in the HTML and using &lt;code&gt;&amp;lt;link rel=&amp;quot;preload&amp;quot;&amp;gt;&lt;/code&gt; so they download as soon as possible.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;&amp;lt;img loading=&amp;quot;lazy&amp;quot;&amp;gt;&lt;/code&gt; attribute for non-critical images, with a polyfill using Intersection Observer on unsupported browsers, such as Safari.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this, they were able to move the needle and prove through A/B testing the hypothesis and business impact. On product pages for example, this effort shaved off more than 600ms, and the A/B test showed an uplift on conversion rate in the range of 1-5% with the company&#39;s defined confidence level.&lt;/p&gt;
&lt;p&gt;Below are the improvements the team were able to make in terms of the percentage of pageviews that are considered &amp;quot;good&amp;quot;, &amp;quot;needs improvement&amp;quot; and &amp;quot;poor&amp;quot;, based on &lt;a href=&quot;https://web.dev/lcp/#what-is-a-good-lcp-score&quot;&gt;Google&#39;s definition for LCP score&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A stacked bar graph of median LCP across Core Web Vitals thresholds for Farfetch listing pages. Pages at the &amp;#x27;good&amp;#x27; threshold increased from 37% to 53%.&quot; decoding=&quot;async&quot; height=&quot;494&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/4qkZjdGJDHNlQbKJtmkJ.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A stacked bar graph of median LCP across Core Web Vitals thresholds for Farfetch listing pages. Pages at the &amp;#x27;good&amp;#x27; threshold increased from 36% to 48%.&quot; decoding=&quot;async&quot; height=&quot;494&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/jL3OLOhcWUQDnR4XjewLBx4e3PC3/hUjnQ4CNtyEhHBUFeuEa.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-rewards-of-a-faster-site-and-better-working-practices&quot;&gt;The rewards of a faster site and better working practices &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/farfetch/#the-rewards-of-a-faster-site-and-better-working-practices&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Building a culture around performance and tools like the business case calculator allowed everyone to begin speaking a shared language that can be understood by product managers, stakeholders, and engineers alike. This has precipitated ongoing discussions around how to prioritize new initiatives and performance enhancements.&lt;/p&gt;
&lt;p&gt;&amp;quot;We wanted to break the cycle of performance being a tech-only concern, something owned only by the engineering team to deal with and fix,&amp;quot; explains Farfetch&#39;s Web Channels Senior Principal Product Manager, Rui Santos. &amp;quot;Connecting performance metrics with business metrics was surprisingly effective to pass the message across very, very quickly. Business drives the company, and connecting its success to speed metrics encouraged a broader set of stakeholders to understand and navigate the trade-off decisions.&amp;quot;&lt;/p&gt;
&lt;p&gt;In the luxury e-commerce segment, whether your site is fast or slow can dictate how consumers see your brand and your service quality as a whole. For users, quality equates to luxury—and this applies to every aspect of their experience, including how your website performs. With site speed producing a proven effect on conversion rate, performance now occupies a safe position in forward planning at Farfetch.&lt;/p&gt;
</content>
    <author>
      <name>Rui Santos</name>
    </author><author>
      <name>Manuel Garcia</name>
    </author><author>
      <name>Patrícia Couto Neto</name>
    </author><author>
      <name>Dikla Cohen</name>
    </author>
  </entry>
  
  <entry>
    <title>Building a PWA at Google, part 1
</title>
    <link href="https://web.dev/building-a-pwa-at-google-part-1/"/>
    <updated>2020-07-29T00:00:00Z</updated>
    <id>https://web.dev/building-a-pwa-at-google-part-1/</id>
    <content type="html" mode="escaped">&lt;p&gt;This is the first of a series of blog posts about the lessons that the Google Bulletin team learned
while building an external-facing PWA. In these posts we&#39;ll share some of the challenges we faced,
the approaches we took to overcome them, and general advice for avoiding pitfalls. This is by no
means a complete overview of PWAs. The aim is to share learnings from our team&#39;s experience.&lt;/p&gt;
&lt;p&gt;For this first post we&#39;ll cover a little background information first and then dive into all the
stuff we learned about service workers.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Bulletin was shut down in 2019 due to lack of product/market fit. We still learned a lot about PWAs along the way! &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;background&quot;&gt;Background &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#background&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Bulletin was in active development from mid-2017 to mid-2019.&lt;/p&gt;
&lt;h3 id=&quot;why-pwa&quot;&gt;Why we chose to build a PWA &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#why-pwa&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before we delve into the development process, let&#39;s examine why building a PWA was an attractive
option for this project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ability to iterate quickly&lt;/strong&gt;. Especially valuable since Bulletin would be piloted in
multiple markets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single code base&lt;/strong&gt;. Our users were roughly evenly split between Android and iOS. A PWA meant
we could build a single web app that would work on both platforms. This increased the velocity
and impact of the team.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Updated quickly and independent of user behavior&lt;/strong&gt;. PWAs can automatically update which
reduces the amount of out-of-date clients in the wild. We were able to push out breaking backend
changes with a very short amount of migration time for clients.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easily integrated with first- and third-party apps.&lt;/strong&gt; Such integrations were a requirement
for the app. With a PWA it often meant simply opening a URL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Removed the friction of installing an app.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;framework&quot;&gt;Our framework &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#framework&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For Bulletin, we used &lt;a href=&quot;https://www.polymer-project.org/&quot; rel=&quot;noopener&quot;&gt;Polymer&lt;/a&gt;, but any modern, well-supported
framework will work.&lt;/p&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;What we learned about service workers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#lessons-learned&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can&#39;t have a PWA without a &lt;a href=&quot;https://developer.chrome.com/docs/workbox/service-worker-overview/&quot; rel=&quot;noopener&quot;&gt;service
worker&lt;/a&gt;. Service workers
give you a lot of power, such as advanced caching strategies, offline capabilities, background sync,
etc. While service workers do add some complexity, we found that their benefits outweighed the added
complexity.&lt;/p&gt;
&lt;h3 id=&quot;generate&quot;&gt;Generate it if you can &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#generate&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Avoid writing a service worker script by hand. Writing service workers by hand requires manually
managing cached resources and rewriting logic that is common to most service workers libraries, such
as &lt;a href=&quot;https://developer.chrome.com/docs/workbox/&quot; rel=&quot;noopener&quot;&gt;Workbox&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Having said that, due to our internal tech stack we could not use a library to generate and manage
our service worker. Our learnings below will at times reflect that. Go to &lt;a href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#pitfalls&quot;&gt;Pitfalls for
non-generated service workers&lt;/a&gt; to read more.&lt;/p&gt;
&lt;h3 id=&quot;libraries&quot;&gt;Not all libraries are service-worker-compatible &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#libraries&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some JS libraries make assumptions that don&#39;t work as expected when run by a service worker. For
instance, assuming &lt;code&gt;window&lt;/code&gt; or &lt;code&gt;document&lt;/code&gt; are available, or using an API not available to service
workers (&lt;code&gt;XMLHttpRequest&lt;/code&gt;, local storage, etc). Make sure any critical libraries you need for your
application are service-worker compatible. For this particular PWA, we wanted to use
&lt;a href=&quot;https://github.com/google/google-api-javascript-client&quot; rel=&quot;noopener&quot;&gt;gapi.js&lt;/a&gt; for authentication, but were
unable to because it did not support service workers. Library authors should also reduce or remove
unnecessary assumptions about the JavaScript context where possible to support service worker use
cases, such as by avoiding service worker-incompatible APIs and &lt;a href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#global-state&quot;&gt;avoiding global
state&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;idb&quot;&gt;Avoid accessing IndexedDB during initialization &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#idb&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Don&#39;t read &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/IndexedDB_API&quot; rel=&quot;noopener&quot;&gt;IndexedDB&lt;/a&gt; when
initializing your service worker script, or else you can get into this undesired situation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User has web app with IndexedDB (IDB) version N&lt;/li&gt;
&lt;li&gt;New web app is pushed with IDB version N+1&lt;/li&gt;
&lt;li&gt;User visits PWA, which triggers download of new service worker&lt;/li&gt;
&lt;li&gt;New service worker reads from IDB before registering &lt;code&gt;install&lt;/code&gt; event handler, triggering an
IDB upgrade cycle to go from N to N+1&lt;/li&gt;
&lt;li&gt;Since user has old client with version N, service worker upgrade process hangs as active
connections are still open to the old version of the database&lt;/li&gt;
&lt;li&gt;Service worker hangs, and never installs&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In our case, the cache was invalidated on service worker install, so if the service worker never
installed, users never received the updated app.&lt;/p&gt;
&lt;h3 id=&quot;resilient&quot;&gt;Make it resilient &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#resilient&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Though service worker scripts run in the background, they can also be terminated at any time, even
when in the middle of I/O operations (network, IDB, etc). Any long-running process should be
resumable at any point.&lt;/p&gt;
&lt;p&gt;In the case of a sync process that uploaded large files to the server and saved to IDB, our solution
for interrupted partial uploads was to take advantage of our internal upload library&#39;s resumable
system, saving the resumable upload URL to IDB prior to uploading, and using that URL to resume an
upload if it did not complete the first time around. Also before any long running I/O operation, the
state was saved to IDB to indicate where in the process we were for each record.&lt;/p&gt;
&lt;h3 id=&quot;global-state&quot;&gt;Don&#39;t depend on global state &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#global-state&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Because service workers exist in a different context, many symbols you might expect to exist are not
present. A lot of our code ran in both a &lt;code&gt;window&lt;/code&gt; context, as well as a service worker context (such
as logging, flags, syncing, etc.). Code needs to be defensive about the services it uses, such as
local storage or cookies. You can use
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/globalThis&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;globalThis&lt;/code&gt;&lt;/a&gt;
to refer to the global object in a manner which will work across all contexts. Also use data stored
in global variables sparingly, as there is no guarantee as to when the script will be terminated and
the state evicted.&lt;/p&gt;
&lt;h3 id=&quot;local-development&quot;&gt;Local development &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#local-development&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A major component of service workers is caching resources locally. However, during development this
is the exact &lt;em&gt;opposite&lt;/em&gt; of what you want, particularly when updates are done lazily. You still want
the server worker installed so you can debug problems with it or work with other APIs like
background sync, or notifications. On Chrome you can achieve this through Chrome DevTools by
enabling the &lt;strong&gt;Bypass for network&lt;/strong&gt; checkbox (&lt;strong&gt;Application&lt;/strong&gt; panel &amp;gt; &lt;strong&gt;Service workers&lt;/strong&gt; pane) in
addition to enabling the &lt;strong&gt;Disable cache&lt;/strong&gt; checkbox in the &lt;strong&gt;Network&lt;/strong&gt; panel in order to also
disable the memory cache. In order to cover more browsers, we opted for a different solution by
including a flag to disable caching in our service worker which is enabled by default on developer
builds. This ensures that devs always get their most recent changes without any caching issues. It&#39;s
important to include the &lt;code&gt;Cache-Control: no-cache&lt;/code&gt; header as well to &lt;a href=&quot;https://web.dev/http-cache/#unversioned-urls&quot;&gt;prevent the browser from
caching any assets&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;lighthouse&quot;&gt;Lighthouse &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#lighthouse&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/overview/&quot; rel=&quot;noopener&quot;&gt;Lighthouse&lt;/a&gt; provides a number of debugging
tools useful for PWAs. It scans a site and generates reports covering PWAs, performance,
accessibility, SEO, and other best practices.
We recommend &lt;a href=&quot;https://github.com/GoogleChrome/lighthouse-ci&quot; rel=&quot;noopener&quot;&gt;running Lighthouse on continuous
integration&lt;/a&gt; to alert you if you break one of the
criteria to be a PWA. This actually happened to us once, where the service worker wasn&#39;t installing
and we didn&#39;t realize it before a production push. Having Lighthouse as part of our CI would have
prevented that.&lt;/p&gt;
&lt;h3 id=&quot;continuous-delivery&quot;&gt;Embrace continuous delivery &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#continuous-delivery&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Because service workers can automatically update, users lack the ability to limit upgrades. This
significantly reduces the amount of out-of-date clients in the wild. When the user opened our app,
the service worker would serve the old client while it lazily downloaded the new client. Once the
new client downloaded, it would prompt the user to refresh the page to access new features. Even if
the user ignored this request, the next time they refreshed the page they would receive the new
version of the client. As a result, it is quite difficult for a user to refuse updates in the same
way they can for iOS/Android apps.&lt;/p&gt;
&lt;p&gt;We were able to push out breaking backend changes with a very short amount of migration time for
clients. Typically, we would give a month for users to update to newer clients before making
breaking changes. Since the app would serve while stale, it was actually possible for older clients
to exist in the wild if the user had not opened the app for a long time. On iOS, service workers are
&lt;a href=&quot;https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/#post-10218:~:text=7%2DDay%20Cap%20on%20All%20Script%2DWriteable%20Storage&quot; rel=&quot;noopener&quot;&gt;evicted after a couple weeks&lt;/a&gt;
so this case does not happen. For Android, this problem could be mitigated by not serving while
stale, or manually expiring the content after a few weeks. In practice, we never encountered
problems from stale clients. How strict a given team wants to be here is up to their specific use
case, but PWAs provide significantly more flexibility than iOS/Android apps.&lt;/p&gt;
&lt;h3 id=&quot;cookies&quot;&gt;Getting cookie values in a service worker &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#cookies&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes it is necessary to access cookie values in a service worker context. In our case, we
needed to access cookie values to generate a token to authenticate first-party API requests. In a
service worker, synchronous APIs such as &lt;code&gt;document.cookies&lt;/code&gt; are not available. You can always send a
message to active (windowed) clients from the service worker to request the cookie values, though
it&#39;s possible for the service worker to run in the background without any windowed clients
available, such as during a background sync. To work around this, we created an endpoint on our
frontend server that simply echoed the cookie value back to the client. The service worker made a
network request to this endpoint and read the response to get the cookie values.&lt;/p&gt;
&lt;p&gt;With the release of the
&lt;a href=&quot;https://developer.chrome.com/blog/asynchronous-access-to-http-cookies/&quot; rel=&quot;noopener&quot;&gt;Cookie Store API&lt;/a&gt;,
this workaround should no longer be necessary for browsers that support it, as it provides
asynchronous access to browser cookies and can be used directly by the service worker.&lt;/p&gt;
&lt;h2 id=&quot;pitfalls&quot;&gt;Pitfalls for non-generated service workers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#pitfalls&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;regeneration&quot;&gt;Ensure service worker script changes if any static cached file changes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#regeneration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A common PWA pattern is for a service worker to install all static application files during its
&lt;code&gt;install&lt;/code&gt; phase, which enables clients to hit the Cache Storage API cache directly for all
subsequent visits . Service workers are only installed when the browser detects that the service
worker script has changed in some way, so we had to ensure the service worker script file itself
changed in some way when a cached file changed. We did this manually by embedding a hash of the
static resource fileset within our service worker script, so every release produced a distinct
service worker JavaScript file. Service worker libraries like
&lt;a href=&quot;https://developer.chrome.com/docs/workbox/&quot; rel=&quot;noopener&quot;&gt;Workbox&lt;/a&gt; automate this process for you.&lt;/p&gt;
&lt;h3 id=&quot;unit-testing&quot;&gt;Unit testing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#unit-testing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Service worker APIs function by adding event listeners to the global object. For example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;fetch&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;evt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;respondWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/foo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This can be a pain to test because you need to mock the event trigger, the event object, wait for
the &lt;code&gt;respondWith()&lt;/code&gt; callback, and then await the promise, before finally asserting on the result. An
easier way to structure this is to delegate all implementation to another file, which is more easily
tested.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; fetchHandler &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./fetch_handler.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;fetch&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;evt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;respondWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;evt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Due to the difficulties of unit testing a service worker script, we kept the core service worker
script as bare-bones as possible, splitting most of the implementation into other modules. Since
those files were just standard JS modules, they could be more easily unit tested with standard test
libraries.&lt;/p&gt;
&lt;h2 id=&quot;stay-tuned&quot;&gt;Stay tuned for parts 2 and 3 &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/building-a-pwa-at-google-part-1/#stay-tuned&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In parts 2 and 3 of this series we&#39;ll talk about media management and iOS-specific issues. If you
want to ask us more about building a PWA at Google, visit our author profiles to find out
how to contact us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/authors/joelriley&quot;&gt;Joel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/authors/douglasparker&quot;&gt;Douglas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/authors/msdikla&quot;&gt;Dikla&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Joel Riley</name>
    </author><author>
      <name>Douglas Parker</name>
    </author><author>
      <name>Dikla Cohen</name>
    </author>
  </entry>
  
  <entry>
    <title>Relating site speed and business metrics</title>
    <link href="https://web.dev/site-speed-and-business-metrics/"/>
    <updated>2020-07-17T00:00:00Z</updated>
    <id>https://web.dev/site-speed-and-business-metrics/</id>
    <content type="html" mode="escaped">&lt;p&gt;Over the last few years it has been well established that site speed performance
is a significant part of the user experience and that improving it benefits
different business metrics such as conversion rates and bounce rates. Multiple
articles and case studies have been published to back this up, including
Cloudflare&#39;s &lt;a href=&quot;https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/&quot; rel=&quot;noopener&quot;&gt;How Website Performance Affects Conversion
Rates&lt;/a&gt;,
Deloitte&#39;s &lt;a href=&quot;https://www2.deloitte.com/ie/en/pages/consulting/articles/milliseconds-make-millions.html&quot; rel=&quot;noopener&quot;&gt;Milliseconds Make
Millions&lt;/a&gt;,
and &lt;a href=&quot;https://web.dev/shopping-for-speed-on-ebay/&quot;&gt;Shopping for Speed on eBay.com&lt;/a&gt;, to name a
few.&lt;/p&gt;
&lt;p&gt;Even though the case for speed is clear, many companies still struggle with
prioritizing work that will improve their site speed since they do not know
exactly how it affects &lt;strong&gt;their&lt;/strong&gt; users and as a result &lt;strong&gt;their&lt;/strong&gt; business.&lt;/p&gt;
&lt;p&gt;In the absence of data, it is easy to delay site speed work and focus on other
tasks. A common scenario is having some people in the company recognize the
importance of site speed and yet not be able to build a case for it and convince
multiple stakeholders to invest accordingly.&lt;/p&gt;
&lt;p&gt;This article provides high-level guidance on how to leverage A/B testing to
evaluate the impact of site speed on business metrics therefore enabling more
effective decision-making on the matter.&lt;/p&gt;
&lt;h2 id=&quot;step-1-pick-a-page-to-ab-test&quot;&gt;Step 1: Pick a page to A/B test &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#step-1-pick-a-page-to-ab-test&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your aim is to test the hypothesis that page speed relates to your business
metrics. For simplicity&#39;s sake, you can initially limit yourself to identifying
a single page for analysis. Future work can expand to multiple pages of the same
type to verify findings, and then to other areas of the site. Some suggestions
for where to start are provided at the bottom of this step. Several requirements
drive the page selection process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The A/B test should only be run on the devices of mobile users. Globally,
the partner sites we assist see an average of &lt;a href=&quot;https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/worldwide&quot; rel=&quot;noopener&quot;&gt;more than
50%&lt;/a&gt;
(and growing!) of their traffic coming from mobile, but this can increase
significantly based on
&lt;a href=&quot;https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/india&quot; rel=&quot;noopener&quot;&gt;region&lt;/a&gt;
and
&lt;a href=&quot;https://www.salecycle.com/blog/stats/2019-ecommerce-year-in-review-infographic/&quot; rel=&quot;noopener&quot;&gt;vertical&lt;/a&gt;.
Mobile devices are more sensitive to slower websites due to processing and
memory constraints and less stable networks. Also, on-the-go usage patterns
mean expectations for speed are higher.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The page you choose for testing should be an important part of your
conversion funnel. Every site has a different purpose, so every site tracks
different success metrics. These metrics are usually related to a user
journey which is analyzed using a funnel. For example, users on an
e-commerce website will have to navigate through a home page, category
pages, product pages, and a checkout page to complete a purchase. If you&#39;re
optimizing for conversions, one of those pages would be a good candidate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The page should have a singular purpose. Unless your site has a very
specific mission, it&#39;s usually best to avoid using the homepage for your
test. Many commercial sites&#39; homepages are portals to a wide variety of
functionality that will make your analysis noisy. For example, if you&#39;re
optimizing for pageviews per session on a news site, it might be best to
exclude the non-commercial portions of the site and focus on monetized
sections and articles.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The page chosen should get enough traffic so that you don&#39;t have to wait
long before getting a statistically significant result.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The selected page should be relatively slow. In fact, the slower the better.
This not only means that you will likely have an easier time improving the
page, it also means that the data should be much clearer. You can do a quick
scan through your &lt;a href=&quot;https://support.google.com/analytics/answer/1205784&quot; rel=&quot;noopener&quot;&gt;Google Analytics Speed
Report&lt;/a&gt; or &lt;a href=&quot;https://support.google.com/webmasters/answer/9205520&quot; rel=&quot;noopener&quot;&gt;Search
Console Core Web Vitals
report&lt;/a&gt; to see which
of your pages are slowest.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The page should be relatively stable. Don&#39;t update pages (anything that
would impact business metrics) until the test is complete. The fewer
external factors there are to consider, the cleaner the analysis will be.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using the above as a guide it should be a bit more clear which pages are good
candidates for your test. Ad landing pages are also a good choice, because
you&#39;re likely to have built-in business metrics, A/B testing,  and analysis at
your disposal. In case you&#39;re still unsure, here are some ideas per vertical:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Content Websites: sections, articles&lt;/li&gt;
&lt;li&gt;Storefronts: category pages, product pages&lt;/li&gt;
&lt;li&gt;Media Players: video discovery/search pages, video play page&lt;/li&gt;
&lt;li&gt;Services &amp;amp; Discovery (travel, rental cars, service registration, etc.):
initial form-entry page&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;step-2-measure-performance&quot;&gt;Step 2: Measure performance &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#step-2-measure-performance&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are two general ways to measure metrics: &lt;a href=&quot;https://web.dev/user-centric-performance-metrics/#how-metrics-are-measured&quot;&gt;in the lab and in the
field&lt;/a&gt;. We
personally have found measuring metrics in the field (also known as Real User
Monitoring (RUM)) to be more useful because it reflects the experience of real
users. Examples of libraries and services that can help you report RUM data
include &lt;a href=&quot;https://zizzamia.github.io/perfume/&quot; rel=&quot;noopener&quot;&gt;Perfume&lt;/a&gt;, &lt;a href=&quot;https://firebase.google.com/docs/perf-mon&quot; rel=&quot;noopener&quot;&gt;Firebase Performance
Monitoring&lt;/a&gt;, and &lt;a href=&quot;https://developers.google.com/analytics/devguides/collection/analyticsjs/events&quot; rel=&quot;noopener&quot;&gt;Google Analytics
Events&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are &lt;a href=&quot;https://web.dev/user-centric-performance-metrics/&quot;&gt;many metrics to choose from&lt;/a&gt;
because they aim to capture different aspects of the user experience. Remember
that your goal is to eventually determine if there&#39;s a direct correlation
between your speed and business metrics, so it might be useful to track a few
speed metrics in order to determine which one has the strongest correlation with
your business success. In general we recommend starting with the &lt;a href=&quot;https://web.dev/vitals/#core-web-vitals&quot;&gt;Core Web
Vitals&lt;/a&gt;. The
&lt;a href=&quot;https://github.com/GoogleChrome/web-vitals&quot; rel=&quot;noopener&quot;&gt;web-vitals.js&lt;/a&gt; library can help you
measure some of the Core Web Vitals in the field, although note that &lt;a href=&quot;https://github.com/GoogleChrome/web-vitals#browser-support&quot; rel=&quot;noopener&quot;&gt;browser
support isn&#39;t 100%&lt;/a&gt;.
Beyond the Core Web Vitals, the &lt;a href=&quot;https://web.dev/vitals/#other-web-vitals&quot;&gt;Other Web Vitals&lt;/a&gt;
are also worth checking out. You can also define &lt;a href=&quot;https://web.dev/user-centric-performance-metrics/#custom-metrics&quot;&gt;custom
metrics&lt;/a&gt;, such as &amp;quot;Time To
First Ad Click&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;step-3-create-speed-performance-variants&quot;&gt;Step 3: Create speed performance variants &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#step-3-create-speed-performance-variants&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this stage you will implement changes to create a faster version of the page
to be tested against the current version.&lt;/p&gt;
&lt;p&gt;A couple of things to keep in mind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Avoid making any changes to the UI or UX. Aside from one page being faster
than the other, changes must be invisible to users.&lt;/li&gt;
&lt;li&gt;Measuring is also a key aspect of this stage. While developing, lab testing
tools such as Lighthouse should be used to indicate the effect your changes
have on performance. Keep in mind that changes to one metric can often
influence another. Once the pages are live, stick to RUM for a more accurate
evaluation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Creating performance variants can be done in different ways. For the purpose of
the test, you would want to do so as simply as possible. Below are a few
options.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create a faster page&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a tool like &lt;a href=&quot;https://squoosh.app/&quot; rel=&quot;noopener&quot;&gt;Squoosh&lt;/a&gt; to manually optimize the
images on your test page&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/docs/devtools/coverage/&quot; rel=&quot;noopener&quot;&gt;Use DevTools code
coverage&lt;/a&gt;
to manually eliminate unused JavaScript or CSS just for that one page&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/efficiently-load-third-party-javascript/&quot;&gt;Efficiently load third-party
scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use a tool like &lt;a href=&quot;https://github.com/addyosmani/critical&quot; rel=&quot;noopener&quot;&gt;Critical&lt;/a&gt; to break
out and inline critical CSS&lt;/li&gt;
&lt;li&gt;Remove non-critical JavaScript code that does not impact the user experience
and which you can do without for the purpose of the test (for example,
certain third-party libraries)&lt;/li&gt;
&lt;li&gt;Implement &lt;a href=&quot;https://web.dev/browser-level-image-lazy-loading/&quot;&gt;browser-level lazy loading&lt;/a&gt; which isn&#39;t supported
by all browsers but may still improve performance significantly where
supported&lt;/li&gt;
&lt;li&gt;Remove non-critical analytics tags or load them asynchronously&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additional optimizations to consider can be found at &lt;a href=&quot;https://web.dev/fast/&quot;&gt;Fast load times&lt;/a&gt;
and &lt;a href=&quot;https://www.smashingmagazine.com/2020/01/front-end-performance-checklist-2020-pdf-pages/&quot; rel=&quot;noopener&quot;&gt;Frontend Performance
Checklist&lt;/a&gt;.
You can also use &lt;a href=&quot;https://pagespeed.web.dev/&quot; rel=&quot;noopener&quot;&gt;PageSpeed
Insights&lt;/a&gt; to run
Lighthouse, which identifies opportunities to improve performance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Slow down the page&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This may be the easiest way to create variants and can be achieved by adding a
simple script, slowing down server response times, loading larger images, etc.
The Financial Times opted for this option when testing how performance impacted
their business metrics: see &lt;a href=&quot;https://medium.com/ft-product-technology/a-faster-ft-com-10e7c077dc1c&quot; rel=&quot;noopener&quot;&gt;A faster
FT.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Speed up page load&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For cases where the test page (let&#39;s say a product detail page) is mostly linked
out from a different page (let&#39;s say the homepage),
&lt;a href=&quot;https://web.dev/link-prefetch/&quot;&gt;prefetching&lt;/a&gt; or
&lt;a href=&quot;https://developer.chrome.com/blog/nostate-prefetch&quot; rel=&quot;noopener&quot;&gt;prerendering&lt;/a&gt;
the product page directly from the homepage for the test group will speed up the
subsequent load of the page. Note that in this case the A/B test split (step 4)
is done on the homepage. In addition, all of this may slow down the first page
so be sure to measure that and take it under consideration when analyzing the
test results (step 5).&lt;/p&gt;
&lt;h2 id=&quot;step-4-create-an-ab-test&quot;&gt;Step 4: Create an A/B test &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#step-4-create-an-ab-test&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you have two versions of the same page where one is faster than the other,
the next step is to split traffic to measure impact. In general there are many
techniques and tools to perform A/B tests, but be aware that not all methods are
well suited to measure speed performance impact.&lt;/p&gt;
&lt;p&gt;If you&#39;re using an A/B testing tool like
&lt;a href=&quot;https://www.optimizely.com/de/&quot; rel=&quot;noopener&quot;&gt;Optimizely&lt;/a&gt; or
&lt;a href=&quot;https://optimize.google.com/optimize/home/&quot; rel=&quot;noopener&quot;&gt;Optimize&lt;/a&gt; we strongly recommend
setting up a server-side test instead of a client-side test, as client side A/B
testing often works by hiding page content until the experiment is loaded, which
would mean the A/B testing itself would skew the metrics you wanted to measure.
If you can only do client-side testing, consider setting up the experiment on a
different page and changing the link outs to your test page to split the
traffic. This way the test page itself isn&#39;t dragged down by the client-side
test.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
  Example
&lt;/summary&gt;
&lt;p&gt;Example of AB testing  performance changes on a given product detail page (PDP)
via server-side testing:&lt;/p&gt;
&lt;img alt=&quot;Server side testing diagram&quot; decoding=&quot;async&quot; height=&quot;230&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/xQWUEAAfowEg0wjmVsrm.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The request goes to the backend, which distributes the users to the two
different versions of the page. While this is in general a good setup, it often
needs IT resources to set up the server-side split.&lt;/p&gt;
&lt;p&gt;Here is an example of a client side testing setup, using the prior page (the
homepage in the diagram below) to run the testing JavaScript:&lt;/p&gt;
&lt;img alt=&quot;Client side testing diagram&quot; decoding=&quot;async&quot; height=&quot;337&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/tX6XL3IoZBVdJXCPAE1E.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The testing JavaScript manipulates the outgoing link to give the two test groups
of users links to the two versions of the PDP in question. This is easy to setup
and maintain through common A/B testing tools like Optimizely or Optimize and
does not influence the performance test because the testing JavaScript runs on a
different page.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;Alternatively, you can pick two pages which behave and perform very similarly
(for example, for two very similar products). Apply your changes to one of them
and then compare the difference in metrics over time. This will mean you&#39;re not
conducting a proper A/B test, yet it can still be quite insightful.&lt;/p&gt;
&lt;p&gt;In case your test page is used as a landing page for ad campaigns, it can be
handy to use your ad network&#39;s built-in A/B testing tools, like &lt;a href=&quot;https://www.facebook.com/business/help/1159714227408868&quot; rel=&quot;noopener&quot;&gt;Facebook Ads
Split Test&lt;/a&gt; or &lt;a href=&quot;https://support.google.com/google-ads/answer/6318732?hl=en&quot; rel=&quot;noopener&quot;&gt;Google
Ads Drafts &amp;amp;
Experiments&lt;/a&gt;. If
that&#39;s not an option, you can use two campaigns with the same setup, and set
different landing pages as targets.&lt;/p&gt;
&lt;h2 id=&quot;step-5-analyze-ab-test&quot;&gt;Step 5: Analyze A/B test &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#step-5-analyze-ab-test&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After you&#39;ve run your test for long enough and have enough data to feel
confident about the results, it&#39;s time to put it all together and run an
analysis. How you do that really depends on how the test has run, so let&#39;s go
through the options.&lt;/p&gt;
&lt;p&gt;If your test was run on ad landing pages using the above-mentioned tools,
analysis should be as straightforward as reading a result. If you&#39;re using
Google&#39;s Drafts &amp;amp; Experiments, take a look at the comparison using the
&lt;a href=&quot;https://support.google.com/google-ads/answer/6318747?hl=en&quot; rel=&quot;noopener&quot;&gt;ScoreCard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Platforms like Optimizely or Optimize also offer &lt;a href=&quot;https://support.google.com/optimize/answer/6218117?hl=en&quot; rel=&quot;noopener&quot;&gt;easy
ways&lt;/a&gt; to interpret the
results and determine how much of an impact speed has on your pages.&lt;/p&gt;
&lt;p&gt;If you&#39;re using Google Analytics or a similar tool, you will have to pull
together the report yourself. Luckily, Google Analytics makes it pretty easy to
build &lt;a href=&quot;https://support.google.com/analytics/answer/1151300?hl=en&quot; rel=&quot;noopener&quot;&gt;custom
reports&lt;/a&gt;, so that&#39;s
where you should start. If you&#39;ve sent speed data to Google Analytics using a
custom dimension, check out the &lt;a href=&quot;https://support.google.com/analytics/answer/2709828?hl=en#reporting&quot; rel=&quot;noopener&quot;&gt;Reporting
guide&lt;/a&gt; to
learn how to set those up and include them in your custom reports. Make sure
your report covers the date of the experiment and is configured to display both
variants. What should go in this report?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Primarily, you need to include the business metrics that you most care
about: conversions, page views, ads viewed, conversion rate, e-commerce
metrics, click-through rate, etc.&lt;/li&gt;
&lt;li&gt;Additionally, other standard page metrics that also make a good case for
improving site speed are bounce rate, average session duration, and exit
percentage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may also need to filter for mobile and make sure to &lt;a href=&quot;https://support.google.com/analytics/thread/16422940?hl=en&amp;amp;msgid=16485536&quot; rel=&quot;noopener&quot;&gt;exclude bots and other
non-user
traffic&lt;/a&gt;.
More advanced analysis would also filter by region, networks, devices, traffic
source, and user profiles and types, such as new users versus repeat visitors.
Each group of users may be more or less sensitive to slower speeds and
identifying these is also quite helpful.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.google.com/looker-studio/answer/6283323?hl=en&quot; rel=&quot;noopener&quot;&gt;Looker Studio&lt;/a&gt; (formerly Data Studio) or
other data visualization tools make it easy to integrate various data sources
including Google Analytics. This makes it easy to conduct analysis, and also
create dashboards that are shareable with the many stakeholders involved in
running a modern website for further buy-in. For example, the Guardian created
an &lt;a href=&quot;https://www.theguardian.com/info/developer-blog/2017/mar/06/empowering-our-editorial-teams-to-impact-page-performance&quot; rel=&quot;noopener&quot;&gt;automated alert
system&lt;/a&gt;
that warned the editorial team when recently published content crossed their
page size or speed thresholds and was likely to result in unsatisfied users.&lt;/p&gt;
&lt;h2 id=&quot;step-6-draw-conclusions-and-decide-on-next-steps&quot;&gt;Step 6: Draw conclusions and decide on next steps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#step-6-draw-conclusions-and-decide-on-next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you have data that connects performance and business metrics, you can
examine the results and start to draw conclusions.&lt;/p&gt;
&lt;p&gt;If you can clearly see a correlation between improving performance and improving
business metrics, summarize the results and report them across the company. Now
that you can talk about speed performance in a &amp;quot;business language&amp;quot; you are more
likely to grab the attention of different stakeholders and place site speed
performance on everyone&#39;s radar. The next step is to set &lt;a href=&quot;https://web.dev/your-first-performance-budget/&quot;&gt;performance
budgets&lt;/a&gt; based on the results, and plan out
work to meet those budgets. Since you know the value such work will provide,
you&#39;ll be able to prioritize accordingly.&lt;/p&gt;
&lt;p&gt;If you can&#39;t identify a correlation, take a look at the caveats below and assess
whether similar tests should be run elsewhere on the site (for example, through
the entire purchase funnel or on a different type of page).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Caveats&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There might be several reasons for not finding significant correlation between
site speed metrics and business metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The page chosen does not have enough influence on the business metrics
you&#39;re examining. For example, a faster product page may not have a big
effect on conversion rates if the checkout page is very unfriendly or slow.
Consider looking at more relevant metrics such as bounce rates,
add-to-basket rates or any other metric that is more directly connected to
the page you&#39;re testing.&lt;/li&gt;
&lt;li&gt;The difference in speed is not significant enough between the two versions.
This should be evaluated according to the RUM metrics you&#39;re measuring.&lt;/li&gt;
&lt;li&gt;There&#39;s a fault with the A/B testing mechanism. Traffic might not be
distributed properly or analytics not reported correctly. In order to rule
this out, consider running an A/A test where you test the same version of a
page using the same testing mechanism and ensure there&#39;s no difference in
results when doing so.&lt;/li&gt;
&lt;li&gt;Site speed really doesn&#39;t influence your business metrics. This is rare but
can occur in cases where your target market is less sensitive to speed (e.g.
the site is mostly accessed from powerful devices on a strong network) or
user demand is very high and choice is limited (e.g. a ticketing service
that exclusively sells tickets for high-demand shows). Note that this does
not mean that a faster site will not improve user experience and as a result
&lt;a href=&quot;https://www.thinkwithgoogle.com/intl/en-154/marketing-collections/mobile/why-mobile-speed-means-loyal-customers-and-how-make-it-happen/&quot; rel=&quot;noopener&quot;&gt;affect brand
reputation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/site-speed-and-business-metrics/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it is tempting to launch speed optimizations across the entire site, it is
usually more beneficial in the long run to first understand what it means to
your users and your company to have a faster website. It is the difference
between saying &amp;quot;we improved FCP by 1.5 seconds&amp;quot; and &amp;quot;we improved FCP by 1.5
seconds and that improved our conversion rates by 5%&amp;quot;. This will allow you to
prioritize further work, get buy-in from different stakeholders and &lt;a href=&quot;https://web.dev/fixing-website-speed-cross-functionally/&quot;&gt;make site
speed performance a company-wide
effort&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Dikla Cohen</name>
    </author><author>
      <name>Martin Schierle</name>
    </author><author>
      <name>Bart Jarochowski</name>
    </author>
  </entry>
</feed>
