ติดตามผู้ใช้เพื่อรับข้อความ Push

หากต้องการส่งข้อความ Push คุณต้องขอสิทธิ์จากผู้ใช้ก่อน แล้วจึงสมัครใช้บริการอุปกรณ์ของผู้ใช้กับบริการ Push ซึ่งเกี่ยวข้องกับการใช้ JavaScript API เพื่อรับออบเจ็กต์ PushSubscription จากนั้นคุณจะส่งออบเจ็กต์ไปยังเซิร์ฟเวอร์

JavaScript API จะจัดการกระบวนการนี้อย่างตรงไปตรงมา คู่มือนี้จะอธิบายขั้นตอนทั้งหมด ซึ่งรวมถึงการตรวจหาฟีเจอร์ การขอสิทธิ์ และการจัดการกระบวนการสมัครใช้บริการ

การตรวจหาฟีเจอร์

ก่อนอื่น ให้ตรวจสอบว่าเบราว์เซอร์รองรับการรับส่งข้อความแบบพุชหรือไม่ คุณตรวจสอบว่าระบบรองรับการพุชได้โดยทำตาม 2 ขั้นตอนต่อไปนี้

  • มองหา serviceWorker ในออบเจ็กต์ navigator
  • มองหา PushManager ในออบเจ็กต์ window
if (!('serviceWorker' in navigator)) {
  // Service Worker isn't supported on this browser, disable or hide UI.
  return;
}

if (!('PushManager' in window)) {
  // Push isn't supported on this browser, disable or hide UI.
  return;
}

แม้ว่าการรองรับทั้ง Service Worker และการรับส่งข้อความพุชในเบราว์เซอร์จะเพิ่มขึ้น แต่คุณควรตรวจหาทั้ง 2 ฟีเจอร์นี้และค่อยๆ ปรับปรุงแอปพลิเคชัน

ลงทะเบียน Service Worker

หลังจากตรวจหาฟีเจอร์แล้ว คุณจะทราบว่าระบบรองรับ Service Worker และการรับส่งข้อความแบบพุช จากนั้นลงทะเบียน Service Worker

เมื่อลงทะเบียน Service Worker คุณจะบอกตำแหน่งไฟล์ Service Worker ให้เบราว์เซอร์ทราบ ไฟล์นี้เป็นไฟล์ JavaScript แต่เบราว์เซอร์จะให้สิทธิ์เข้าถึง API ของ Service Worker รวมถึงการรับส่งข้อความแบบพุช กล่าวคือ เบราว์เซอร์จะเรียกใช้ไฟล์ในสภาพแวดล้อมของ Service Worker

หากต้องการลงทะเบียน Service Worker ให้เรียกใช้ navigator.serviceWorker.register() และส่งเส้นทางไปยังไฟล์ เช่น

function registerServiceWorker() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      console.log('Service worker successfully registered.');
      return registration;
    })
    .catch(function (err) {
      console.error('Unable to register service worker.', err);
    });
}

ฟังก์ชันนี้จะบอกตำแหน่งไฟล์ Service Worker ให้เบราว์เซอร์ทราบ ในที่นี้ ไฟล์ Service Worker อยู่ที่ /service-worker.js หลังจากที่คุณเรียกใช้ register() เบราว์เซอร์จะทำตามขั้นตอนต่อไปนี้

  1. ดาวน์โหลดไฟล์ Service Worker

  2. เรียกใช้ JavaScript

  3. หากไฟล์ทำงานได้อย่างถูกต้องโดยไม่มีข้อผิดพลาด พรอมิสที่ register() แสดงผลจะได้รับการแก้ไข หากเกิดข้อผิดพลาด สัญญาจะปฏิเสธ

หมายเหตุ: หาก register() ปฏิเสธ ให้ตรวจสอบ JavaScript เพื่อหาข้อผิดพลาดหรือการพิมพ์ผิดในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

เมื่อ register() แก้ไขแล้ว ฟังก์ชันจะแสดงผล ServiceWorkerRegistration คุณใช้การลงทะเบียนนี้เพื่อเข้าถึง PushManager API

ความเข้ากันได้ของเบราว์เซอร์กับ PushManager API

Browser Support

  • Chrome: 42.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 16.

Source

การขอสิทธิ์

หลังจากลงทะเบียน Service Worker และได้รับสิทธิ์แล้ว ให้ขอสิทธิ์จากผู้ใช้เพื่อส่งข้อความ Push

