Mainline Menswear implementa l'PWA e registra un aumento del 55% del tasso di conversione

Mainline è un rivenditore di abbigliamento online che offre i più grandi marchi di moda. L'azienda con sede nel Regno Unito si affida al proprio team di esperti interni, combinati strategicamente con i partner chiave, per fornire a tutti un'esperienza di acquisto fluida. Con una presenza sul mercato in oltre 100 paesi tramite sette siti web territoriali personalizzati e un'app, Mainline continuerà a garantire che l'offerta di e-commerce rivaleggia con la concorrenza.

Sfida

L'obiettivo di Mainline Menswear era quello di integrare l'attuale sito web ottimizzato per il mobile con funzionalità progressivamente conformi alla sua visione di "mobile first", concentrandosi su design e funzionalità ottimizzati per il mobile, tenendo presente il mercato degli smartphone in crescita.

Soluzione

L'obiettivo era creare e lanciare una PWA che completasse la versione originale ottimizzata per il mobile del sito web di Mainline Menswear, per poi confrontare le statistiche con l'app mobile ibrida, attualmente disponibile su Android e iOS.

Una volta che l'app è stata lanciata e utilizzata da un piccolo gruppo di utenti Mainline Menswear, sono stati in grado di determinare la differenza nelle statistiche chiave tra PWA, app e web.

L'approccio adottato da Mainline durante la conversione del suo sito web in PWA era di assicurarsi che il framework scelto per il sito web (Nuxt.js, utilizzando Vue.js) fosse a prova di futuro e di poter sfruttare la tecnologia web in rapida evoluzione.

Risultati

Il 139%

Più pagine per sessione nella PWA rispetto al web.

Il 161%

Durate delle sessioni più lunghe nella PWA rispetto al web.

10%

Riduzione della frequenza di rimbalzo nella PWA rispetto al web

12,5%

Valore medio degli ordini più elevato nella PWA rispetto al web

Il 55%

di aumento del tasso di conversione in PWA rispetto al web.

Il 243%

Aumento delle entrate per sessione nella PWA rispetto al web.

Approfondimento tecnico

Mainline Menswear utilizza il framework Nuuxt.js per raggruppare ed eseguire il rendering del proprio sito, che è una singola applicazione a pagina (SPA).

Generazione di un file del service worker

Per generare il service worker, Mainline Menswear ha aggiunto la configurazione tramite un'implementazione personalizzata del modulo nuxt/pwa Workbox.

Il motivo per cui hanno eseguito il fork del modulo nuxt/pwa è stato per consentire al team di aggiungere ulteriori personalizzazioni al file dei service worker che non sono riusciti a raggiungere o con cui non sono riusciti a utilizzare la versione standard. Una di queste ottimizzazioni riguarda la funzionalità offline del sito, ad esempio la pubblicazione di una pagina offline predefinita e la raccolta di dati e analisi offline.

Anatomia del manifest dell'app web

Il team ha generato un file manifest con icone per diverse dimensioni delle icone delle app mobile e altri dettagli delle app web come 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"
}

Una volta installata, l'app web può essere avviata dalla schermata Home senza che il browser ostacoli il browser. Per farlo, devi aggiungere il parametro display nel file manifest dell'app web:

{
  "display": "standalone"
}

Infine, ma non per importanza, l'azienda ora è in grado di monitorare facilmente quanti utenti visitano la sua applicazione web dalla schermata Home semplicemente aggiungendo un parametro utm_source nel campo start_url del file manifest:

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

Memorizzazione nella cache del runtime per navigazioni più veloci

La memorizzazione nella cache per le app web è fondamentale per ottimizzare la velocità delle pagine e offrire una migliore esperienza utente agli utenti di ritorno.

Per la memorizzazione nella cache sul web, esistono approcci diversi. Il team utilizza una combinazione della cache HTTP e dell'API Cache per la memorizzazione nella cache degli asset sul lato client.

L'API Cache offre a Mainline Menswear un controllo più preciso sugli asset memorizzati nella cache, consentendo di applicare strategie complesse a ogni tipo di file. Sebbene tutto questo sembri complicato e difficile da configurare e gestire, Workbox offre un modo semplice per dichiarare strategie così complesse e allevia il problema della manutenzione.

