レッスン18:Webhookを通じた外部サービスとの連携
WebhookとはHTTPベースのコールバック関数であり、外部サービスが何らかのイベントを通知するために呼び出し、データのペイロードとともに送信します。Webhookにより、異なるウェブアプリやサービスが互いに通信できるようになります。
Webhookを呼び出すサービスの例としては、以下が挙げられます:
- GitHub:リポジトリにコミットがプッシュされたとき
- Dropbox:ドキュメントが更新されたとき
- WooCommerce:注文が追加されたとき
- Microsoft Teams:リッチテキストメッセージを受信してパブリックチャンネルに投稿するとき
- ConvertKit:サブスクライバーが有効化されたとき
Gato GraphQLを使えば、Webhookとして機能するPersisted Queryを作成できます:
- Persisted QueryはそれぞれのURLで公開されているため、Webhookのターゲットとして使用できます
- 各Persisted Queryは、特定のWebhookのみを専門的に処理できます
このチュートリアルレッスンでは、ConvertKitと連携するためのPersisted Queryを作成します。
Webhookのドキュメントを確認する
最初のステップは、そのウェブサイトのドキュメントを読み、ペイロードを通じてどのようなデータが送信されるかを理解することです。
ConvertKitのWebhookを分析すると、サブスクライバー関連のイベントは以下のようなJSONペイロードとともにPOSTリクエストをURLに送信します:
{
"subscriber": {
"id": 1,
"first_name": "John",
"email_address": "John@example.com",
"state": "active",
"created_at": "2018-02-15T19:40:24.913Z",
"fields": {
"My Custom Field": "Value"
}
}
}ペイロードからデータを抽出する
リクエストはPOSTで送信されるため、HTTPリクエストのボディからデータを抽出する必要があります(これは**HTTP Request via Schema**拡張機能によってサポートされています)。
HTTPリクエストがGETで実行される場合、Persisted QueryはURLパラメータから直接データ項目を取得できます。
このGraphQLクエリはリクエストのボディを取得してJSONオブジェクトに変換します。次に、JSONオブジェクトから"subscriber.first_name"と"subscriber.email_address"を抽出し、動的変数としてエクスポートします:
query ExtractPayloadData {
body: _httpRequestBody
bodyJSONObject: _strDecodeJSONObject(string: $__body)
subscriberFirstName: _objectProperty(
object: $__bodyJSONObject,
by: { path: "subscriber.first_name" }
)
@export(as: "subscriberFirstName")
subscriberEmail: _objectProperty(
object: $__bodyJSONObject,
by: { path: "subscriber.email_address" }
)
@export(as: "subscriberEmail")
}**HTTP Request via Schema**拡張機能を使用すると、以下のフィールドを通じて現在のHTTPリクエストのすべてのデータを取得できます:
_httpRequestBody: HTTPリクエストのボディ_httpRequestClientHost: クライアントのホスト_httpRequestClientIP: クライアントのIPアドレス(サーバーが適切に設定されていない場合はnull)_httpRequestCookie: リクエストのCookie値_httpRequestCookies: リクエストのCookie一覧_httpRequestDomain: リクエストされたURLのドメイン_httpRequestFullURL: リクエストされたURL(クエリパラメータを含む)_httpRequestHasCookie: リクエストに特定のCookieが含まれているか?_httpRequestHasHeader: リクエストに特定のヘッダーが含まれているか?_httpRequestHasParam: リクエストに特定のパラメータが含まれているか?_httpRequestHeader: リクエストのヘッダー値_httpRequestHeaders: リクエストのヘッダー一覧_httpRequestHost: リクエストされたURLのホスト_httpRequestMethod: リクエストメソッド_httpRequestStringParam:?param=value形式のパラメータ値(POSTまたはGET経由)_httpRequestStringListParam:?param[]=value1¶m[]=value2形式のパラメータ値(POSTまたはGET経由)_httpRequestParams: POSTまたはURLクエリ経由で渡されたパラメータ_httpRequestProtocol: リクエストのプロトコル_httpRequestQuery: クエリパラメータの文字列_httpRequestReferer: リクエストのリファラー_httpRequestRequestTime: リクエスト開始時のタイムスタンプ_httpRequestScheme: リクエストされたURLのスキーム_httpRequestServerIP: サーバーのIPアドレス_httpRequestURL: リクエストされたURL(クエリパラメータなし)_httpRequestURLPath: リクエストされたURLの絶対パス(「/」から始まる)_httpRequestUserAgent: ユーザーエージェント
データを使ってアクションを実行する
ペイロードからデータを抽出したら、そのデータを使って何らかのアクションを実行できます。
このGraphQLクエリはsubscriber.subscriber_unsubscribeイベントを処理し、登録解除した人にフィードバックを求めるメールを送信します。
query CreateEmailMessage
@depends(on: "ExtractPayloadData")
{
emailMessageTemplate: _strConvertMarkdownToHTML(
text: """
Hey {$subscriberFirstName}, it's sad to let you go!
Please be welcome to complete [this form](https://forms.gle/FpXNromWAsZYC1zB8) and let us know if there is anything we can do better.
Thanks. Hope to see you back!
"""
)
emailMessage: _strReplaceMultiple(
search: ["{$subscriberFirstName}"],
replaceWith: [$subscriberFirstName],
in: $__emailMessageTemplate
)
@export(as: "emailMessage")
}
mutation SendEmail @depends(on: "CreateEmailMessage") {
_sendEmail(
input: {
to: $subscriberEmail
subject: "Would you like to give us feedback on how we can improve?"
messageAs: {
html: $emailMessage
}
}
) {
status
}
}