ちょっと話題の記事

Amazon Pinpointの新機能「カスタムチャネル」を使って配信処理をLambda Functionで行う

2018.03.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Amazon Pinpointとは?

Amazon Pinpoint(以降、Pinpoint)は、モバイルアプリ利用者などの顧客との関わりを強固にするための機能を提供するサービスです。

リリース当初は「モバイルアプリのプッシュ通知」だけでしたが、現在は様々なチャネルのメッセージ送信が可能になっていることから 顧客セグメントに対して様々な方法でメッセージを送ることができるサービス となっています。

モバイルアプリにSDKを組み込むことで使用状況データを追跡できるため、実施したキャンペーンに対するリアクションなどを分析できます。

また、セグメントは使用状況データを元にした絞り込みルールを作る形で指定することもできますし、CSVなどのリストファイルをインポートする形で指定することもできます。

PinpointはAmazon Mobile Analyticsの機能の一部を持っている形でしたが、Mobile Analyticsは2018年4月末でサポートが終了されることから、Mobile Analyticsの上位互換 という位置付けと認識して良いでしょう。

モバイルだけじゃない、様々なチャネルにメッセージを送信

前述しましたが、Pinpointを使ってメッセージを送信する先は、モバイルアプリに限りません。様々なチャネルに対してメッセージを送ることができるようになっています。

  • モバイルアプリのプッシュ通知
    • iOSアプリ (APNs)
    • Androidアプリ (FCM/GCM)
    • Baidu (Baidu Cloud Push)
    • Kindle Fireアプリ (ADM)
  • Eメール
  • SMS(ショートメッセージサービス)
  • カスタムチャネル

最後の「カスタムチャネル」が、本記事で紹介したい新機能です!

破壊力抜群の新機能「カスタムチャネル」とは

「カスタムチャネル」はAWS Lambdaと連係し、 配信処理をLambda Functionで行える機能 です。Pinpointで配信リクエストがあると、配信先などの情報がLambda Functionに渡されて実行されます。あとは煮るなり焼くなりご自由にどうぞ!ということです。

「カスタムチャネル」は現在(2018年3月9日)はパブリックベータとして提供されており、誰でもいますぐに試すことができます。

カスタムチャネルを使ったセグメントコンテンツ配信をやってみた

今回はカスタムチャネルを使って セグメントコンテンツ配信 を考えてみました。

  1. セグメントとなるユーザーリストはファイルでインポート
  2. カスタムチャネルを使ってセグメントに対してメッセージの配信処理を実行
  3. セグメント対象のユーザーごとに、Lambda Function内でメッセージをDynamoDBに格納
  4. モバイルアプリ経由でDynamoDBを参照し、セグメント対象の場合のみコンテンツを受け取る

本記事では、上記の手順3までを行います。最終的には手順4までやると一通りの流れが作れます。

環境の準備(AWS CLIでサポートされるまで)

現時点でカスタムチャネルはAPI経由でしか利用できないため、PinpointのREST APIをリクエストできる環境が必要になります。

AWS CLIを使いたいところですが、AWS CLIもまだ対応されていません。そこでクレデンシャル付きでcurlのようにAPIをリクエストできる、こちらのツールを使います。

次のようにインストールします。

$ pip install awscurl

あとはクレデンシャルが ~/.aws/credentials および ~/.aws/config に設定されていれば、curlのように叩くだけでクレデンシャル(AWS Sig4)付きでリクエストが通ります。Profileを変更したい場合はコマンドラインオプションで指定するだけです。

カスタムチャネルを使う目的だけですが、今回はPinpointのAPI操作を一律 awscurl 経由で行います。

Pinpoint Applicationの作成

まずはPinpointのApplicationを作ります。APIはこちら

$ awscurl --service mobiletargeting \
"https://pinpoint.us-east-1.amazonaws.com/v1/apps" \
--region us-east-1 \
-X POST \
-d '{ "Name": "CustomChannelApp" }'

次のようにレスポンスが返り、完了です。

