trocco®とTwilio APIを使ってOne to Oneマーケティングを実現するコードをChatGPTに書いてもらう

# これはなに
私はprimeNumberというデータエンジニアリングの会社にて、様々な企業のビジネス課題をデータの力で解決するお手伝いをしています。

データ活用の中でも「顧客データ分析」を実施するためには、まずは顧客情報や行動履歴といった異なる種類のデータを一つのデータ分析基盤に集約する、というところから着手し、溜まったデータを可視化/分析していくことが定石です。
一方でその次のステップとして、データの「分析」だけでなく「活用」をより高度化していきたい、と考えるタイミングが出てきます。マーケティングの文脈においては、広告/メールやその他多種多様なコミュニケーション手段の中から、お客様ごとに最適な方法で必要な情報を届けることで、リレーションを強化していくことが求められます。

One to Oneコミュニケーションを実現するためにまず思いつくことはMAツールの導入ですが、よりライトにPoC的な取り組みから小さく始めて効果を見てみたい、という場面も多いでしょう。データ活用プロジェクトに限らずですが、スモールスタート/クイックウィンの考え方は重要です。
今回ご紹介するのは、**trocco®/Twilio/BigQueryといった複数のSaaS/PaaSを組み合わせながら、顧客への個別メッセージ配信施策を手軽に実践することができる方法**です。

また、今回ご紹介する方法の中で一部プログラミング知識を要する箇所がありますが、ChatGPTを活用することでコーディング負荷を最小限に抑えるTipsもあわせて触れていきます。

# 今回のゴール
全体の流れは以下となります。
![フローチャート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/1f35b678-7617-7e6e-ce43-72bdc48bae6d.png)
(drawn by Code interpreter)
...普通にMermaid記法で描いたほうがよかったかもですね！

# 事前準備
### trocco®アカウントの作成
配信対象抽出とAPI連携処理のために、分析基盤構築・運用の支援SaaS「trocco®」を利用します。
trocco®には無料で始められるフリープランがありますが、今回利用する「プログラミングETL機能」は有償プランへのアドオンとして利用できるオプションとなりますので、ご興味のある方は料金プランページ等をご参照ください。

https://trocco.io/lp/index.html

### Twilioアカウント(無料)の作成
Twilioには無料のトライアルアカウントがあります。
検証段階ではそれで十分なので、以下のわかりやすいチュートリアルを参照し、
アカウント発行と「最初のTwilio電話番号を取得する」までを実施しましょう。

https://www.twilio.com/ja/docs/usage/tutorials/how-to-use-your-free-trial-account

番号取得まで完了したら、以下の情報を控えておいてください。
* TwilioアカウントSID
* 認証トークン
* 送信用電話番号

### データウェアハウス環境の準備
参照元のデータを格納する箱として、データウェアハウス(DWH)を用意します。
今回はGoogle CloudのDWH製品であるBigQueryを利用します。BigQueryは毎月1TBのスキャンまで無料(※記事執筆時点)ですので、気軽に検証利用ができます。

https://cloud.google.com/bigquery/pricing?hl=ja

# 実装
大まかな流れは以下となります。
1. BigQueryから、SMS送信に必要なデータ(電話番号,メッセージ本文)を抽出します
1. trocco®の「プログラミングETL」機能を使って、抽出したデータ1行ずつに対して実行するスクリプトを定義します
1. 実装したスクリプトのテストをします
1. 定義したジョブを画面上から実行してみます

BigQuery内のテーブルに何かしら送信対象のカスタマー情報が存在するという想定で、サンプルの設定を作っていきましょう。

### 1. BigQueryから、SMS送信に必要なデータ(電話番号,メッセージ本文)を抽出

まず、trocco®の画面にログインします。
ログイン後の画面にて、転送設定の「新規追加」を押します。

すると以下のように「転送元」と「転送先」を選択する画面に移ります。
今回はどちらも「BigQuery」を選択します。
![新規作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/36ecc1d9-9409-2ac1-2f2e-aef41adcdfe1.png)

次の画面では、転送元/転送先それぞれの接続情報を入力していきます。
![スクリーンショット 2023-07-13 14.40.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/783102e4-c398-2309-fba1-eb3dd8cdab0d.png)

公式ドキュメントを参照しながら必要な情報を埋めます。
転送元：BigQuery の SQL 項目にて、送信対象を抽出するクエリを記述します。
![スクリーンショット 2023-07-13 14.46.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/9d6190df-1392-8af8-f5da-9c1e835127f4.png)

ちなみにSQLクエリ生成もChatGPTは得意だったりするので、普段SQLを書く機会が多くない方などはうまく頼ると時短になりそうです。

### 2. trocco®の「プログラミングETL」機能を使って、抽出したデータ1行ずつに対して実行するスクリプトを定義

クエリと基本的な接続情報を入力したら、STEP2の画面に移ります。
![スクリーンショット 2023-07-13 15.44.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/0ee5c484-da96-595d-5f42-5388a0406721.png)

クエリ結果に基づいてテーブル定義が自動生成されます。特に変更の必要はなさそうなので、そのまま下にスクロールしていき「ETL設定」の中の「プログラミングETLを利用する」を選択します。
![スクリーンショット 2023-07-13 15.48.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/2c54351d-8e73-8820-915c-e766597fd02e.png)

展開された入力欄に、スクリプトを記述していきます。
現在、プログラミング言語としてはRubyとPythonが対応しています。今回はRubyで実装します。

