בגדי גברים ממוצעים מיישמים PWA ומשיגים עלייה של 55% בשיעור ההמרות

Minline היא קמעונאית אופנה באינטרנט שמציעה את שמות המעצבים הגדולים ביותר בתחום האופנה. החברה הבריטית מפקידה את צוות המומחים הפנימיים שלה, מעורב באופן אסטרטגי עם שותפים מרכזיים, כדי לספק לכולם חוויית קנייה חלקה. עם נוכחות אונליין ביותר מ-100 מדינות, באמצעות אפליקציה ושבעה אתרים אזוריים בהתאמה אישית, החברה תמשיך להבטיח שהמסחר האלקטרוני מתחרה בתחרות.

אתגר

המטרה של Minline Menswear הייתה להשלים את האתר הנוכחי שעבר אופטימיזציה לנייד עם תכונות מתקדמות, שיתאימו לחזון "ניידים" תחילה, והתמקדו בעיצוב ובפונקציונליות ידידותיים לנייד, תוך התחשבות בשוק ההולך וגדל של סמארטפונים.

פתרון

המטרה הייתה לפתח ולהשיק PWA שלמה לגרסה המקורית הידידותית לנייד של אתר Minline Menswear, ולאחר מכן להשוות בין הנתונים הסטטיסטיים לבין האפליקציה ההיברידית לנייד של האתר, שזמינה כרגע ב-Android וב-iOS.

לאחר ההשקה של האפליקציה, ולאחר מכן קבוצה קטנה של משתמשים ב-Mainline Menswear, הם יכלו לזהות את ההבדל בנתונים הסטטיסטיים העיקריים בין PWA, אפליקציה ואינטרנט.

הגישה שנקטה Minline בהמרת האתר ל-PWA הייתה לוודא שהמסגרת שהם בחרו עבור האתר (Nuxt.js, תוך שימוש ב-Vue.js) תהיה מוגנת בעתיד, ותאפשר להם לנצל את היתרונות של טכנולוגיית אינטרנט שמועברת במהירות.

תוצאות

139%

יותר דפים לסשן ב-PWA לעומת באינטרנט.

161%

משכי סשן ארוכים יותר ב-PWA לעומת באינטרנט.

10%

שיעור עזיבה נמוך יותר ב-PWA לעומת באינטרנט

12.5%

ערך הזמנה ממוצע גבוה יותר ב-PWA לעומת באינטרנט

55%

שיעור המרה גבוה יותר ב-PWA לעומת באינטרנט.

243%

הכנסה גבוהה יותר לכל סשן ב-PWA לעומת באינטרנט.

ניתוח טכני מפורט

בחברת Mainline Menswear משתמשים ב-Nuxt.js framework כדי לקבץ ולעבד את האתר שלהם, כלומר אפליקציה שמוגדרת בדף יחיד (SPA).

יצירת קובץ Service Worker

כדי לייצר את קובץ השירות (service worker), נוספה ב-Mainline Menswear הגדרות אישיות באמצעות הטמעה מותאמת אישית של nuxt/pwa Workbox מודול.

הסיבה לכך שהם שיתפו את המודול nuxt/pwa הייתה כדי לאפשר לצוות להוסיף עוד התאמות אישיות לקובץ ה-Service Worker, שלא הייתה לו אפשרות או שהיו לו בעיות במסגרת השימוש בגרסה הרגילה. אחת האופטימיזציה הייתה לפונקציונליות אופליין של האתר. לדוגמה, הצגת דף אופליין שמוגדר כברירת מחדל ואיסוף ניתוח נתונים במצב אופליין.

המבנה של קובץ המניפסט של אפליקציית האינטרנט

הצוות יצר מניפסט עם סמלים לגדלים שונים של סמלי אפליקציות לנייד ופרטים אחרים של אפליקציות אינטרנט, כמו name, description ו-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"
}

לאחר ההתקנה, ניתן להפעיל את אפליקציית האינטרנט ממסך הבית, בלי שהדפדפן יפריע לך. כדי לעשות זאת, צריך להוסיף את הפרמטר display לקובץ המניפסט של אפליקציית האינטרנט:

{
  "display": "standalone"
}

לבסוף, החברה יכולה עכשיו לעקוב בקלות אחר מספר המשתמשים שנכנסים לאפליקציית האינטרנט שלה ממסך הבית, על ידי הוספה של פרמטר utm_source בשדה start_url במניפסט:

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

שמירה במטמון של זמן ריצה לניווט מהיר יותר

שמירה במטמון של אפליקציות אינטרנט חיונית לאופטימיזציה של מהירות הדף ולמתן חוויית משתמש טובה יותר למשתמשים חוזרים.

לשמירה במטמון באינטרנט, יש כמה גישות שונות. הצוות משתמש בשילוב של מטמון HTTP ו-מטמון API כדי לשמור נכסים במטמון בצד הלקוח.