{
  "Name": "CustomChannelApp",
  "Id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

このIDは以降のPinpoint APIの呼び出しに使います。

DynamoDB Tableの作成

ユーザーのコンテンツを格納する場所として、DynamoDB Tableを作成します。今回は以下のようにしました。

  • Table Name: user-content
  • Hash Key: user-id

Lambda Functionの作成

次に、カスタムチャネルで配信処理を行うLambda Functionを作ります。CustomChannel という名前にしました。

Lambda Functionの作り方は割愛しますが、DynamoDBへの書き込みが行うため、Execution Role(IAM Role)にDynamoDBへの書き込み権限を付与しなければいけない点に注意してください。

ソースコードは次のようになります。

const AWS = require('aws-sdk');
const ddb = new AWS.DynamoDB.DocumentClient();

exports.handler = (event, context, callback) => {
  console.log(JSON.stringify(event));
  const msg = event.Message["smsmessage"]["body"];
  const endpoints = event.Endpoints;
  const requests = [];
  for (const key in event.Endpoints) {
      const endpoint = event.Endpoints[key];
      requests.push({
        PutRequest: {
          Item: {
            'user-id': endpoint.Address,
            'content': msg
          }
        }
      });
  }
  ddb.batchWrite({
    RequestItems: {
      'user-content': requests
    }
  })
  .promise()
  .then(() => {
    callback(null, 'Success');
  })
  .catch(err => {
    callback(err);
  });
};

PinpointからLambda Functionに渡されるデータは全て event オブジェクトの中にあります。何が入ってくるのかはドキュメントを参考にします。

引用します。

  • MessageConfiguration – Amazon Pinpoint API の Messages リソースの DirectMessageConfiguration と同じ構造を持ちます。
  • ApplicationId – キャンペーンが属する Amazon Pinpoint プロジェクトの ID。
  • CampaignId – 関数が呼び出される Amazon Pinpoint プロジェクトの ID。
  • TreatmentId – A/B テストに使用されるキャンペーンバリエーションの ID。
  • ActivityId – キャンペーンによって実行中のアクティビティの ID。
  • ScheduledTime – キャンペーンのメッセージが ISO 8601 形式で配信されるスケジュール時間。
  • Endpoints – エンドポイント ID をエンドポイント定義と関連付けるマップ。各イベントデータのペイロードには最大 50 のエンドポイントが含まれます。キャンペーンセグメントに 50 以上のエンドポイントが含まれる場合、Amazon Pinpoint はすべてのエンドポイントが処理されるまで、繰り返し関数を呼び出します (最大で一度に 50 のエンドポイント)。

このうち、MessageConfigurationEndpoints を使っています(MessageConfiguration は現在は Message が渡される点に注意)。Endpoints は一度に最大50件渡されるので、Lambda Function内では各エンドポイントに対して配信するように実装する必要があります。DynamoDBへの書き込みにする場合はBatchWriteItemが丁度良いです。

PinpointにLambda Functionの呼び出し許可を与える

PinpointがLambda Functionを呼び出すことになるので、Pinpointに呼び出し許可を与える必要があります。

ここでは、Lambdaの add-permission を使います。

$ aws lambda add-permission \
--function-name CustomChannel \
--statement-id pinpoint \
--action lambda:InvokeFunction \
--principal pinpoint.us-east-1.amazonaws.com \
--region us-east-1 \
--source-arn 'arn:aws:mobiletargeting:us-east-1:<AWSアカウントID>:/*'

これでカスタムチャネルを動作させる準備が整いました。

使ってみる

あとは通常のPinpointの配信の流れと大きな変わりはありません。以下の順番で行います。

  1. セグメントを作る
  2. キャンペーンを作る

セグメントを作る

セグメントファイルは改行区切りJSONで作ります。ChannelType を指定する必要がありますが、カスタムチャネル用のものはないようなので、SMSを使います。

適当なユーザーIDとして、user-001user-002user-004に送ります。

{"ChannelType":"SMS","Address":"user-0001"}
{"ChannelType":"SMS","Address":"user-0002"}
{"ChannelType":"SMS","Address":"user-0004"}

このファイルを適当なS3バケットにアップロードしておきます。

インポートジョブの作成は、次のようにリクエストします。APIはこちら。また、PinpointがS3にアクセスするIAM Roleが事前に必要なので、作成していない場合はこちらを参考に作成してください。

$ awscurl --service mobiletargeting \
"https://pinpoint.us-east-1.amazonaws.com/v1/apps/<PinpointのApplication Id>/jobs/import" \
--region us-east-1 \
-X POST \
-d '{
  "Format": "JSON",
  "RoleArn": "<PinpointがS3にアクセスするIAM Role>",
  "S3Url": "<S3のパス>",
  "SegmentName":"ExampleSegment",
  "DefineSegment":true
}'

インポートジョブを作成したら、セグメント一覧をリクエストします。APIはこちら

$ awscurl --service mobiletargeting \
"https://pinpoint.us-east-1.amazonaws.com/v1/apps/<PinpointのApplication Id>/segments" \
--region us-east-1 \
-X GET

レスポンスの Id がセグメントのIDです。あとで使います。

{
  "Item": [
    {
      "Name": "ExampleSegment",
      "Id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "ApplicationId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "CreationDate": "2018-03-08T20:02:46.978Z",
      "LastModifiedDate": "2018-03-08T20:02:46.914Z",
      "Version": 1,
      "SegmentType": "IMPORT",
      "ImportDefinition": {
        "Size": 3,
        "S3Url": "s3://xxxxx/segments.json",
        "RoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/PinpointImport",
        "ExternalId": "xxxxxxxxxxxx",
        "Format": "JSON",
        "ChannelCounts": {
          "SMS": 3
        }
      }
    }
  ]
}

キャンペーンを作る

いよいよキャンペーンを作り、配信です。APIはこちらHookLambdaFunctionName にLambda Functionの名前を指定し ModeDELIVERY にすることで、Lambda Functionで配信処理が行われます。

$ awscurl --service mobiletargeting \
"https://pinpoint.us-east-1.amazonaws.com/v1/apps/<PinpointのApplication Id>/campaigns" \
--region us-east-1 \
-X POST \
-d '{
  "MessageConfiguration": {
    "SMSMessage": {
      "Body": "Hello!"
    }
  },
  "Schedule": {
    "StartTime": "IMMEDIATE",
    "IsLocalTime": false,
  },
  "SegmentId": "<セグメントのID>",
  "SegmentVersion": 1,
  "Name": "Segment Campaign",
  "Description": "Segment Campaign",
  "Hook": {
    "LambdaFunctionName": "CustomChannel",
    "Mode": "DELIVERY"
  }
}'

DynamoDB Tableに書き込まれていることが確認できました?

まとめ - Pinpointの配信先は自由自在。より強力なセグメント配信サービスに進化しました

Pinpointは「プッシュ通知のためのサービス」というイメージが強かったですが、EメールやSMSのサポートを経て、カスタムチャネルという可能性に満ち溢れた機能が付き、無敵のセグメント配信サービスへと進化を遂げました。モバイルアプリに限らない様々なチャネルに活用できるサービスとなっています。カスタマイズ性が非常に高いので、ほとんどのニーズに対応できると思います。「使わない」という選択肢はもう無いですねっ!

今後とも、とってもかわいいPinpointをどうぞよろしくお願いします!