Mainline Menswear implementa PWA e tem aumento de 55% na taxa de conversão

A Mainline é uma loja de roupas on-line que oferece as maiores marcas de estilistas do setor de moda. A empresa sediada no Reino Unido confia na equipe de especialistas internos, combinados estrategicamente com os principais parceiros, para fornecer uma experiência de compra simples para todos. Com presença de mercado em mais de 100 países por meio de sete sites territoriais personalizados e um app, a Mainline vai continuar garantindo que a oferta de e-commerce seja rival da concorrência.

Desafio

O objetivo da Mainline Menswear era complementar o atual site otimizado para dispositivos móveis com recursos progressivos que se aderissem à nossa visão "para dispositivos móveis", concentrando-se no design e na funcionalidade compatíveis com dispositivos móveis, considerando um mercado de smartphones em crescimento.

Solução

O objetivo era criar e lançar um PWA que complementasse a versão original compatível com dispositivos móveis do site da Mainline Menswear e, em seguida, comparar as estatísticas com o app híbrido para dispositivos móveis, disponível no Android e no iOS.

Depois que o app foi lançado e estava sendo usado por uma pequena seção de usuários masculinos da Mainline, eles conseguiram determinar a diferença nas principais estatísticas entre PWA, app e Web.

A abordagem que a Mainline adotou ao converter o site em um PWA foi garantir que o framework selecionado para o site (Nuxt.js, usando Vue.js) fosse preparado para o futuro e permitisse aproveitar a tecnologia da Web rápida.

Resultados

139%

Mais páginas por sessão no PWA do que na Web.

161%

Sessões mais longas no PWA em comparação com a Web.

10%

Menor taxa de rejeição no PWA em comparação com a Web

12,5%

de aumento no valor médio do pedido no PWA em comparação com a Web

55%

de aumento na taxa de conversão no PWA em comparação com a Web.

243%

de aumento na receita por sessão no PWA em comparação com a Web.

Aprofundamento técnico

A Mainline Menswear está usando o framework Nuxt.js para agrupar e renderizar o site, que é um aplicativo de página única (SPA).

Como gerar um arquivo de service worker

Para gerar o service worker, a Mainline Menswear adicionou a configuração usando uma implementação personalizada do módulo nuxt/pwa Workbox.

Eles bifurcaram o módulo nuxt/pwa para permitir que a equipe adicionasse mais personalizações ao arquivo do service worker que não conseguiam ou tinham problemas ao usar a versão padrão. Uma dessas otimizações foi em torno da funcionalidade off-line do site, como, por exemplo, veicular uma página off-line padrão e coletar análises off-line.

Anatomia do manifesto do app da Web

A equipe gerou um manifesto com ícones de diferentes tamanhos de ícones de apps para dispositivos móveis e outros detalhes de apps da Web, como name, description e theme_color:

{
  "name": "Mainline Menswear",
  "short_name": "MMW",
  "description": "Shop mens designer clothes with Mainline Menswear. Famous brands including Hugo Boss, Adidas, and Emporio Armani.",
  "icons": [
    {
      "src": "/_nuxt/icons/icon_512.c2336e.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#107cbb"
}

Depois de instalado, o app da Web pode ser iniciado na tela inicial sem que o navegador atrapalhe. Para isso, adicione o parâmetro display ao arquivo de manifesto do app da Web:

{
  "display": "standalone"
}

Por último, mas não menos importante, agora a empresa pode rastrear facilmente quantos usuários estão visitando o app da Web pela tela inicial simplesmente anexando um parâmetro utm_source no campo start_url do manifesto:

{
  "start_url": "/?utm_source=pwa"
}

Armazenamento em cache no ambiente de execução para navegações mais rápidas

O armazenamento em cache para apps da Web é necessário para otimizar a velocidade da página e fornecer uma melhor experiência para usuários recorrentes.

Há algumas abordagens diferentes para o armazenamento em cache na Web. A equipe está usando uma combinação de cache HTTP e API Cache para armazenar recursos em cache no lado do cliente.

A API Cache oferece à Mainline Menswear um controle mais preciso sobre os recursos em cache, permitindo aplicar estratégias complexas a cada tipo de arquivo. Embora tudo isso pareça complicado e difícil de configurar e manter, o Workbox oferece uma maneira fácil de declarar essas estratégias complexas e facilita a manutenção.

Armazenamento em cache de CSS e JS

A equipe optou por armazenar arquivos CSS e JS em cache e exibi-los nesse cache usando a estratégia StaleWhileRevalidate do Workbox. Essa estratégia permite veicular todos os arquivos CSS e JS do Nuxt rapidamente, o que aumenta significativamente o desempenho do site. Ao mesmo tempo, os arquivos são atualizados em segundo plano para a versão mais recente para a próxima visita:

/* sw.js */
workbox.routing.registerRoute(
  /\/_nuxt\/.*(?:js|css)$/,
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'css_js',
  }),
  'GET',
);

Como armazenar fontes do Google em cache

