LoginSignup
2
5

More than 1 year has passed since last update.

Flutter から Lambda を経由し Amazon Pinpoint で Push 通知を実装 ②

Last updated at Posted at 2022-06-19

はじめに

こちらの続きになります。

以下を行っていきます。

  • Pinpointに対してセグメントとキャンペーンを更新するLambdaを作成

  • Pinpointに対してキャンペーンを削除するLambdaを作成

  • Lambda_Layerを利用し、メソッドをモジュール化(共通化)する

    • 作成、更新、削除をモジュール化します
  • フィルタリング内容が同じ場合、セグメントを再利用するLambdaを作成

5. Pinpointに対してセグメントとキャンペーンを更新する

Pinpointに対してセグメントとキャンペーンを更新するLambdaを作成します。

スクリーンショット 2022-06-19 11.51.06.png

起動済のキャンペーンは更新できません。

更新できるキャンペーンは、キャンペーンが実行前のものに限ります。
実行前かどうかは、コンソール上でキャンペーンのステータスから確認できます。

  • ↓ステータスが完了していないため、更新可能
    スクリーンショット 2022-06-19 12.01.20.png
  • ↓ステータスが完了のため、キャンペーンの更新不可
    スクリーンショット 2022-06-19 12.02.26.png

更新するキャンペーンIDはステータスが完了でないIDを使ってください。

Lambdaが受け取るevent内容

こちらになります。

{
  "item": [
    "bags",
    "outerwear"
  ],
  "gender": "woman",
  "startTime":"2023-01-01T00:00:00+09:00"
}

スクリーンショット 2022-06-19 19.32.46.png

セグメントとキャンペーンを更新するLambdaを作成

更新する箇所以下の点です。

  • セグメントのItem属性のpantsからouterwearに変更
  • キャンペーンのpush通知の日時を2023年1月1日に変更

Lambdaで必要な情報は、キャンペーンIDです。コンソールからでも確認できます。

const application_id = process.env.AWS_PINPOINT_PROJECT_ID;

const campaign_id = '0c75d2bcf6284280822eac0892537b73';

const AWS = require('aws-sdk');
const pinpoint = new AWS.Pinpoint({ region: process.env.AWS_REGION });

function write_campaign_data(
  messages_per_second,
  ttl,
  push_title,
  campaign_title,
  push_body,
  schedule,
  segment_id
) {
  const APNS_row_content = {
    aps: {
      alert: {
        title: push_title,
        body: push_body,
      },
      sound: 'default',
      content_available: true,
    },
  };
  const GCM_row_content = {
    data: {
      title: push_title,
      body: push_body,
      jsonBody: {
        type: campaign_title,
      },
    },
  };
  return {
    AdditionalTreatments: [],
    Description: '',
    HoldoutPercent: 0,
    IsPaused: false,
    Limits: {
      Daily: 0,
      MaximumDuration: 10800,
      MessagesPerSecond: messages_per_second,
      Total: 0,
    },
    MessageConfiguration: {
      APNSMessage: {
        Action: 'OPEN_APP',
        TimeToLive: ttl,
        RawContent: JSON.stringify(APNS_row_content),
      },
      GCMMessage: {
        Action: 'OPEN_APP',
        TimeToLive: ttl,
        RawContent: JSON.stringify(GCM_row_content),
      },
    },
    Name: campaign_title,
    Schedule: {
      Frequency: 'ONCE',
      StartTime: schedule,
      Timezone: 'UTC+09',
    },
    SegmentId: segment_id,
    SegmentVersion: 1,
  };
}

