PWA に切り替えたことで MishiPay のビジネスがどのように改善されたかをご覧ください。
MishiPay を使用すると、買い物客はレジで並ぶ時間を無駄にすることなく、スマートフォンで商品をスキャンして支払うことができます。MishiPay のScan & Go テクノロジーにより、買い物客は自分のスマートフォンを使用して商品のバーコードをスキャンし、支払いを済ませて、そのまま店舗を出ることができます。調査によると、店舗での待ち行列は、世界中の小売業界に年間約 2000 億ドルの費用を負担させています。
この技術は、GPS センサーやカメラなどのデバイスのハードウェア機能を利用して、ユーザーが MishiPay 対応の店舗を探し、実店舗で商品バーコードをスキャンして、任意のデジタル決済方法で支払うことを可能にします。スキャン&ゴー テクノロジーの初期バージョンは、プラットフォーム固有の iOS アプリと Android アプリでしたが、早期導入ユーザーに好評でした。PWA に切り替えることでトランザクションが 10 倍に増加し、キュー待ち時間が 2.5 年分削減された方法について、詳しくは以下をご覧ください。
10×
取引の増加
2 年半
キューイングを保存しました
課題
ユーザーは、この技術がキューやレジ待ちの際に非常に役立つと考えています。キューをスキップしてスムーズに店舗での購入を完了できるためです。しかし、Android または iOS のアプリをダウンロードする手間があるため、ユーザーは価値にもかかわらず、このテクノロジーを採用しませんでした。これは MishiPay にとって大きな課題でした。ユーザーの利用を促進するために、参入障壁を下げる必要がありました。
解決策
PWA の構築とリリースにより、インストールの手間を省くことができ、新規ユーザーが実店舗でテクノロジーを試し、行列に並ばずにシームレスなショッピング体験を得られるようになりました。リリース以降、プラットフォーム固有のアプリと比較して、PWA のユーザーの採用が大幅に増加しています。
技術的な詳細
MishiPay 対応の店舗の検索
この機能を有効にするには、IP ベースのフォールバック ソリューションとともに getCurrentPosition()
API を使用します。
const geoOptions = {
timeout: 10 * 1000,
enableHighAccuracy: true,
maximumAge: 0,
};
window.navigator.geolocation.getCurrentPosition(
(position) => {
const cords = position.coords;
console.log(`Latitude : ${cords.latitude}`);
console.log(`Longitude : ${cords.longitude}`);
},
(error) => {
console.debug(`Error: ${error.code}:${error.message}`);
/**
* Invoke the IP based location services
* to fetch the latitude and longitude of the user.
*/
},
geoOptions,
);
このアプローチは、アプリの以前のバージョンではうまく機能していましたが、後で MishiPay のユーザーにとって大きな問題であることが判明しました。その理由は次のとおりです。
- IP ベースのフォールバック ソリューションの位置情報の不正確さ。
- 地域ごとに MishiPay 対応店舗のリストが増えているため、ユーザーはリストをスクロールして正しい店舗を特定する必要があります。
- ユーザーが誤って間違った店舗を選択してしまい、購入が正しく記録されないことがあります。
こうした問題に対処するため、各店舗の店内ディスプレイに、位置情報に基づく一意の QR コードを埋め込みました。これにより、オンボーディングの迅速化が実現しました。ユーザーは、店舗に設置されているマーケティング資料に印刷されている位置情報付き QR コードをスキャンするだけで、Scan & Go ウェブ アプリケーションにアクセスできます。これにより、ウェブアドレス mishipay.shop
を入力してサービスにアクセスする必要がなくなります。
商品のスキャン
MishiPay アプリのコア機能はバーコード スキャンです。これにより、ユーザーはレジに到達する前に購入品をスキャンして合計金額を確認できます。
ウェブでスキャン エクスペリエンスを構築するために、3 つのコアレイヤを特定しました。
動画ストリーム
getUserMedia()
メソッドを使用すると、以下の制約付きでユーザーのリアビュー カメラにアクセスできます。このメソッドを呼び出すと、カメラへのアクセスを許可または拒否するよう求めるメッセージが自動的にトリガーされます。動画ストリームにアクセスしたら、次のように動画要素にリレーできます。
/**
* Video Stream Layer
* https://developer.mozilla.org/docs/Web/API/MediaDevices/getUserMedia
*/
const canvasEle = document.getElementById('canvas');
const videoEle = document.getElementById('videoElement');
const canvasCtx = canvasEle.getContext('2d');
fetchVideoStream();
function fetchVideoStream() {
let constraints = { video: { facingMode: 'environment' } };
if (navigator.mediaDevices !== undefined) {
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
videoEle.srcObject = stream;
videoStream = stream;
videoEle.play();
// Initiate frame capture - Processing Layer.
})
.catch((error) => {
console.debug(error);
console.warn(`Failed to access the stream:${error.name}`);
});
} else {
console.warn(`getUserMedia API not supported!!`);
}
}
処理レイヤ
特定の動画ストリームでバーコードを検出するには、フレームを定期的にキャプチャしてデコーダレイヤに転送する必要があります。フレームをキャプチャするには、Canvas API の drawImage()
メソッドを使用して、VideoElement
から HTMLCanvasElement
にストリームを描画します。
/**
* Processing Layer - Frame Capture
* https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas
*/
async function captureFrames() {
if (videoEle.readyState === videoEle.HAVE_ENOUGH_DATA) {
const canvasHeight = (canvasEle.height = videoEle.videoHeight);
const canvasWidth = (canvasEle.width = videoEle.videoWidth);
canvasCtx.drawImage(videoEle, 0, 0, canvasWidth, canvasHeight);
// Transfer the `canvasEle` to the decoder for barcode detection.
const result = await decodeBarcode(canvasEle);
} else {
console.log('Video feed not available yet');
}
}
高度なユースケースでは、このレイヤは切り抜き、回転、グレースケールへの変換などの前処理タスクも実行します。これらのタスクは CPU 使用率が高く、バーコード スキャンは長時間実行されるオペレーションであるため、アプリケーションが応答しなくなる可能性があります。OffscreenCanvas API を使用すると、CPU 使用率の高いタスクをウェブワーカーにオフロードできます。ハードウェア グラフィック アクセラレーションをサポートしているデバイスでは、WebGL API とその WebGL2RenderingContext
を使用して、CPU 使用率の高い前処理タスクのゲインを最適化できます。
デコーダ レイヤ
最後のレイヤはデコーダ レイヤで、処理レイヤによってキャプチャされたフレームからバーコードをデコードします。Shape Detection API(一部のブラウザでは利用できない)により、ブラウザ自体が ImageBitmapSource
からバーコードをデコードします。ImageBitmapSource
は、img
要素、SVG image
要素、video
要素、canvas
要素、Blob
オブジェクト、ImageData
オブジェクト、ImageBitmap
オブジェクトのいずれかです。
/**
* Barcode Decoder with Shape Detection API
* https://web.dev/shape-detection/
*/
async function decodeBarcode(canvas) {
const formats = [
'aztec',
'code_128',
'code_39',
'code_93',
'codabar',
'data_matrix',
'ean_13',
'ean_8',
'itf',
'pdf417',
'qr_code',
'upc_a',
'upc_e',
];
const barcodeDetector = new window.BarcodeDetector({
formats,
});
try {
const barcodes = await barcodeDetector.detect(canvas);
console.log(barcodes);
return barcodes.length > 0 ? barcodes[0]['rawValue'] : undefined;
} catch (e) {
throw e;
}
}
Shape Detection API をまだサポートしていないデバイスの場合、バーコードをデコードするための代替ソリューションが必要です。Shape Detection API は、Shape Detection API と代替ソリューションの切り替えに役立つ getSupportedFormats()
メソッドを公開します。
// Feature detection.
if (!('BarceodeDetector' in window)) {
return;
}
// Check supported barcode formats.
BarcodeDetector.getSupportedFormats()
.then((supportedFormats) => {
supportedFormats.forEach((format) => console.log(format));
});
フォールバック ソリューション
オープンソースとエンタープライズのスキャン ライブラリがいくつかあり、任意のウェブ アプリケーションと簡単に統合してスキャンを実装できます。MishiPay が推奨するライブラリをいくつかご紹介します。
上記のライブラリはすべて、上記のすべてのレイヤを構成する本格的な SDK です。また、さまざまなスキャン操作をサポートするインターフェースも公開します。ビジネスケースに必要なバーコード形式と検出速度に応じて、Wasm ソリューションと非 Wasm ソリューションのどちらを選択するかを決定できます。バーコードをデコードするために追加のリソース(Wasm)が必要になるというオーバーヘッドがあるにもかかわらず、Wasm ソリューションは精度に関して Wasm 以外のソリューションよりも優れています。
主に Scandit を選択しました。ビジネスのユースケースに必要なすべてのバーコード形式をサポートし、スキャン速度では利用可能なすべてのオープンソース ライブラリを上回っています。
スキャンの未来
すべての主要ブラウザで Shape Detection API が完全にサポートされると、バーコード スキャナに必要な機能を備えた新しい HTML 要素 <scanner>
が導入される可能性があります。MishiPay のエンジニアリングチームは、Scan & Go などのエクスペリエンスを可能にするオープンソース ライブラリやライセンス ライブラリの数が増えているため、バーコード スキャン機能を新しい HTML 要素として使用する確かなユースケースがあると考えています。
まとめ
アプリの疲労は、デベロッパーがプロダクトを市場に投入する際に直面する問題です。多くのユーザーは、アプリをダウンロードする前に、そのアプリが提供する価値を理解したいと考えています。MishiPay が買い物客の時間を節約し、エクスペリエンスを向上させる店舗では、ダウンロードを待ってからアプリを使用できるようにするのは直感に反します。ここで PWA が役に立ちます。参入障壁を排除することで、取引が 10 倍に増加し、ユーザーはキュー待ちで 2 年半も節約できるようになりました。
謝辞
この記事は Joe Medley さんが確認しました。