A estratégia de armazenamento em cache do Google Fonts depende de dois tipos de arquivo:

  • A folha de estilo que contém as declarações @font-face.
  • Os arquivos de fontes subjacentes (solicitados na folha de estilo mencionada acima).
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
  /https:\/\/fonts\.googleapis\.com\/*/,
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'google_fonts_stylesheets',
  }),
  'GET',
);

// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
  /https:\/\/fonts\.gstatic\.com\/*/,
  new workbox.strategies.CacheFirst({
    cacheName: 'google_fonts_webfonts',
    plugins: [
      new workbox.cacheableResponse.CacheableResponsePlugin({
        statuses: [0, 200],
      }),
      new workbox.expiration.ExpirationPlugin({
        maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
        maxEntries: 30,
      }),
    ],
  }),
  'GET',
);

Como armazenar imagens em cache

No caso das imagens, a Mainline Menswear decidiu escolher duas estratégias. A primeira estratégia se aplica a todas as imagens provenientes da CDN, que geralmente são imagens de produtos. As páginas têm muitas imagens, então eles estão conscientes de não ocupar muito do armazenamento do dispositivo dos usuários. Então, usando o Workbox, foi adicionada uma estratégia que é armazenar em cache imagens provenientes apenas da CDN com um máximo de 60 imagens usando ExpirationPlugin.

A 61a (mais recente) imagem solicitada substitui a primeira (mais antiga) para que no máximo 60 imagens de produtos sejam armazenadas em cache a qualquer momento.

workbox.routing.registerRoute(
  ({ url, request }) =>
    url.origin === 'https://mainline-menswear-res.cloudinary.com' &&
    request.destination === 'image',
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'product_images',
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        // Only cache 60 images.
        maxEntries: 60,
        purgeOnQuotaError: true,
      }),
    ],
  }),
);

A segunda estratégia de imagens processa o restante das imagens solicitadas pela origem. Essas imagens tendem a ser muito poucas e pequenas em toda a origem, mas, por questões de segurança, o número dessas imagens em cache também é limitado a 60.

workbox.routing.registerRoute(
  /\.(?:png|gif|jpg|jpeg|svg|webp)$/,
  new workbox.strategies.StaleWhileRevalidate({
    cacheName: 'images',
    plugins: [
      new workbox.expiration.ExpirationPlugin({
        // Only cache 60 images.
        maxEntries: 60,
        purgeOnQuotaError: true,
      }),
    ],
  }),
);

Fornecimento de funcionalidade off-line

A página off-line é pré-armazenada em cache logo após o service worker ser instalado e ativado. Isso é feito criando uma lista de todas as dependências off-line: o arquivo HTML off-line e um ícone SVG off-line.

const OFFLINE_HTML = '/offline/offline.html';
const PRECACHE = [
  { url: OFFLINE_HTML, revision: '70f044fda3e9647a98f084763ae2c32a' },
  { url: '/offline/offline.svg', revision: 'efe016c546d7ba9f20aefc0afa9fc74a' },
];

A lista de pré-cache é alimentada no Workbox, que cuida de todo o trabalho pesado de adicionar os URLs ao cache, verificar se há incompatibilidade de revisão, atualizar e disponibilizar os arquivos pré-armazenados em cache com uma estratégia CacheFirst.

workbox.precaching.precacheAndRoute(PRECACHE);

Como gerenciar navegações off-line

Depois que o service worker é ativado e a página off-line é pré-armazenada em cache, ela é usada para responder às solicitações de navegação off-line do usuário. Embora o app da Web da Mainline Menswear seja um SPA, a página off-line é mostrada somente depois que a página é atualizada, o usuário fecha e reabre a guia do navegador ou quando o app da Web é iniciado na tela inicial enquanto está off-line.

Para isso, a Mainline Menswear ofereceu um substituto para solicitações NavigationRoute com falha com a página off-line pré-armazenada em cache:

const htmlHandler = new workbox.strategies.NetworkOnly();
const navigationRoute = new workbox.routing.NavigationRoute(({ event }) => {
    const request = event.request;
    // A NavigationRoute matches navigation requests in the browser, i.e. requests for HTML
    return htmlHandler.handle({ event, request }).catch(() => caches.match(OFFLINE_HTML, {
        ignoreSearch: true
    }));
});
workbox.routing.registerRoute(navigationRoute);

Demonstração

Exemplo de página off-line em www.mainlinemenswear.co.uk.

Relatórios de instalações concluídas

Além do acompanhamento de inicialização da tela inicial (com "start_url": "/?utm_source=pwa" no manifesto do app da Web), o app da Web também registra instalações bem-sucedidas ao detectar o evento appinstalled em window:

window.addEventListener('appinstalled', (evt) => {
  ga('send', 'event', 'Install', 'Success');
});

A adição de recursos de PWA ao seu site melhora ainda mais a experiência dos clientes ao comprar com você, além de facilitar o lançamento de um app [específico da plataforma].

Andy Hoyle, diretor de desenvolvimento

Conclusão

Para saber mais sobre Progressive Web Apps e como criá-los, acesse a seção Progressive Web Apps em web.dev.

Para ler mais estudos de caso de Progressive Web Apps, navegue até a seção de estudos de caso.