exports.handler = async (event) => {
  console.log('event:', JSON.stringify(event, null, 2));

  const campaign_data = write_campaign_data(
    100, // int:MessagesPerSecond
    3600, // int:TimeToLive
    'test_title', // str:push_title
    'test_campaign', // str:campaign_title
    'test_body', // str:push_body
    event['startTime'] // str:schedule
  );
  let campaign_response;
  try {
    const params_campaign = {
      ApplicationId: application_id,
      WriteCampaignRequest: campaign_data,
      CampaignId: campaign_id,
    };
    campaign_response = await pinpoint.updateCampaign(params_campaign).promise();
    console.log('campaign_response:', JSON.stringify(campaign_response, null, 2));
  } catch (err) {
    console.error(err);
  }
  const segment_id = campaign_response['CampaignResponse']['SegmentId'];

  const segment_data = {
    Name: 'favorite_segment',
    Dimensions: {
      UserAttributes: {
        Item: {
          AttributeType: 'INCLUSIVE',
          Values: event['item'],
        },
        Gender: {
          AttributeType: 'INCLUSIVE',
          Values: event['gender'].split(','),
        },
      },
    },
  };

  try {
    const params_segment = {
      ApplicationId: application_id,
      WriteSegmentRequest: segment_data,
      SegmentId: segment_id,
    };
    const segment_response = await pinpoint.updateSegment(params_segment).promise();
    console.log('segment_response:', JSON.stringify(segment_response, null, 2));
  } catch (err) {
    console.error(err);
  }
};

前回、セグメントとキャンペーンを作成するLambdaのコードからそこまで変わっていないですね。

実行すると、セグメントの内容、キャンペーンの内容が更新されました。

スクリーンショット 2022-06-19 12.13.57.png
スクリーンショット 2022-06-19 12.14.08.png

6.Pinpointに対してセグメントとキャンペーンを削除する

スクリーンショット 2022-06-19 12.17.24.png

セグメントとキャンペーンを削除するLambdaを作成

削除したいキャンペーンIDがあれば、キャンペーンとセグメントどちらも削除できます。

const application_id = process.env.AWS_PINPOINT_PROJECT_ID;
const campaign_id = '0c75d2bcf6284280822eac0892537b73';

const AWS = require('aws-sdk');
const pinpoint = new AWS.Pinpoint({ region: process.env.AWS_REGION });

exports.handler = async (event) => {
  console.log('event:', JSON.stringify(event, null, 2));

  let campaign_response;
  try {
    const params_campaign = {
      ApplicationId: application_id,
      CampaignId: campaign_id,
    };
    const campaign_response = await pinpoint.deleteCampaign(params_campaign).promise();
    console.log('campaign_response:', JSON.stringify(campaign_response, null, 2));
  } catch (err) {
    console.error(err);
  }
  
  const segment_id = segment_response['CampaignResponse']['SegmentId'];
  
  try {
    const params_segment = {
      ApplicationId: application_id,
      SegmentId: segment_id,
    };
    await pinpoint.deleteSegment(params_segment).promise();
  } catch (err) {
    console.error(err);
  }
};

Lambda_Layerを利用し、メソッドをモジュール化(共通化)する

下記、4つのモジュールを作成し、3つのLambdaを作成します。

  • セグメントとキャンペーンを作成するモジュール
  • キャンペーンデータのモジュール
  • セグメントとキャンペーンを削除するモジュール
  • セグメントとキャンペーンを更新するモジュール
  1. セグメントとキャンペーンを作成するLambdaを作成
  2. セグメントとキャンペーンを削除するLambdaを作成
  3. セグメントとキャンペーンを更新するLambdaを作成

Lambda_Layerの利用方法はこちらの記事を参考にしてください。

セグメントとキャンペーンを作成するモジュール

ファイル名をcreate_action_pinpoint.jsとします

create_action_pinpoint.js
module.exports = async (action, write_request, application_id) => {
  const AWS = require('aws-sdk');
  const pinpoint = new AWS.Pinpoint({ region: process.env.AWS_REGION });

  try {
    // create_campaign
    if (action == 'campaign') {
      const params_campaign = {
        ApplicationId: application_id,
        WriteCampaignRequest: write_request,
      };
      const campaign_response = await pinpoint.createCampaign(params_campaign).promise();
      console.log('campaign_response:', JSON.stringify(campaign_response, null, 2));

      return campaign_response;
    }
    // create_segment
    const params_segment = {
      ApplicationId: application_id,
      WriteSegmentRequest: write_request,
    };
    const segment_response = await pinpoint.createSegment(params_segment).promise();
    console.log('segment_response:', JSON.stringify(segment_response, null, 2));

    return segment_response;
  } catch (err) {
    console.error(err);
  }
};

キャンペーンデータのモジュール

ファイル名をwrite_campaign_data.jsとします