Memorizzazione nella cache di CSS e JS

Per i file CSS e JS, il team ha scelto di memorizzarli nella cache e pubblicarli nella cache utilizzando la strategia StaleWhileRevalidate Workbox. Questa strategia consente di pubblicare rapidamente tutti i file CSS e JS di Nuxt, il che aumenta notevolmente le prestazioni del sito. Allo stesso tempo, viene eseguito l'aggiornamento in background dei file alla versione più recente per la prossima visita:

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

Memorizza i caratteri Google nella cache

La strategia per la memorizzazione nella cache di Google Fonts dipende da due tipi di file:

  • Il foglio di stile che contiene le dichiarazioni @font-face.
  • I file dei caratteri sottostanti (richieste all'interno del foglio di stile indicato sopra).
// 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',
);

Memorizzazione nella cache delle immagini

Per quanto riguarda le immagini, Mainline Menswear ha deciso di adottare due strategie. La prima strategia si applica a tutte le immagini provenienti dalla rete CDN, che di solito sono immagini di prodotto. Le pagine sono piene di immagini, perciò sono consapevoli di non occupare troppo spazio di archiviazione sul dispositivo degli utenti. Tramite Workbox, ha aggiunto una strategia che memorizza nella cache le immagini provenienti solo dalla rete CDN con un massimo di 60 immagini utilizzando ExpirationPlugin.

La 61 (più recente) immagine richiesta sostituisce la prima (meno recente) immagine in modo che non vengano memorizzate nella cache più di 60 immagini prodotto in qualsiasi 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,
      }),
    ],
  }),
);

La seconda strategia gestisce il resto delle immagini richieste dall'origine. Queste immagini tendono a essere molto poche e piccole in tutta l'origine, ma per sicurezza, anche il numero di queste immagini memorizzate nella cache è limitato 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,
      }),
    ],
  }),
);

Fornisce funzionalità offline

La pagina offline viene pre-memorizzata nella cache subito dopo l'installazione e l'attivazione del service worker. Per farlo, crea un elenco di tutte le dipendenze offline: il file HTML offline e un'icona SVG offline.

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

L'elenco di preregistrazione viene quindi inserito in Workbox, che si occupa di tutte le attività legate all'aggiunta degli URL alla cache, al controllo di eventuali mancate corrispondenze delle revisioni, all'aggiornamento e alla pubblicazione dei file prememorizzati nella cache con una strategia CacheFirst.

workbox.precaching.precacheAndRoute(PRECACHE);

Gestione delle navigazioni offline

Una volta attivato il service worker e pre-cache la pagina offline, questa viene utilizzata per rispondere alle richieste di navigazione offline dell'utente. Sebbene l'app web di Mainline Menswear sia un'APS, la pagina offline viene visualizzata solo dopo che è stata ricaricata, l'utente chiude e riapre la scheda del browser o quando l'app web viene avviata dalla schermata Home in modalità offline.

Per ottenere questo risultato, Mainline Menswear ha fornito un metodo di riserva per le richieste NavigationRoute non riuscite con la pagina offline prememorizzata nella 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);

Demo

Esempio di pagina offline visto su www.mainlinemenswear.co.uk.

Registrazione delle installazioni andate a buon fine

Oltre al monitoraggio dell'avvio nella schermata Home (con "start_url": "/?utm_source=pwa" nel file manifest dell'applicazione web), l'app web segnala anche le installazioni di app riuscite ascoltando l'evento appinstalled il giorno window:

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

L'aggiunta delle funzionalità PWA al tuo sito web migliorerà ulteriormente l'esperienza dei clienti che fanno acquisti presso la tua attività e il mercato sarà più veloce rispetto a un'app [specifica della piattaforma].

Andy Hoyle, Head of Development

Conclusione

Per scoprire di più sulle app web progressive e su come crearle, vai alla sezione App web progressive su web.dev.

Per altri case study sulle app web progressive, vai alla sezione dei case study.