API สำหรับขอสิทธิ์นั้นใช้งานง่าย อย่างไรก็ตาม API เพิ่งเปลี่ยนจากการใช้การเรียกกลับเป็นการคืนค่า Promise เนื่องจากคุณไม่สามารถระบุได้ว่าเบราว์เซอร์ใช้ API เวอร์ชันใด คุณจึงต้องใช้และจัดการทั้ง 2 เวอร์ชัน

function askPermission() {
  return new Promise(function (resolve, reject) {
    const permissionResult = Notification.requestPermission(function (result) {
      resolve(result);
    });

    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  }).then(function (permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error("We weren't granted permission.");
    }
  });
}

ในโค้ดก่อนหน้า การเรียกใช้ Notification.requestPermission() จะแสดงข้อความแจ้งต่อผู้ใช้ดังนี้

ข้อความแจ้งขอสิทธิ์ที่แสดงใน Chrome บนเดสก์ท็อปและอุปกรณ์เคลื่อนที่

หลังจากที่ผู้ใช้โต้ตอบกับข้อความแจ้งขอสิทธิ์โดยเลือกอนุญาต บล็อก หรือปิดข้อความแจ้ง คุณจะได้รับผลลัพธ์เป็นสตริง 'granted', 'default' หรือ 'denied'

ในโค้ดตัวอย่าง สัญญาที่ askPermission() ส่งคืนจะได้รับการแก้ไขหากมีการให้สิทธิ์ ไม่เช่นนั้น ระบบจะแสดงข้อผิดพลาดและปฏิเสธสัญญา

จัดการกรณีขอบที่ผู้ใช้คลิกปุ่มบล็อก หากเกิดกรณีนี้ขึ้น เว็บแอปจะขอสิทธิ์จากผู้ใช้ไม่ได้อีก ผู้ใช้ต้องเลิกบล็อกแอปของคุณด้วยตนเองโดยเปลี่ยนสถานะสิทธิ์ในแผงการตั้งค่า โปรดพิจารณาอย่างรอบคอบว่าควรขอสิทธิ์เมื่อใดและอย่างไร เนื่องจากหากผู้ใช้คลิกบล็อก การย้อนกลับการตัดสินใจดังกล่าวไม่ใช่เรื่องง่าย

ผู้ใช้ส่วนใหญ่จะให้สิทธิ์หากเข้าใจว่าทำไมแอปจึงขอสิทธิ์

เอกสารนี้จะอธิบายวิธีที่เว็บไซต์ยอดนิยมบางแห่งขอสิทธิ์ในส่วนท้ายของเอกสารนี้

สมัครรับข้อมูลให้ผู้ใช้ด้วย PushManager

หลังจากลงทะเบียน Service Worker และขอรับสิทธิ์แล้ว คุณจะติดตามผู้ใช้ได้โดยเรียกใช้ registration.pushManager.subscribe()

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

เมื่อเรียกใช้เมธอด subscribe() คุณจะส่งออบเจ็กต์ options ที่ประกอบด้วยพารามิเตอร์ที่จำเป็นและไม่บังคับ

ส่วนนี้จะอธิบายตัวเลือกที่คุณส่งได้

ตัวเลือก userVisibleOnly

เมื่อมีการเพิ่มการรับส่งข้อความ Push ลงในเบราว์เซอร์เป็นครั้งแรก นักพัฒนาแอปไม่แน่ใจเกี่ยวกับการส่งข้อความ Push โดยไม่แสดงการแจ้งเตือน โดยทั่วไปเรียกว่าการพุชแบบเงียบเนื่องจากผู้ใช้ไม่ทราบว่ามีเหตุการณ์เกิดขึ้นในเบื้องหลัง

ความกังวลคือ นักพัฒนาแอปอาจติดตามตำแหน่งของผู้ใช้ได้อย่างต่อเนื่องโดยที่ผู้ใช้ไม่ทราบ

เราจึงเพิ่มตัวเลือก userVisibleOnly เพื่อหลีกเลี่ยงสถานการณ์นี้และช่วยให้ผู้เขียนข้อกำหนดพิจารณาได้ว่าควรสนับสนุนฟีเจอร์นี้อย่างไรให้ดีที่สุด การส่งค่า true เป็นข้อตกลงเชิงสัญลักษณ์กับเบราว์เซอร์ว่าเว็บแอปจะแสดงการแจ้งเตือนทุกครั้งที่ได้รับข้อความพุช (นั่นคือไม่มีพุชแบบเงียบ)

คุณต้องส่งค่า true หากไม่ใส่คีย์ userVisibleOnly หรือส่งผ่าน false คุณจะได้รับข้อผิดพลาดต่อไปนี้