write_campaign_data.js
module.exports = (
  messages_per_second,
  ttl,
  push_title,
  campaign_title,
  push_body,
  schedule,
  segment_id
) => {

  const APNS_row_content = {
    aps: {
      alert: {
        title: push_title,
        body: push_body,
      },
      sound: 'default',
      content_available: true,
    },
  };
  const GCM_row_content = {
    data: {
      title: push_title,
      body: push_body,
      jsonBody: {
        type: campaign_title,
      },
    },
  };
  return {
    AdditionalTreatments: [],
    Description: '',
    HoldoutPercent: 0,
    IsPaused: false,
    Limits: {
      Daily: 0,
      MaximumDuration: 10800,
      MessagesPerSecond: messages_per_second,
      Total: 0,
    },
    MessageConfiguration: {
      APNSMessage: {
        Action: 'OPEN_APP',
        TimeToLive: ttl,
        RawContent: JSON.stringify(APNS_row_content),
      },
      GCMMessage: {
        Action: 'OPEN_APP',
        TimeToLive: ttl,
        RawContent: JSON.stringify(GCM_row_content),
      },
    },
    Name: campaign_title,
    Schedule: {
      Frequency: 'ONCE',
      StartTime: schedule,
      Timezone: 'UTC+09',
    },
    SegmentId: segment_id,
    SegmentVersion: 1,
  };
};

1. セグメントとキャンペーンを作成するLambdaを作成

上記の2つのモジュールを利用して、セグメントとキャンペーンを作成するLambdaを作成しましょう。

下記のようにローカルでディレクトリとファイルを作成し、nodejsをzip化して、LambdaLayerにアップします。

self_modules % tree
.
└── nodejs
   └── node_modules
       ├── create_action_pinpoint.js
       └── write_campaign_data.js

LambdaLayerにアップします。
スクリーンショット 2022-06-19 17.54.25.png
Lambdaのコンソールからレイヤーを追加します。

スクリーンショット 2022-06-19 17.57.57.png

Lambdaのコードは以下の通りになります。

const application_id = process.env.AWS_PINPOINT_PROJECT_ID;

const create_ = require('create_action_pinpoint');
const write_campaign_data = require('write_campaign_data');

exports.handler = async (event) => {
  console.log('event:', JSON.stringify(event, null, 2));

  const segment_data = {
    Name: 'favorite_segment',
    Dimensions: {
      UserAttributes: {
        Item: {
          AttributeType: 'INCLUSIVE',
          Values: event['item'],
        },
        Gender: {
          AttributeType: 'INCLUSIVE',
          Values: event['gender'].split(','),
        },
      },
    },
  };

  const pinpoint_response = await create_('segment', segment_data, application_id);
  const response_segment_id = pinpoint_response['SegmentResponse']['Id'];
  
  const campaign_data = write_campaign_data(
    100, // int:MessagesPerSecond
    3600, // int:TimeToLive
    'test_title', // str:push_title
    'test_campaign', // str:campaign_title
    'test_body', // str:push_body
    'IMMEDIATE', // str:schedule
    response_segment_id // str:segment_id
  );

  await create_('campaign', campaign_data, application_id);
};

実行すると、セグメントとキャンペーンが作成されました。

LambdaLayerにして、モジュール化することで複数のLambdaで使用でき、コード量を減らすことができます。

以下のようにして、モジュールを呼びます。
const create_ = require('create_action_pinpoint');
const write_campaign_data = require('write_campaign_data');

セグメントとキャンペーンを削除するモジュール

次は、セグメントとキャンペーンを削除するモジュールを作成します。
ファイル名をdelete_action_pinpoint.jsとします

delete_action_pinpoint.js
module.exports = async (action, application_id, id) => {
  const AWS = require('aws-sdk');
  const pinpoint = new AWS.Pinpoint({ region: process.env.AWS_REGION });

  try {
    if (action == 'campaign') {
      const params_campaign = {
        ApplicationId: application_id,
        CampaignId: id,
      };
      const campaign_response = await pinpoint.deleteCampaign(params_campaign).promise();
      console.log('campaign_response:', JSON.stringify(campaign_response, null, 2));

      return campaign_response;
    }
    const params_segment = {
      ApplicationId: application_id,
      SegmentId: id,
    };
    const segment_response = await pinpoint.deleteSegment(params_segment).promise();
    console.log('segment_response:', JSON.stringify(segment_response, null, 2));

    return segment_response;
  } catch (err) {
    console.error(err);
  }
};