בעזרת cache API אפשר להעניק ל-Mainline Menswear שליטה מדויקת יותר על הנכסים שנשמרו במטמון, וכך להחיל אסטרטגיות מורכבות על כל סוג קובץ. כל זה נשמע מסובך וקשה להגדרה ולתחזוקה, אבל ארגז עבודה מאפשר להם להצהיר בקלות על אסטרטגיות מורכבות כאלה, וחוסך את הטרחה שכרוכה בתחזוקה.

שמירת CSS ו-JS

לקובצי CSS ו-JS, הצוות בחר לשמור אותם במטמון ולהציג אותם במטמון באמצעות אסטרטגיית תיבת העבודה StaleWhileRevalidate. האסטרטגיה הזו מאפשרת להם להציג את כל הקבצים של Nuxt CSS ו-JS במהירות, וכך לשפר משמעותית את ביצועי האתר. במקביל, הקבצים מתעדכנים ברקע לגרסה העדכנית ביותר בביקור הבא:

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

שמירת גופנים של Google במטמון

האסטרטגיה לשמירת קובצי Google Fonts תלויה בשני סוגי קבצים:

  • גיליון הסגנונות שמכיל את ההצהרות @font-face.
  • קובצי הגופנים הבסיסיים (נדרשים בתוך גיליון הסגנונות שהוזכר למעלה).
// 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',
);

שמירת תמונות במטמון

לתמונות, ב-Mainline Menswear החליטו לבחור שתי אסטרטגיות. האסטרטגיה הראשונה חלה על כל התמונות שמקורן ב-CDN, שהן בדרך כלל תמונות מוצר. הדפים שלהם עמוסים בתמונות, כך שהם מודעים לכך שלא תופסים יותר מדי מקום אחסון במכשיר של המשתמשים. לכן, באמצעות Workbox, הם הוסיפו אסטרטגיה של שמירת תמונות במטמון רק מה-CDN באמצעות עד 60 תמונות באמצעות ExpirationPlugin.

התמונה ה-61 (החדשה ביותר) המבוקשת מחליפה את התמונה הראשונה (הישנה ביותר), כך שלא יותר מ-60 תמונות מוצרים יישמרו במטמון בכל רגע נתון.

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,
      }),
    ],
  }),
);

אסטרטגיית התמונות השנייה מטפלת בשאר התמונות שהתבקשו על ידי המקור. בדרך כלל התמונות האלה מעטות מאוד וקטנות בכל המקור, אבל ליתר ביטחון, מספר התמונות במטמון מוגבל ל-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,
      }),
    ],
  }),
);

מספקת פונקציונליות במצב אופליין

הדף אופליין נשמר מראש במטמון מיד אחרי שה-Service Worker מותקן ומופעל. לשם כך הן יוצרות רשימה של כל יחסי התלות אופליין: קובץ ה-HTML אופליין וסמל SVG אופליין.

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

לאחר מכן, רשימת המטמון מוזנת ב-Workbox שמטפלת בכל העבודה הקשה של הוספת כתובות URL למטמון, בדיקה אם יש אי התאמה בגרסאות קודמות, עדכון והצגה של הקבצים שנשמרו מראש באסטרטגיה CacheFirst.

workbox.precaching.precacheAndRoute(PRECACHE);

טיפול בניווטים אופליין

אחרי שה-Service Worker מופעל והדף אופליין נשמר מראש במטמון, הוא משמש לתגובה לבקשות הניווט של המשתמש במצב אופליין. אפליקציית האינטרנט של Minline Menswear היא שירות SPA, אבל הדף אופליין מופיע רק אחרי שהדף נטען מחדש, המשתמש סוגר ופותח מחדש את הכרטיסייה בדפדפן, או כשאפליקציית האינטרנט מופעלת ממסך הבית במצב אופליין.

כדי להשיג את המטרה הזו, ב-Mainline Menswear נוצרה חזרה לבקשות של NavigationRoute שנכשלו באמצעות הדף של מצב אופליין שנשמר מראש:

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);

הדגמה (דמו)

דוגמה לדף אופליין כפי שהוא מופיע באתר www.mainlinemenswear.co.uk.

דיווח על התקנות שהושלמו

מלבד המעקב אחרי הפעלת מסך הבית (עם "start_url": "/?utm_source=pwa" בקובץ המניפסט של אפליקציית האינטרנט), אפליקציית האינטרנט מדווחת גם על התקנות אפליקציה שבוצעו בהצלחה על ידי האזנה לאירוע appinstalled ב-window:

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

הוספת יכולות של PWA לאתר תשפר את חוויית הלקוחות בקניות בחנות הפיזית, ותהיה לך אפשרות לשווק מהר יותר מאשר אפליקציה [ספציפית לפלטפורמה].

אנדי הייל, ראש מחלקת פיתוח

סיכום

למידע נוסף על Progressive Web Apps ואיך ליצור אותן, כדאי לעיין בקטע Progressive Web Apps באתר web.dev.

למידע נוסף על מקרים לדוגמה ב-Progressive Web Apps, יש לעיין בקטע 'מקרים לדוגמה'.