Amplify Analyticsを使ってPinpointの動的セグメントを構築してみる

2021.12.17

いわさです。

Amplifyの分析にPinpointを使うことで、動的セグメントを構築することが可能です。
以下の記事ではCSVインポートによる静的セグメントを構築しています。

システムの外部から取り込むセグメントは静的セグメントとして定期的にインポートするのが良いですが、AmplifyはPinpointとの統合機能が充実しています。
本日はAmplifyを使ったアプリケーションからユーザーセグメントを作成し、属性に応じたキャンペーンを作成してみます。

Amplifyの統合

今回は、Expoを使っていきたいと思います。
以下の記事でも紹介されていますが、Expoを使うとAndroid StudioやXcodeを使用しなくてもReact Nativeアプリケーションの開発を迅速に始めることが出来ます。
私は今回始めて使ったのですがQRコードを使ったローカル実機でのデバッグとホットリロード機能が便利すぎました。お薦めです。

iwasa.takahito@hoge src % expo init buildsegment
✔ Choose a template: › blank               a minimal app as clean as an empty canvas
✔ Downloaded and extracted project files.
🧶 Using Yarn to install packages. Pass --npm to use npm instead.
✔ Installed JavaScript dependencies.

✅ Your project is ready!

To run your project, navigate to the directory and run one of the following yarn commands.

- cd buildsegment
- yarn start # you can open iOS, Android, or web from here, or run them directly with the commands below.
- yarn android
- yarn ios
- yarn web

Expoでプロジェクトの初期化で出来たら、次はAmplifyの初期化し、依存パッケージをインストールします。
今回必要なのは、aws-amplify@react-native-async-storage/async-storage@react-native-community/netinfoの3つです。

iwasa.takahito@hoge buildsegment % amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project buildsegment
The following configuration will be applied:

...

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

...

? Please choose the profile you want to use hoge
Adding backend environment dev to AWS Amplify app: drc2yb0x6lcxb
⠋ Initializing project in the cloud...

...

Your project has been successfully initialized and connected to the cloud!

...


iwasa.takahito@hoge buildsegment % npm install aws-amplify @react-native-async-storage/async-storage @react-native-community/netinfo
+ aws-amplify@4.3.11

...

  run `npm audit fix` to fix them, or `npm audit` for details

AmplifyバックエンドにAnalytics機能を追加しプッシュします。
バックエンドは今回はここまででOKです。

iwasa.takahito@hoge buildsegment % amplify add analytics
? Select an Analytics provider Amazon Pinpoint
? Provide your pinpoint resource name: buildsegment
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 analytics events? (we recommend you allow this when getting started) Yes
✅ Successfully added auth resource locally.

...

iwasa.takahito@hoge buildsegment % amplify push                                        
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌───────────┬───────────────┬───────────┬───────────────────┐
│ Category  │ Resource name │ Operation │ Provider plugin   │
├───────────┼───────────────┼───────────┼───────────────────┤
│ Auth      │ buildsegment  │ Create    │ awscloudformation │
├───────────┼───────────────┼───────────┼───────────────────┤
│ Analytics │ buildsegment  │ Create    │ awscloudformation │
└───────────┴───────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes
⠴ Updating resources in the cloud. This may take a few minutes...

...

UPDATE_COMPLETE amplify-buildsegment-dev-112853 AWS::CloudFormation::Stack Fri Dec 17 2021 11:40:22 GMT+0900 (日本標準時) 
✔ All resources are updated in the cloud

作成されたリソースを確認

ここまでのコマンドで、Pinpointプロジェクトが新規作成されています。

既存のPinpointプロジェクトを統合することも可能で、その場合はamplify add analyticsコマンドで既存プロジェクトを指定します。
注意点がひとつあって、Pinpointプロジェクトは-などの記号を使用出来るのですが、add analytics時に指定するプロジェクトは英数字のみという制限があるようです。ルールが一致していないのでそこだけ気をつけましょう。