Twilio APIをRubyスクリプトから叩くには、どのように記述していけばいいでしょうか。ChatGPT先生に聞いてみましょう。
![スクリーンショット 2023-07-13 15.49.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/d4a2802c-665d-e8b0-30ac-e2125ee341df.png)

```ruby
require 'twilio-ruby'

# あなたのTwilioアカウントSIDと認証トークン
account_sid = 'your_account_sid'
auth_token = 'your_auth_token'

# Twilioクライアントの初期化
@client = Twilio::REST::Client.new(account_sid, auth_token)

# SMSの送信
message = @client.messages.create(
  from: 'your_twilio_number',  # Twilioから提供される電話番号
  to: 'recipient_number',  # 送信先の電話番号
  body: 'Hello! This is a test SMS from Twilio!'  # メッセージ本文
)

puts message.sid
```

いい感じですね。
提案されたコードではTwilioが提供するRuby SDKライブラリを用いていますが、標準ライブラリでHTTP APIを叩くことができれば環境を問わず実行できそうです。

> twilio-ruby ライブラリを使わずに、HTTP APIを利用する方針で実装できますか？

```ruby
require 'net/http'
require 'uri'

# TwilioのAPIエンドポイント
uri = URI('https://api.twilio.com/2010-04-01/Accounts/your_account_sid/Messages.json')

# あなたのTwilioアカウントSIDと認証トークン
account_sid = 'your_account_sid'
auth_token = 'your_auth_token'

# リクエストの設定
req = Net::HTTP::Post.new(uri)
req.basic_auth account_sid, auth_token
req.set_form_data(
  'From' => 'your_twilio_number',
  'To' => 'recipient_number',
  'Body' => 'Hello! This is a test SMS from Twilio!'
)

# リクエストの送信
res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
  http.request(req)
end

# 応答の確認
case res
when Net::HTTPSuccess then
  puts "Message sent successfully: #{res.body}"
else
  puts "Message failed to send: #{res.body}"
end
```

いいですね。もうほとんどこのまま使えそうです。

提案されたコードを、trocco®のプログラミングETL機能で動かすために調整をしていきましょう。
プログラムの書き方を知るために、以下の機能ドキュメントを読んでみます。
https://documents.trocco.io/docs/programming-etl

`before_action` 関数にて共通的な変数を定義しておき、
`transform_row` 関数で実際に送信APIを叩く処理を記述すればよさそうですね。
また、status, response_body といった処理結果も念のため出力データに渡して、処理履歴テーブルとして保存しておきましょう。

```ruby
require 'net/http'
require 'uri'

class Etl < EtlBase
  def before_action
    # TwilioのAPIエンドポイント
    @uri = URI('https://api.twilio.com/2010-04-01/Accounts/your_account_sid/Messages.json')

    # あなたのTwilioアカウントSIDと認証トークン
    @account_sid = 'your_account_sid'
    @auth_token = 'your_auth_token'
  end

  def transform_row(row)
    # リクエストの設定
    req = Net::HTTP::Post.new(@uri)
    req.basic_auth @account_sid, @auth_token
    req.set_form_data(
      'From' => row["from_number"],
      'To' => row["to_number"],
      'Body' => row["body"]
    )

    # リクエストの送信
    res = Net::HTTP.start(@uri.hostname, @uri.port, :use_ssl => @uri.scheme == 'https') do |http|
      http.request(req)
    end
    row["response_body"] = res.body

    # 応答の確認
    case res
    when Net::HTTPSuccess then
      puts "Message sent successfully: #{res.body}"
      row["status"] = "success"
    else
      puts "Message failed to send: #{res.body}"
      row["status"] = "failed"
    end

    row
  end
end
```

これでメインの処理ロジックが定義できました。

### 3. テスト

手直ししたスクリプトが正しいかどうか、画面上でテストしてみましょう。
コード入力画面右側の「テストデータ」に表示されているデータを使って、実際にスクリプトを動かしてみます。
![スクリーンショット 2023-07-13 16.20.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/33ee5404-08a0-04be-2980-fb49d420c1d3.png)

手元のスマホを見てみると
![IMG_1125.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/09fe6dbc-db5d-989b-745a-c9c7b70de2d3.jpeg)
メッセージが届いていました！

スクリプトの動作確認ができたので、設定を保存しましょう。

### 4. 実行

作成した転送設定は画面上の「実行」ボタンからアドホックに実行することもできますし、スケジュール設定されたワークフローから呼び出すこともできます。
![スクリーンショット 2023-07-13 16.31.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511608/4ade0180-7166-b4f8-ebda-3e5a9a410de1.png)

# まとめ
以上で、実行環境のインフラ等を用意することなく、データ抽出とメッセージ配信施策の実施までの流れをクイックに実装することができました。
このような処理をMAツールを導入する以外の方法で実現しようとした場合、Cloud FunctionsやAWS Lambda等のサーバーレスサービスを用いて実現することも有力な選択肢になると思います。一方で、元データの取込/更新や抽出対象セグメントのリフレッシュ処理からその後の施策実行までを一貫して一つのサービスで管理できるというのは、データマネジメント全般を支援できるtrocco®ならではの利点です。

# 最後に
今回のような、データ活用の取り組みを「いまあるものから小さく素早く始めてみたい」といったお悩みに応えるソリューションサービスを提供しています。ご興味のある方はぜひお問い合わせください。

https://primenumber.co.jp/solution/