Chrome currently only supports the Push API for subscriptions that will result
in user-visible messages. You can indicate this by calling
`pushManager.subscribe({userVisibleOnly: true})` instead. See
[https://goo.gl/yqv4Q4](https://goo.gl/yqv4Q4) for more details.

Chrome รองรับ Push API เฉพาะการสมัครรับข้อมูลที่ส่งผลให้เกิดข้อความที่ผู้ใช้มองเห็น โดยโทรหา pushManager.subscribe({userVisibleOnly: true}) ดูข้อมูลเพิ่มเติมได้ที่ https://goo.gl/yqv4Q4

ดูเหมือนว่า Chrome จะไม่ใช้การแจ้งเตือนแบบพุชเงียบๆ ที่ครอบคลุม แต่ผู้เขียนข้อกำหนดกำลังพิจารณา API งบประมาณที่จะช่วยให้เว็บแอปส่งข้อความพุชแบบเงียบได้จำนวนหนึ่งตามการใช้งานเว็บแอป

ตัวเลือก applicationServerKey

เอกสารนี้เคยกล่าวถึงคีย์เซิร์ฟเวอร์แอปพลิเคชัน บริการพุชใช้คีย์เซิร์ฟเวอร์แอปพลิเคชันเพื่อระบุแอปพลิเคชันที่สมัครรับข้อมูลผู้ใช้ และเพื่อให้แน่ใจว่าแอปพลิเคชันเดียวกันจะส่งข้อความถึงผู้ใช้

คีย์เซิร์ฟเวอร์แอปพลิเคชันคือคู่คีย์สาธารณะและคีย์ส่วนตัวที่เฉพาะเจาะจงสำหรับแอปพลิเคชันของคุณ เก็บคีย์ส่วนตัวไว้เป็นความลับสำหรับแอปพลิเคชันของคุณ และแชร์คีย์สาธารณะได้อย่างอิสระ

อาร์กิวเมนต์ applicationServerKey ที่ส่งไปยังการเรียก subscribe() คือคีย์สาธารณะของแอปพลิเคชัน เบราว์เซอร์จะส่งคีย์นี้ไปยังบริการ Push เมื่อผู้ใช้สมัครใช้ ซึ่งจะช่วยให้บริการ Push เชื่อมโยงคีย์สาธารณะของแอปพลิเคชันกับ PushSubscription ของผู้ใช้ได้

แผนภาพต่อไปนี้แสดงขั้นตอนเหล่านี้

  1. โหลดเว็บแอปในเบราว์เซอร์และเรียกใช้ subscribe() โดยส่งคีย์เซิร์ฟเวอร์แอปพลิเคชันสาธารณะ
  2. จากนั้นเบราว์เซอร์จะส่งคำขอเครือข่ายไปยังบริการพุช ซึ่งจะสร้างปลายทาง เชื่อมโยงปลายทางนี้กับคีย์สาธารณะของแอปพลิเคชัน และส่งปลายทางกลับไปยังเบราว์เซอร์
  3. เบราว์เซอร์จะเพิ่มปลายทางนี้ไปยัง PushSubscription ซึ่งพรอมิส subscribe() จะแสดงผล

แผนภาพที่แสดงวิธีใช้คีย์เซิร์ฟเวอร์แอปพลิเคชันสาธารณะในเมธอด `subscribe()`

เมื่อส่งข้อความพุช ให้สร้างส่วนหัว Authorization ที่มีข้อมูลซึ่งลงนามด้วยคีย์ส่วนตัวของเซิร์ฟเวอร์แอปพลิเคชัน เมื่อบริการพุชได้รับคำขอให้ส่งข้อความพุช บริการจะตรวจสอบส่วนหัวการให้สิทธิ์ที่ลงชื่อนี้โดยค้นหาคีย์สาธารณะที่ลิงก์กับปลายทางที่ได้รับคำขอ หากลายเซ็นถูกต้อง บริการพุชจะทราบว่าคำขอมาจากเซิร์ฟเวอร์แอปพลิเคชันที่มีคีย์ส่วนตัวที่ตรงกัน ซึ่งเป็นมาตรการรักษาความปลอดภัยที่ป้องกันไม่ให้ผู้อื่นส่งข้อความถึงผู้ใช้แอปพลิเคชันของคุณ

แผนภาพที่แสดงวิธีใช้คีย์เซิร์ฟเวอร์แอปพลิเคชันส่วนตัวเมื่อส่งข้อความ

ในทางเทคนิคแล้ว applicationServerKey เป็นค่าที่ไม่บังคับ อย่างไรก็ตาม การติดตั้งใช้งานที่ง่ายที่สุดใน Chrome ต้องใช้ส่วนขยายนี้ และเบราว์เซอร์อื่นๆ อาจต้องใช้ในอนาคต โดยจะแจ้งให้เราทราบหรือไม่ก็ได้ใน Firefox

ข้อกำหนด VAPID จะกำหนดคีย์เซิร์ฟเวอร์แอปพลิเคชัน เมื่อเห็นการอ้างอิงถึงคีย์เซิร์ฟเวอร์แอปพลิเคชันหรือคีย์ VAPID โปรดทราบว่าคีย์ทั้ง 2 ประเภทนี้เหมือนกัน

สร้างคีย์เซิร์ฟเวอร์แอปพลิเคชัน

คุณสร้างชุดคีย์เซิร์ฟเวอร์แอปพลิเคชันแบบสาธารณะและส่วนตัวได้โดยไปที่ web-push-codelab.glitch.me หรือใช้บรรทัดคำสั่ง web-push เพื่อสร้างคีย์ดังนี้

    $ npm install -g web-push
    $ web-push generate-vapid-keys

สร้างคีย์เหล่านี้เพียงครั้งเดียวสำหรับแอปพลิเคชัน และตรวจสอบว่าคุณเก็บคีย์ส่วนตัวไว้เป็นส่วนตัว

สิทธิ์และ subscribe()

การเรียกใช้ subscribe() จะมีผลข้างเคียงอย่างหนึ่ง หากเว็บแอปไม่มีสิทธิ์แสดงการแจ้งเตือนเมื่อคุณโทรหา subscribe() เบราว์เซอร์จะขอสิทธิ์ให้คุณ ซึ่งจะเป็นประโยชน์หาก UI ของคุณทํางานร่วมกับโฟลว์นี้ แต่หากต้องการควบคุมเพิ่มเติม (ซึ่งนักพัฒนาแอปส่วนใหญ่ต้องการ) ให้ใช้ Notification.requestPermission() API ที่เอกสารนี้กล่าวถึงก่อนหน้านี้

ภาพรวม PushSubscription

คุณเรียกใช้ subscribe() ส่งตัวเลือก และรับสัญญาที่เปลี่ยนเป็น PushSubscription เช่น

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

ออบเจ็กต์ PushSubscription มีข้อมูลทั้งหมดที่จำเป็นต่อการส่งข้อความพุชไปยังผู้ใช้รายนั้น หากคุณพิมพ์เนื้อหาโดยใช้ JSON.stringify() คุณจะเห็นข้อมูลต่อไปนี้

    {
      "endpoint": "https://some.pushservice.com/something-unique",
      "keys": {
        "p256dh":
    "BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
        "auth":"FPssNDTKnInHVndSTdbKFw=="
      }
    }

endpoint คือ URL ของบริการพุช หากต้องการทริกเกอร์ข้อความพุช ให้ส่งคำขอ POST ไปยัง URL นี้

ออบเจ็กต์ keys มีค่าที่ใช้ในการเข้ารหัสข้อมูลข้อความที่ส่งพร้อมกับข้อความพุช (เอกสารนี้จะกล่าวถึงการเข้ารหัสข้อความในภายหลัง)

ส่งการสมัครใช้บริการไปยังเซิร์ฟเวอร์

หลังจากสมัครใช้บริการแบบพุชแล้ว ให้ส่งข้อมูลการสมัครใช้บริการไปยังเซิร์ฟเวอร์ คุณกำหนดวิธีส่งได้ แต่เคล็ดลับคือให้ใช้ JSON.stringify() เพื่อดึงข้อมูลที่จำเป็นทั้งหมดจากออบเจ็กต์การสมัครใช้บริการ หรือคุณจะประกอบผลลัพธ์เดียวกันด้วยตนเองก็ได้ เช่น

const subscriptionObject = {
  endpoint: pushSubscription.endpoint,
  keys: {
    p256dh: pushSubscription.getKeys('p256dh'),
    auth: pushSubscription.getKeys('auth'),
  },
};

// The above is the same output as:

const subscriptionObjectToo = JSON.stringify(pushSubscription);

หากต้องการส่งการสมัครใช้บริการจากหน้าเว็บ ให้ใช้ข้อมูลต่อไปนี้

function sendSubscriptionToBackEnd(subscription) {
  return fetch('/api/save-subscription/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(subscription),
  })
    .then(function (response) {
      if (!response.ok) {
        throw new Error('Bad status code from server.');
      }

      return response.json();
    })
    .then(function (responseData) {
      if (!(responseData.data && responseData.data.success)) {
        throw new Error('Bad response from server.');
      }
    });
}

