AWS Amplify の Analytics カテゴリまとめ

メリークリスマス、この記事では AWS Amplify で行える色々な分析機能について話します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1490/30500bc7-387f-62cc-36d0-735bcc5c419b.png)

[AWS Amplify](https://aws-amplify.github.io/docs/) は Web およびモバイルアプリを開発するためのフレームワークです。
Amplify CLI を通じてアプリケーションにカテゴリを追加、設定することで、開発者は自分のアプリに欲しい機能を使えるようになります。

例えば GraphQL API を使いたいなら `amplify add api` からの `amplify push` といった具合です。

```shell-session
$ amplify add api

? Please select from one of the below mentioned services GraphQL
? Provide API name: amplifyandroid
? Choose an authorization type for the API Amazon Cognito User Pool
Using service: Cognito, provided by: awscloudformation

 The current configured provider is Amazon Cognito.

 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections.
 How do you want users to be able to sign in when using your Cognito User Pool? Email
 Warning: you will not be able to edit these selections.
 What attributes are required for signing up? (Press <space> to select, <a> to toggle all, <i> to invert selection)Email
Successfully added auth resource

$ amplify push
```

このときの `api` は Amplify 的には「カテゴリ」と呼ばれているのですが、その中に `analytics` というものがあります。それを解説します。

# Analytics カテゴリでできること

2019.12.25 現在、プラットフォームごとに Analytics カテゴリでできることは次のような感じです。

* [Amplify JavaScript](https://aws-amplify.github.io/docs/js/analytics) (React, React Native, Angular, Ionic, Vue, Pure JavaScript) では
    * Amazon Pinpoint を使ったイベントの記録、ユーザー属性の登録など
    * Amazon Kinesis Data Streams, Amazon Kinesis Data Firehose を使ったイベントのストリーミング
    * Amazon Personalize へのイベントデータの送信
* [Amplify iOS](https://aws-amplify.github.io/docs/ios/analytics) では
    * Amazon Pinpoint を使ったイベントの記録、属性の登録など
* [Amplify Android](https://aws-amplify.github.io/docs/android/analytics) では
    * Amazon Pinpoint を使ったイベントの記録、属性の登録など

Amplify for iOS/Android は、AWS re:Invent 2019 の会期中にアナウンスされた新しいもので、2019.12.25 現在はプレビュー中であって本番での利用は意図されていません。JavaScript 版に比べてまだ機能も少ないですが、今後拡充されていくことでしょう。
なお、Amplify for iOS/Android でなく、従来から提供されていた iOS/Android SDK では AWS API ベースの多様な機能がすでに提供されていますが、その辺の違いなどはこの記事の守備範囲ではないので割愛します。（たぶん他の誰かが書くのではないかと。）

今回は、現時点で Analytics カテゴリの機能が充実している JavaScript 版を例に話を進めていきます。

# 準備：セットアップ

## Analytics カテゴリの追加

```terminal
$ amplify add analytics
Using service: Pinpoint, provided by: awscloudformation
? Provide your pinpoint resource name: amplifysample
Adding analytics would add the Auth category to the project if not already added.
? Apps need authorization to send analytics events. Do you want to allow guests and unauthenticated users to send anal
ytics events? (we recommend you allow this when getting started) Yes
Successfully added auth resource locally.
Successfully added resource amplifysample locally

Some next steps:
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all your local backend and front-end resources (if you have hosting category added) and provisions them in the cloud

$ amplify push
```

```javascript
import Amplify, { Analytics } from 'aws-amplify';
import awsconfig from './aws-exports';

Amplify.configure(awsconfig);
```

# 基本編：デフォルトの Analytics機能

そのまま Analytics クラスの各種メソッドを使うと、Amazon Pinpoint にイベントや属性データを収集して可視化することができます。



## イベントをトラッキングする

イベント件数を集計する。

```javascript
Analytics.record('Purchase event');
```

イベントに属性情報を付加する。この属性情報は、ダッシュボードでの可視化時に絞り込み表示する条件に使えます。

```javascript
Analytics.record({
    name: 'Purchase event', 
    // Attribute values must be strings
    attributes: { 
        page: 'itemDetail',
        itemCategory: 'Book'
    }
});
```

イベントにメトリクス（数値情報）を付加する。このメトリクス情報は、ダッシュボードで推移を可視化できます。

```javascript
Analytics.record({
    name: 'purchase', 
    attributes: { },
    metrics: { 
        itemPrice: 100,
        timeSpentOrdering: 60
    }
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1490/8a7f7588-40df-e983-14e3-88759837a3bb.png)


## 自動で取得できるイベントたち

### Session

デフォルトで Session Start, Session Stop などは記録されます。

### Page Views

`autoTrack` メソッドで Page View 数を取得するよう設定できます。

```javascript
Analytics.autoTrack('pageView', {
    // 必須。false にするとオフにできます。
    enable: true,
    // イベント名。省略可。デフォルトでは 'pageView'
    eventName: 'pageView',
    // イベントの属性。省略可。オブジェクトか関数を指定できる。
    // 関数を指定すると、設定する属性を動的に決められる。
    attributes: {
        attr: 'attr'
    },
    // 関数を使った場合
    // attributes: () => {
    //    const attr = somewhere();
    //    return {
    //        myAttr: attr
    //    }
    // },

    // SPA かどうかを指定する。省略可。デフォルトは 'multiPageApp'。
    // React のような Single-Page App で使う場合は 'SPA' にセットする。
    type: 'multiPageApp',
    // どのサービスに PV 情報を送信するか。省略可。デフォルトは 'AWSPinpoint'。
    provider: 'AWSPinpoint',
    // トラックされる URL 情報。省略可。関数を指定すると柔軟な値を返せる。
    getUrl: () => {
        // the default function
        return window.location.origin + window.location.pathname;
    }
});
```

### Media Tracking

HTML5 の `media types` を使ってメディアを再生する場合、次のコードで _Play, Pause, Ended, TimeWatched, Resume_ といった挙動を自動でトラックすることができます。

```javascript
Analytics.record({
    eventType: "MediaAutoTrack",
    userId: "<USER_ID>", // 省略可
    properties: {
        "domElementId": "MEDIA DOM ELEMENT ID",
        "itemId": "<ITEM_ID>"
    }
});
```

### 任意のイベント

任意のイベントも自動取得されるよう設定できます。
たとえば、ボタンクリックをトラックしたい場合は次のように書きます。

```javascript
Analytics.autoTrack('event', {
    // 必須。有効/無効の指定
    enable: true,
    // 収集したいイベント。省略可。デフォルトでは ['click']
    events: ['click'],
    // どんな拡張データ属性をもった HTML 要素をトラック対象にするか。省略可。
    // デフォルトは data-amplify-analytics-。
    selectorPrefix: 'data-amplify-analytics-',
    // どのサービスに情報を送るか。省略可。デフォルトは 'AWSPinpoint'
    provider: 'AWSPinpoint',
    // イベントに付与するイベント属性情報。省略可。
    // オブジェクトか関数を指定。関数を指定すると属性を動的に決められる。
    attributes: {
        attr: 'attr'
    }
    // 関数の場合
    // attributes: () => {
    //    const attr = somewhere();
    //    return {
    //        myAttr: attr
    //    }
    // }
});
```

その上で、HTML 側で次のように実装します。

```html
<button
    data-amplify-analytics-on='click'
    data-amplify-analytics-name='click'
    data-amplify-analytics-attrs='attr1:attr1_value,attr2:attr2_value'
/>
```

これでボタンクリック時にイベント情報が自動で送信されます。これは次のコードと同じ意味を持ちます。

```javascript
<script>
    var sendEvent = function() {
        Analytics.record({
            name: 'click',
            attributes: {
                attr: 'attr',       // デフォルト属性
                attr1: attr1_value, // ボタンごとの追加属性
                attr2: attr2_value, // ボタンごとの追加属性
            }
        });
    }
</script>
<button onclick="sendEvent()"/>
```

## 属性を取得、集計する

さて、ここまでは「イベント」を取得してきました。イベントと並んで、「属性」を収集することもできます。
Amplify の Analytics で取得できる「属性」にはいくつかの種類があります。それぞれ次のようなものです。

* イベント属性
    * 上で紹介した、 `Analytics.record()` 時に付加できる「個々のイベントごとの属性情報」です。
* エンドポイント属性
    * 「エンドポイント」ごとに設定できるカスタムな属性情報です。「エンドポイント」は個々のデバイスやブラウザなど、ほぼクライアントアプリケーションに相当するものです。一人のユーザーは複数のエンドポイントを所有していることがあります。
* ユーザー属性
    * 「ユーザー」ごとに設定できるカスタムな属性情報です。一人のユーザーが複数の「エンドポイント」を持っている場合、 エンドポイントに設定された `userId` が同じであれば、ユーザー属性はエンドポイント間で *自動的に同期* されます。便利！
* デモグラフィック情報
    * SDK によって自動的に取得、セットされる情報です。明示的に上書きすることもできます。
      * アプリケーションのバージョン（1.0 等々）
      * ロケール（en_US, ja_JP など）
      * デバイスのメーカー（Apple, Samsung など）
      * モデル情報（iPhone, iPad, Galaxy Hogehoge など）
      * プラットフォーム（iOS, Android, Windows など）
      * タイムゾーン（Asia/Tokyo など）
* ロケーション情報
    * 場所に関する情報です。
      * 都市
      * 国
      * 緯度
      * 経度
      * 郵便番号
      * 州

これらの属性を収集するには `updateEndpoint` メソッドを使います。

```javascript
import Analytics from '@aws-amplify/analytics';

Analytics.updateEndpoint({
    // 通知受信者に一意なエンドポイントの "アドレス"。channelType によってメールアドレス、デバイストークン、電話番号などになる
    address: 'xxxxxxx', 
    attributes: {
        // 任意に設定できるエンドポイント属性。通知対象のセグメントを作るときの条件に使える。
        hobbies: ['piano', 'hiking'],
    },
    // 通知経路（チャネル）。GCM | APNS | APNS_SANDBOX | APNS_VOIP | APNS_VOIP_SANDBOX | ADM | SMS | EMAIL | BAIDU が有効。
    channelType: 'APNS',
    demographic: {
        // SDK によって自動で取得される（明示的に指定もできる）デモグラフィック情報。
        appVersion: 'xxxxxxx',
        locale: 'xxxxxx',
        make: 'xxxxxx',
        model: 'xxxxxx',
        modelVersion: 'xxxxxx',
        platform: 'xxxxxx',
        platformVersion: 'xxxxxx',
        timezone: 'xxxxxx'
    },
    location: {
        // SDK によって自動で取得される（明示的に指定もできる）ロケーション情報。
        city: 'xxxxxx',
        country: 'xxxxxx',
        latitude: 0,
        longitude: 0,
        postalCode: 'xxxxxx',
        region: 'xxxxxx'
    },
    metrics: {
        // 任意の数値情報
    },
    optOut: 'ALL', // オプトアウトしたユーザーの場合 ALL にすると通知を受信しない。 NONE にすると受信する。
    userId: 'XXXXXXXXXXXX', // 任意のユーザー ID
    userAttributes: {
        // userId が同じエンドポイント間で自動的に同期される任意のユーザー属性
        interests: ['football', 'basketball', 'AWS']
    }
}).then(() => {
});
```

↑ たくさん指定できますが、たとえば ↓ な感じでカジュアルに属性をセットできます。

```javascript
Analytics.updateEndpoint({
    attributes: {editor: 'Vim'}
});
```

Amazon Pinpoint から通知するメールアドレスをセットするならこういう感じですね。

```javascript
Analytics.updateEndpoint({
    address: 'amplify@example.com',
    channelType: 'EMAIL'
});
```

はい。

## Analytics を有効・無効にする

デフォルトではこれらの Analytics 機能は有効になっていますが、任意のタイミングで無効にしたり戻したりできます。

```javascript
// 無効にする
Analytics.disable();

// 有効にする
Analytics.enable();
```

# 応用編：イベントトラッキングのサービスプロバイダを指定する

ここまでは基本的に Amazon Pinpoint にデータを収集する話をしてきましたが、Amplify では Pinpoint の代わりに Amazon Kinesis Data Streams, Amazon Kinesis Data Firehose, Amazon Personalize でイベントを収集することもできます。

## [Amazon Kinesis Data Streams](https://aws.amazon.com/jp/kinesis/data-streams/) の例

```javascript
import { Analytics, AWSKinesisProvider } from 'aws-amplify';
Analytics.addPluggable(new AWSKinesisProvider());

// 利用する Kinesis の情報を指定
Analytics.configure({
    AWSKinesis: {
        // リージョン
        region: 'XX-XXXX-X',
        // イベントをバッファするサイズ。省略可。
        bufferSize: 1000,
        // フラッシュしたときにバッファから削除されるイベント数。省略可。
        flushSize: 100,
        // バッファ内のサイズ確認および必要に応じてフラッシュするインターバル。ミリ秒。省略可。
        flushInterval: 5000, // 5s
        // 送信に失敗したときのリトライ上限数
        resendLimit: 5
    } 
});

// Kinesis にデータを送信
Analytics.record({
    data: { 
        // The data blob to put into the record
    },
    // OPTIONAL
    partitionKey: 'myPartitionKey', 
    streamName: 'myKinesisStream'
}, 'AWSKinesis');
```

これができると何が嬉しいかというと、Amazon Kinesis Data Streams を使ってデータパイプラインを構築できることです。
Amazon Pinpoint だけでもイベントや属性データの収集・可視化はできますが、より柔軟に全体を構築することができるようになります。

## [Amazon Kinesis Data Firehose](https://aws.amazon.com/jp/kinesis/data-firehose/) の例

前の例は Data Streams でしたが、もっとお手軽 Data Firehose もほぼ同じ感覚で使えます。

```javascript
import { Analytics, AWSKinesisFirehoseProvider } from 'aws-amplify';
Analytics.addPluggable(new AWSKinesisFirehoseProvider());

Analytics.configure({
    AWSKinesisFirehose: {
        region: 'XX-XXXX-X',
        bufferSize: 1000,
        flushSize: 100,
        flushInterval: 5000, // 5s
        resendLimit: 5
    } 
});

Analytics.record({
    data: { 
        // The data blob to put into the record
    },
    streamName: 'myKinesisStream'
}, 'AWSKinesisFirehose');
```

Firehose に送っといて Amazon S3 に入れて Amazon Athena でクエリするとか、Amazon Elasticsearch Service に送って Kibana で見るとか、楽しそうですね！

## [Amazon Personalize](https://aws.amazon.com/jp/personalize/) の例

そして、「Amazon.com で使用されているのと同じテクノロジーに基づく、リアルタイムのパーソナライズとレコメンデーション」を提供してくれる Amazon Personalize にもイベントデータを流すことができます。

Personalize について知りたい方はこちらの資料をどうぞ。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1490/5ecf297a-9e7c-c915-4c4b-3ec74f4be6c8.png)](https://www.slideshare.net/AmazonWebServicesJapan/20190716-aws-black-belt-online-seminar-amazon-personalize)

すごくざっくり言うと、Personalize はある程度の規模の教師データセットで学習させてから推論を行う方法と、リアルタイムにイベントをトラッキングして最新の推論結果に活かす方法を提供してくれています。Amplify は、後者のリアルタイムイベント送信を簡単にしてくれます。

といっても使い方に難しい点はありません。だいたい Kinesis と似たような設定方法、利用方法です。

```javascript
import { Analytics, AmazonPersonalizeProvider } from 'aws-amplify';
Analytics.addPluggable(new AmazonPersonalizeProvider());

Analytics.configure({
    AmazonPersonalize: {
        // 必須。Personalize で払い出しておいた Tracking ID。
        trackingId: '<TRACKING_ID>',
        region: 'XX-XXXX-X',
        flushSize: 10,
        flushInterval: 5000, // 5s
    }
});

Analytics.record({
    eventType: "<EVENT_TYPE>",
    userId: "<USER_ID>", // 省略可
    properties: {
        "itemId": "<ITEM_ID>",
        "eventValue": "<EVENT_VALUE>"
    }
}, "AmazonPersonalize");
```

## カスタムプロバイダーの例

ここまで Amazon Pinpoint、Amazon Kinesis、Amazon Personalize にイベントデータを送信する方法を見てきましたが、ここでカスタムが出てくるところが AWS っぽいですね。
例えば、自前で構築してあるデータ収集用 API を叩きたい場合などに使えますね！

自前のイベントトラッキングプロバイダーを作るには、 `AnalyticsProvider` Interface を実装するクラスを作ります。

```typescript
import { Analytics, AnalyticsProvider } from 'aws-amplify';

export default class MyAnalyticsProvider implements AnalyticsProvider {
    // category and provider name
    static category = 'Analytics';
    static providerName = 'MyAnalytics';

    // you need to implement these four methods
    // configure your provider
    configure(config: object): object;

    // record events and returns true if succeeds
    record(params: object): Promise<boolean>;

    // return 'Analytics';
    getCategory(): string;

    // return the name of you provider
    getProviderName(): string;
}
```

このクラスを Plugin として Add することで使えるようになります。

```javascript
Analytics.addPluggable(new MyAnalyticsProvider());

Analytics.configure({
    MyAnalyticsProvider: { 
        // My Analytics provider configuration 
    }
});

Analytics.record({
    // Something to track
}, 'MyAnalyticsProvider');
```

# 以上

ということで、 `amplify add analytics` して `amplify push` して `Analytics.record()` `Analytics.updateEndpoint()` しましょう！