やったこと
- Webアプリケーションのユーザ離脱数をCloudWatchカスタムメトリクスとして取得する
- ユーザ離脱は、ユーザが異なるページに遷移しようとする「beforeunload」イベントを監視することで簡易的に検知
- 「beforeunload」イベント発生時に、正常に漏れなくCloudWatchにデータを送信できるよう、Beacon APIを使用する。
構成図
バックエンド
一般的なAPI GatewayとLambdaの構成をとる。
API GatewayにPOSTメソッドを作成し、LambdaプロキシでLambdaと紐づける。
Lambdaにはデフォルト権限に加えて「cloudwatch:PutMetricData」権限を付与する。
{
"Effect": "Allow",
"Action": "cloudwatch:PutMetricData",
"Resource": "*"
}
ソースコードは以下の通り。
import { CloudWatchClient, PutMetricDataCommand } from "@aws-sdk/client-cloudwatch";
const cloudwatch = new CloudWatchClient({ region: 'ap-northeast-1'});
export const handler = async (event) => {
try {
const data = JSON.parse(event.body);
const params = {
MetricData: [
{
MetricName: data.MetricName,
Dimensions: data.Dimensions,
Value: data.Value,
Unit: 'Count'
}
],
Namespace: 'UserWithdrawalDetection'
};
const command = new PutMetricDataCommand(params);
await cloudwatch.send(command);
return {
statusCode: 200,
body: JSON.stringify({
msessage: 'Success',
})
};
} catch (error) {
console.log("Error", error) ;
return {
statusCode: 500,
body: JSON.stringify({
msessage: 'Failed',
})
};
}
};
フロントエンド(React on S3)
簡易検証のため、srcディレクトリに以下のコンポーネントファイルを配置。
endpointは作成したAPI Gatewayのエンドポイントに書き換える。
import './App.css'
import Home from './Home'
import About from './About'
import MyPage from './MyPage'
import UserWithdrawalDetectionComponent from './UserWithdrawalDetectionComponent'
import { BrowserRouter, Route, Routes, Link } from 'react-router-dom'
function App() {
UserWithdrawalDetectionComponent((event) => {
const pageUrl = window.location.href
const data = {
MetricName: 'PageUnload',
Dimensions: [
{
Name: 'PageUrl',
Value: pageUrl,
},
],
Value: 1,
}
// endpointは作成したAPI Gatewayのエンドポイントに書き換える
const endpoint =
'https://xxx.execute-api.ap-northeast-1.amazonaws.com/Prd/collect-metrics'
// Becon APIを利用して、データをバックエンド(API Gateway+Lambda)に送付
navigator.sendBeacon(endpoint, JSON.stringify(data))
// 検証のため、タブクローズ時に、アサーションを出している
event.preventDefault()
event.returnValue = 'Are you sure you want to leave?'
})
return (
<>
<div className="App">
<BrowserRouter>
<Link to="/">Home</Link> | <Link to="/about">About</Link>|{' '}
<Link to="/myPage">MyPage</Link>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/myPage" element={<MyPage />} />
<Route path="*" element={<h1>Not Found Page</h1>} />
</Routes>
</BrowserRouter>
</div>
</>
)
}
export default App
import React from 'react'
const Home = () => {
return <h1>Home</h1>
}
export default Home
import React from 'react'
const Home = () => {
return <h1>Home</h1>
}
export default Home
import React from 'react'
const MyPage = () => {
return <h1>MyPage</h1>
}
export default MyPage
import React from 'react'
const About = () => {
return <h1>About</h1>
}
export default About
import { useEffect } from 'react'
const UserWithdrawalDetectionComponent = (callback) => {
useEffect(() => {
window.addEventListener('beforeunload', callback)
return () => {
window.removeEventListener('beforeunload', callback)
}
}, [callback])
}
export default UserWithdrawalDetectionComponent
ローカルでnpm run buildコマンドを実行して、生成されたbuildディレクトリ内のファイル、フォルダをS3に配置する。
S3は静的Webホスティング機能を使用する。
動作確認
Webアプリケーションにアクセスし、ページごとにタブを閉じる、キャンセルを繰り返す。
この裏側で、どのページでサイトを閉じたのかの情報をCloudWatchに送っている。
CloudWatchメトリクスの確認。
ページURLをディメンションとして、カスタムメトリクスが作成されている。
ダッシュボードにて期間内のページごとのユーザ離脱数を可視化してみる。
値は各ディメンションごとの合計値を算出している。
最後に
ユーザ離脱率を取得しましたが、加えてユーザアクセス数も取得することでユーザ離脱率まで簡単に取得できそうですね。
サードパーティツールやAWS Pinpointを使用することで簡単に離脱率は取得できますが、そこまでリッチな機能はいらないといったケースでは有効活用できそうです。