เซิร์ฟเวอร์ Node.js จะรับคำขอนี้และบันทึกข้อมูลลงในฐานข้อมูลเพื่อใช้ในภายหลัง

app.post('/api/save-subscription/', function (req, res) {
  if (!isValidSaveRequest(req, res)) {
    return;
  }

  return saveSubscriptionToDatabase(req.body)
    .then(function (subscriptionId) {
      res.setHeader('Content-Type', 'application/json');
      res.send(JSON.stringify({data: {success: true}}));
    })
    .catch(function (err) {
      res.status(500);
      res.setHeader('Content-Type', 'application/json');
      res.send(
        JSON.stringify({
          error: {
            id: 'unable-to-save-subscription',
            message:
              'The subscription was received but we were unable to save it to our database.',
          },
        }),
      );
    });
});

เมื่อมีPushSubscriptionรายละเอียดในเซิร์ฟเวอร์ คุณจะส่งข้อความถึงผู้ใช้ได้ทุกเมื่อ

สมัครใช้บริการอีกครั้งเป็นประจำเพื่อไม่ให้หมดอายุ

เมื่อสมัครรับข้อความ Push คุณมักจะได้รับPushSubscription.expirationTimeของ null ในทางทฤษฎีแล้ว การสมัครใช้บริการนี้จะไม่มีวันหมดอายุ (ในทางตรงกันข้าม DOMHighResTimeStamp จะระบุเวลาหมดอายุที่แน่นอน) แต่ในทางปฏิบัติแล้ว เบราว์เซอร์มักจะปล่อยให้การสมัครใช้บริการหมดอายุ เช่น กรณีนี้อาจเกิดขึ้นหากไม่ได้รับการแจ้งเตือนแบบพุชเป็นเวลานาน หรือหากเบราว์เซอร์ตรวจพบว่าผู้ใช้ไม่ได้ใช้แอปที่มีสิทธิ์การแจ้งเตือนแบบพุช รูปแบบหนึ่งในการป้องกันปัญหานี้คือการสมัครรับข้อมูลผู้ใช้อีกครั้งเมื่อได้รับการแจ้งเตือนแต่ละครั้ง ดังที่ข้อมูลโค้ดต่อไปนี้แสดง ซึ่งคุณจะต้องส่งการแจ้งเตือนบ่อยพอเพื่อป้องกันไม่ให้เบราว์เซอร์ยกเลิกการสมัครใช้บริการโดยอัตโนมัติ คุณควรพิจารณาข้อดีและข้อเสียของความจำเป็นในการแจ้งเตือนที่ถูกต้องอย่างรอบคอบเทียบกับการส่งสแปมให้ผู้ใช้โดยไม่ตั้งใจเพียงเพื่อป้องกันไม่ให้การสมัครใช้บริการหมดอายุ ท้ายที่สุดแล้ว คุณไม่ควรพยายามหลีกเลี่ยงความพยายามของเบราว์เซอร์ในการปกป้องผู้ใช้จากการสมัครรับการแจ้งเตือนที่ลืมไปนานแล้ว

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