また、Cognitoから使用するためのIAMロールも作成されているのですが、Pinpointへのイベント送信とエンドポイント情報の登録・更新を行うためのポリシーが設定されています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "mobiletargeting:PutEvents",
                "mobiletargeting:UpdateEndpoint"
            ],
            "Resource": [
                "arn:aws:mobiletargeting:*:123456789012:apps/94a603f23de1434ea63cd0c217c2689e*"
            ],
            "Effect": "Allow"
        }
    ]
}

コード修正

expo initで作成された初期状態で"Open up App.js to start working on your app!"というテキストが配置された画面が表示されるようになっています。
UIとしてはこのままでも良いのですが、Amplifyの構成処理を追加しましょう。(ハイライト部分)

App.js

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';

import { Amplify, Analytics } from 'aws-amplify';
import awsconfig from './src/aws-exports';
Amplify.configure(awsconfig);

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

ここまでの手順でsrc/aws-exports.jsには既にPinpointプロジェクトなどの情報が設定されていますので追加で修正を行う必要はありません。

Pinpointでセグメントの作成

では、ここからPinpointで動的セグメントにエンドポイントが追加されていく様子を観察したいと思います。
まずはPinpointプロジェクトで動的セグメントを作成しましょう。

特に条件を指定しなくて良いです。全てのエンドポイントを対象にします。
しかし、この時点ではまだエンドポイントは0件だと思います。

先程までの手順でフロントエンドアプリケーションも作成出来ましたので実行してみましょう。
Expo Clientをインストール済みのデバイスでQRコードを読み込むか、コマンドを入力し仮想デバイスを起動しましょう。

iwasa.takahito@hoge buildsegment % npm start

> buildsegment@1.0.0 start /Users/iwasa.takahito/src/buildsegment
> expo start

Starting project at /Users/iwasa.takahito/src/buildsegment
Developer tools running on http://localhost:19002
Starting Metro Bundler
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█ ▄▄▄▄▄ █   █▄ █▄▀█ ▄▄▄▄▄ █
█ █   █ █ ▀▄ █▀▄ ▄█ █   █ █
█ █▄▄▄█ █▀██▀▀ ▀▄██ █▄▄▄█ █
█▄▄▄▄▄▄▄█▄▀▄█ █ █▄█▄▄▄▄▄▄▄█
█▄ ▀▀▄▄▄▀▀▀▀▄▀█▄ ███ ▀▄▄ ▄█
█ ▀▄█ █▄▀▄█▀ ▄▄█  ▀ █▄  ▀██
█ ▄▄▀ ▄▄█▀▀▄█▄▀▄▀▄▀▄▀▀▄ ▀██
███▄█▀▄▄██▀██▀█▀▄▄▄█▄▀ ▀███
█▄▄████▄▄▀▄ ▄ █▄▄ ▄▄▄ ▀ ▄▄█
█ ▄▄▄▄▄ █▀█▄ ██▀▀ █▄█ ▀▀███
█ █   █ █▄▀▀▀▀▀▄█▄▄ ▄▄▀ ▀▀█
█ █▄▄▄█ █▀ █ ███▄██▄▀█▀▀ ██
█▄▄▄▄▄▄▄█▄▄▄███▄████▄▄▄▄▄▄█

› Metro waiting on exp://192.168.0.151:19000
› Scan the QR code above with Expo Go (Android) or the Camera app (iOS)

› Press a │ open Android
› Press i │ open iOS simulator
› Press w │ open web

› Press r │ reload app
› Press m │ toggle menu
› Press d │ show developer tools
› shift+d │ toggle auto opening developer tools on startup (disabled)

› Press ? │ show all commands

Logs for your project will appear below. Press Ctrl+C to exit.

アプリケーションが起動され、画面が表示されました。
では、ここでPinpointの動的セグメント画面に戻ってみましょう。

エンドポイント合計数が1になっています。
今アプリケーションを起動したことで新規エンドポイントが作成されました。

追加されたエンドポイント情報を確認してみましょう。
セグメントのエクスポート機能でCSVダウンロードすることが出来ます。