2. セグメントとキャンペーンを削除するLambdaを作成

ローカルのnode_modules内にdelete_action_pinpoint.jsを加えて、再度nodejsをzip化して、LambdaLayerにアップしましょう。

self_modules % tree
.
└── nodejs
   └── node_modules
       ├── create_action_pinpoint.js
       ├── delete_action_pinpoint.js
       └── write_campaign_data.js
const application_id = process.env.AWS_PINPOINT_PROJECT_ID;
const campaign_id = "0c75d2bcf6284280822eac0892537b73";

const delete_ = require('delete_action_pinpoint');

exports.handler = async (event) => {
  console.log('event:', JSON.stringify(event, null, 2));

  const pinpoint_response = await delete_('campaign', application_id, campaign_id);
  
  const segment_id = pinpoint_response['CampaignResponse']['SegmentId'];
  
  await delete_('segment', application_id, segment_id);
};

セグメントとキャンペーンを更新するモジュール

次は、セグメントとキャンペーンを削除するモジュールを作成します。
ファイル名をupdate_action_pinpoint.jsとします

update_action_pinpoint.js
module.exports = async (action, write_request, application_id, id) => {
  const AWS = require('aws-sdk');
  const pinpoint = new AWS.Pinpoint({ region: process.env.AWS_REGION });

  try {
    if (action == 'campaign') {
      const params_campaign = {
        ApplicationId: application_id,
        WriteCampaignRequest: write_request,
        CampaignId: id,
      };
      const campaign_response = await pinpoint.updateCampaign(params_campaign).promise();
      console.log('campaign_response:', JSON.stringify(campaign_response, null, 2));

      return campaign_response;
    }
    const params_segment = {
      ApplicationId: application_id,
      WriteSegmentRequest: write_request,
      SegmentId: id,
    };
    const segment_response = await pinpoint.updateSegment(params_segment).promise();
    console.log('segment_response:', JSON.stringify(segment_response, null, 2));

    return segment_response;
  } catch (err) {
    console.error(err);
  }
};

3. セグメントとキャンペーンを更新するLambdaを作成

ローカルのnode_modules内にupdate_action_pinpoint.jsを加えて、再度nodejsをzip化して、LambdaLayerにアップしましょう。

self_modules % tree
.
└── nodejs
   └── node_modules
       ├── create_action_pinpoint.js
       ├── delete_action_pinpoint.js
       ├── update_action_pinpoint.js
       └── write_campaign_data.js

セグメントとキャンペーンを更新するLambdaのコードは以下の通りです。

const application_id = process.env.AWS_PINPOINT_PROJECT_ID;

const campaign_id = '0c75d2bcf6284280822eac0892537b73';

const update_ = require('update_action_pinpoint');
const write_campaign_data = require('write_campaign_data');

exports.handler = async (event) => {
  console.log('event:', JSON.stringify(event, null, 2));

  const campaign_data = write_campaign_data(
    100, // int:MessagesPerSecond
    3600, // int:TimeToLive
    'test_title', // str:push_title
    'test_campaign', // str:campaign_title
    'test_body', // str:push_body
    event['startTime'] // str:schedule
  );
  const campaign_response = await update_('campaign', campaign_data, application_id, campaign_id);

  const segment_id = campaign_response['CampaignResponse']['SegmentId'];

  const segment_data = {
    Name: 'favorite_segment',
    Dimensions: {
      UserAttributes: {
        Item: {
          AttributeType: 'INCLUSIVE',
          Values: event['item'],
        },
        Gender: {
          AttributeType: 'INCLUSIVE',
          Values: event['gender'].split(','),
        },
      },
    },
  };
  await update_('segment', segment_data, application_id, segment_id);
};

フィルタリング内容が同じ場合、セグメントを再利用する

今のままですと、毎回セグメントを作成します。
フィルタリング(条件)の内容が同じセグメントが、すでにpinpointで作成済みの場合、新たなセグメントを作成せず、作成済みのセグメントを利用するLambdaを作成します。

こちらは、今後更新していきます。

参考

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5