คำถามที่พบบ่อย

คำถามที่พบบ่อยมีดังนี้

คุณเปลี่ยนบริการพุชที่เบราว์เซอร์ใช้ได้ไหม

ไม่ เบราว์เซอร์จะเลือกบริการพุช ดังที่เอกสารนี้ได้กล่าวถึงsubscribe()การเรียก เบราว์เซอร์จะส่งคำขอเครือข่ายไปยังบริการพุชเพื่อดึงรายละเอียดที่ประกอบกันเป็น PushSubscription

บริการพุชต่างๆ ใช้ API ที่แตกต่างกันไหม

บริการพุชทั้งหมดคาดหวัง API เดียวกัน

API ทั่วไปนี้เรียกว่า Web Push Protocol ซึ่งอธิบายคำขอเครือข่ายที่แอปพลิเคชันของคุณสร้างขึ้นเพื่อทริกเกอร์ข้อความ Push

หากคุณติดตามผู้ใช้บนเดสก์ท็อป ระบบจะติดตามผู้ใช้บนโทรศัพท์ด้วยไหม

ไม่ได้ ผู้ใช้ต้องลงทะเบียนรับข้อความพุชในแต่ละเบราว์เซอร์ที่ต้องการรับข้อความ นอกจากนี้ ผู้ใช้ยังต้องให้สิทธิ์ในแต่ละอุปกรณ์ด้วย

ขั้นตอนถัดไป

Codelabs