特にパラメータは指定していないですが、デフォルトでエンドポイントへの属性がいくつか設定されていますね。

Id,ChannelType,EndpointStatus,OptOut,RequestId,Demographic.ModelVersion,Demographic.AppVersion,Demographic.Platform,EffectiveDate,User.UserId
56371f80-5efe-11ec-a76e-e70e2290db12,APNS,ACTIVE,ALL,327ca1ee-b403-4293-9c3a-10e24780e91f,28,android/28,android,2021-12-17T05:58:20.828Z,ap-northeast-1:0dddbaa7-eed0-480d-a96a-843dc71ed92d

ただし、キャンペーンでセグメントを選択しようとしても「一致が見つかりませんでした」と表示されてしまいます。
また、先程のセグメント詳細画面でも、対象エンドポイントが0件になっていましたね。

もう一度先程のCSVファイルを確認してみると、OptOutALLになっていることがわかります。
これは全てのメッセージチャネルからオプトアウトした状態を指しています。

アプリケーション側から明示的なオプトインが必要です。

オプトイン+ユーザー属性を追加

では、オプトイン設定を行ってみます。
加えて、セグメントでユーザー属性を取り扱ってみたいので、60歳以上かどうかを選択するボタンを配置し、エンドポイントへの反映結果を確認してみましょう。

App.js

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, Button } from 'react-native';

import { Amplify, Analytics } from 'aws-amplify';
import awsconfig from './src/aws-exports';
Amplify.configure(awsconfig);

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <Button title="60歳以上" onPress={() => {
        Analytics.updateEndpoint({
          optOut: 'NONE',
          address: 'hogehoge.address',
          userAttributes: {
            over60: [true]
          }
        }).then(() => {
        });
      }} />
      <Button title="60歳未満" onPress={() => {
        Analytics.updateEndpoint({
          optOut: 'NONE',
          address: 'hogehoge.address',
          userAttributes: {
            over60: [false]
          }
        }).then(() => {
        });
      }} />
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

起動して、複数の端末で別々の選択肢を選んでみます。

先程のセグメントを確認してみると、0件だった対象エンドポイントが2件になっています。

CSVを確認してみると、OptOutNONEになっていることが確認出来ます。

Id,ChannelType,Address,EndpointStatus,OptOut,RequestId,Demographic.ModelVersion,Demographic.AppVersion,Demographic.Platform,EffectiveDate,User.UserId,User.UserAttributes.over60
56371f80-5efe-11ec-a76e-e70e2290db12,GCM,hogehoge.address,INACTIVE,NONE,7977e21b-c904-40a4-aa0c-e4aca3ac86ae,28,android/28,android,2021-12-17T07:29:14.981Z,ap-northeast-1:0dddbaa7-eed0-480d-a96a-843dc71ed92d,true
2ab09fa0-5f0b-11ec-a881-99d7ef4c7f09,GCM,hogehoge.address,ACTIVE,NONE,3b63d995-fdf7-4c8b-bcfe-7fd927a5880a,30,android/30,android,2021-12-17T07:30:11.346Z,ap-northeast-1:e9f2e7f5-dfc2-47e2-b675-7395d6e8f04c,false

この状態でキャンペーンを作成すると対象セグメントで送信件数が2件になることが確認出来ます。
また、ユーザーのカスタム属性である、60歳以上かどうかのフラグで絞り込むと、対象者を絞ったキャンペーンを作成することも出来ました。

まとめ

本日は、Amplifyを使ってPinpointへの統合を行ってみました。

初期設定のみで、アプリケーション起動時のエンドポイント作成、オプトインからユーザー属性の収集まで行うことが出来ました。
また、動的セグメントを使って、ユーザー属性に応じたキャンペーンを展開することが出来ることも確認出来ました。

ここまで出来ると、オンラインマーケティング感がかなり出てきますね。 Amplifyを使わなくてもエンドポイントの作成などは行うことは出来ますが、Amplifyを使うことでどれだけ簡単にPinpointで分析出来るかがわかりました。