SlackでのExperience Platform イベントのモニタリング
Adobe App Builder Webhook プロキシと統合して、SlackでExperience Platform通知を受け取る方法を説明します。 データエンジニアや管理者は、Platform実装の健全性をモニタリングするために、Adobe Experience PlatformからSlackでプロアクティブな通知を受け取る必要があります。 このチュートリアルでは、Adobe App Builderを使用してAdobe I/O EventsをSlackに接続するためのアーキテクチャと実装手順について説明します。
なぜWebhook プロキシなのか?
Adobe I/O EventsをSlack Incoming Webhookに直接接続することは、検証プロセスのプロトコルが一致しないため不可能です。
-
チャレンジ: Adobe I/O EventsでWebhookを登録すると、Adobeはエンドポイントに「チャレンジ」リクエスト(
GETまたはPOST)を送信します。 エンドポイントはこの課題を正常に処理し、特定の値を返して所有権を確認する必要があります。 -
制限: Slackの受信Webhookは、メッセージ用にJSON ペイロードを取り込むためにのみ設計されています。 Adobeの検証課題のハンドシェイクを認識したり、対応したりするロジックがありません。
-
解決策: Adobe App Builderを使用して、中間的なWebhook プロキシをデプロイします。 このプロキシは、AdobeとSlackの間に配置され、次の操作を行います。
- Adobeからのリクエストを受け取り、検証の課題に対応します。
- ペイロードをSlack互換メッセージにフォーマットし、Slackに転送します。
-
配信方法:実行時アクション。 ランタイムアクションは、Adobe App Builderにパッケージ化されています。 ランタイムアクション(web アクション以外)をイベントハンドラーとして使用すると、Adobe I/O Eventsは署名検証とチャレンジレスポンスを自動的に処理します。 ランタイムアクションは、必要なコードが少なく、組み込みのセキュリティを提供するため、推奨されるアプローチです。
アーキテクチャの概要
Adobe Developer Consoleとは?
Adobe Developer Consoleは、Adobe プロジェクト、API、資格情報を管理するための中央ポータルです。 これは、プロジェクトの作成、認証の設定、Webhookの登録をおこなう場所です。
App Builderとは?
Adobe App Builderは、開発者がクラウドネイティブなアプリケーションを構築するための包括的なフレームワークです。
-
プロビジョニング: App Builderはデフォルトで有効になっていません。機能として組織にプロビジョニングする必要があります。 組織に App Builder の使用権限があることを確認してください。
-
プロジェクトテンプレート: App Builder プロジェクトは、Developer ConsoleのApp Builder テンプレート( テンプレートからのプロジェクト > App Builder)を使用して作成されます。 テンプレートは、必要なワークスペースとランタイム環境を自動的に設定します。
-
App Builder入門ガイド:テンプレート 🔗から最初のプロジェクトをプロビジョニングして作成するには、 ドキュメントを参照してください。
Adobe I/O Runtimeとは?
Adobe I/O Runtimeは、App Builderの能力を支えるサーバーレスプラットフォームです。 開発者は、サーバーインフラストラクチャを管理することなく、HTTP要求に応答して実行されるコード(サービスとしての機能)をデプロイできます。
この実装では、Actionを使用します。 アクションは、Adobe I/O Runtime上で実行されるステートレス関数(Node.jsで記述)です。 アクションは、Adobe I/O Eventsが接続するパブリック HTTP エンドポイントとして機能します。
詳しくは、Adobe I/O Runtimeのドキュメント を参照してください。
実装ガイド
前提条件
始める前に、次の項目を確認してください。
-
Adobe Developer Console アクセス: App Builderが有効になっている組織内のシステム管理者または開発者ロール にアクセスできる必要があります。
note tip TIP App Builder プロビジョニングを検証するには、Adobe Developer Consoleにログインし、目的の組織に属していることを確認し、テンプレートからプロジェクトを作成を選択して、App Builder テンプレートが使用可能であることを確認します。 そうでない場合は、「App Builderの入手方法」のApp Builder FAQ セクションを確認してください。 -
Node.jsとnpm:このプロジェクトには、NPM (Node Package Manager)を含むNode.jsが必要です。 NPMは、Adobe CLIのインストールとプロジェクトの依存関係の管理に使用されます。
- Node.jsのダウンロード(LTS バージョンを推奨)
- npm入門ガイド - インストールを確認する方法に関するガイド。
-
aio CLI:端末を介してインストールされました:npm install -g @adobe/aio-cli -
Slack アプリ設定: 受信Webhookがアクティブ化されたワークスペースでSlack アプリを設定する必要があります。
- Slack アプリの作成
- Slack着信Webhook ガイド – このガイドに従ってアプリを作成し、Webhook URLを生成します(
https://hooks.slack.com/から始まります…)。
手順1:Adobe Developer Consoleでのプロジェクトの作成
まず、Adobe Developer ConsoleでApp Builder テンプレートを使用してプロジェクトを作成します。
- Adobe Developer Consoleにログインします
- 「テンプレートからプロジェクトを作成」を選択
- App Builder テンプレートを選択します
- プロジェクト タイトル (例:
Slack webhook integration)を入力します - 保存を選択
ランタイム環境の初期化
ターミナルで次のコマンドを実行して、プロジェクト構造を作成します。
aioにログイン
aio login
手順2:新しいApp Builder プロジェクトの初期化
aio app init slack-webhook-proxy
-
組織を選択し、Enterを押します
-
前の手順で作成したプロジェクト (例:
Slack webhook integration)を選択し、Enterを押します -
「組織でサポートされているテンプレートのみ」オプションを選択します
-
Enterを押してサンプルセクションをスキップします
-
プロンプトが表示されたら、次のコンポーネントが選択されていることを確認し(円を入力する必要があります)、Enterを押します。
- アクション:ランタイムアクションのデプロイ
- イベント:Adobe I/O Eventsに公開
- Web Assets: ホストされた静的アセットにデプロイ
-
「上」矢印と「下」矢印を使用して、受信リストに移動し、Adobe Experience Platform: リアルタイム顧客プロファイルを選択し、Enterを押します
-
汎用 アクションは自動的に生成されます
-
UIの Pure HTML/JS を選択し、Enterを押します
-
外部API名へのアクセス方法を示すサンプルアクションとして generic を保持し、Enterを押します
-
クラウドイベント形式でメッセージを作成するサンプルアクション名として publish-events を保持し、Enterを押します
アプリの初期化が完了します。
プロジェクトディレクトリに移動します
cd slack-webhook-proxy
Web アクションを追加
aio app add action
- 自分の組織でサポートされているテンプレートのみを選択し、Enterを押します
- 表示されたテーブルのpublish-events アクションを参照してください。Spaceを押してアクションを選択します。 ビデオチュートリアルに示すように、名前の横にある円が入力されている場合は、Enterを押します
- アクションに
webhook-proxyという名前を付けます
手順3:プロキシアクションコードの更新
IDEまたはテキストエディターで、次のコードを使用してファイル actions/webhook-proxy/index.jsを作成または変更します。 この実装は、Slackにイベントを転送します。 ランタイムアクション登録を使用すると、署名の検証とチャレンジ処理が自動的に行われます。
const fetch = require("node-fetch");
const { Core } = require("@adobe/aio-sdk");
/**
* Adobe I/O Events to Slack Runtime Proxy
*
* Receives events from Adobe I/O Events and forwards them to Slack.
* Signature verification and challenge handling are automatic when
* using Runtime Action registration (non-web action).
*/
async function main(params) {
const logger = Core.Logger("webhook-proxy", { level: params.LOG_LEVEL || "info" });
try {
logger.info(`Event received: ${JSON.stringify(params)}`);
// Forward to Slack
return forwardToSlack(params, params.SLACK_WEBHOOK_URL, logger);
} catch (error) {
logger.error(`Error: ${error.message}`);
return { statusCode: 500, body: { error: "Internal server error" } };
}
}
/**
* Forwards the event payload to Slack
*/
async function forwardToSlack(payload, webhookUrl, logger) {
if (!webhookUrl) {
logger.error("SLACK_WEBHOOK_URL not configured");
return { statusCode: 500, body: { error: "Server configuration error" } };
}
// Extract Adobe headers passed to runtime action
const headers = {
"x-adobe-event-code": payload["x-adobe-event-code"],
"x-adobe-event-id": payload["x-adobe-event-id"],
"x-adobe-provider": payload["x-adobe-provider"]
};
const slackMessage = buildSlackMessage(payload, headers);
const response = await fetch(webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(slackMessage)
});
if (!response.ok) {
const errorText = await response.text();
logger.error(`Slack API error: ${response.status} - ${errorText}`);
return { statusCode: response.status, body: { error: errorText } };
}
logger.info("Event forwarded to Slack");
return { statusCode: 200, body: { success: true } };
}
/**
* Builds a Slack Block Kit message from the event payload
*/
function buildSlackMessage(payload, headers) {
// Adobe passes event code as x-adobe-event-code header (available in params for runtime actions)
const eventType = headers["x-adobe-event-code"] ||
payload["x-adobe-event-code"] ||
payload.event_code ||
payload.type ||
payload.event_type ||
"Adobe Event";
const eventId = headers["x-adobe-event-id"] || payload["x-adobe-event-id"] || payload.event_id || payload.id || "N/A";
const eventData = payload.data || payload.event || payload;
return {
blocks: [
{
type: "header",
text: { type: "plain_text", text: `Event: ${eventType}`, emoji: true }
},
{
type: "section",
fields: formatDataFields(eventData)
},
{ type: "divider" },
{
type: "context",
elements: [{
type: "mrkdwn",
text: `*Event ID:* ${eventId} | *Time:* ${new Date().toISOString()}`
}]
}
]
};
}
/**
* Formats event data as Slack mrkdwn fields
*/
function formatDataFields(data, maxFields = 10) {
if (typeof data !== "object" || data === null) {
return [{ type: "mrkdwn", text: `*Payload:*\n${String(data)}` }];
}
const entries = Object.entries(data);
if (entries.length === 0) {
return [{ type: "mrkdwn", text: "_No data provided_" }];
}
return entries.slice(0, maxFields).map(([key, value]) => ({
type: "mrkdwn",
text: `*${key}:*\n${typeof value === "object" ? `\`\`\`${JSON.stringify(value)}\`\`\`` : value}`
}));
}
exports.main = main;
手順4:アクションの設定
app.config.yamlのアクション設定は重要です。 Web: noを使用して、Developer Consoleでランタイムアクションとして登録できる非web アクションを作成します。
application:
runtimeManifest:
packages:
slack-webhook-proxy:
license: Apache-2.0
actions:
webhook-proxy:
function: actions/webhook-proxy/index.js
web: no
runtime: nodejs:22
inputs:
LOG_LEVEL: info
SLACK_WEBHOOK_URL: $SLACK_WEBHOOK_URL
annotations:
require-adobe-auth: false
final: true
web: no?の理由
Web以外のアクションを使用し、Developer Consoleの「ランタイムアクション」オプションを使用して登録すると、Adobe I/O Eventsは自動的に次の操作を行います。
- チャレンジの検証を処理します(
GETとPOST) - アクションを呼び出す前にデジタル署名を確認します
- アクションの前に署名バリデーターアクションを連結します
つまり、コードはビジネスロジック(Slackへの転送)のみを処理する必要があります。
手順4:環境変数の更新
資格情報を安全に管理するには、環境変数を使用します。 プロジェクトのルートにある.env ファイルを作成または変更して、Slack Webhook URLを追加します。 .env ファイルが表示されない場合は、システムに隠しファイルを表示するようにしてください。
# ... other .env file content ...
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
手順5:アクションのデプロイ
環境変数を設定したら、アクションをデプロイします。 ターミナルでこのコマンドを実行する場合は、プロジェクトのルート、つまりslack-webhook-proxyに必ず配置してください。
aio app deploy
アクションはAdobe I/O Runtimeにデプロイされ、Developer Consoleで登録できます。
手順6:Adobe Developer Consoleでアクションを登録する
アクションがデプロイされたら、Adobe Eventsの宛先として登録します。
-
Adobe Developer Consoleに移動し、App Builder プロジェクトを開きます。
-
Workspaceを選択
-
「サービスを追加」を選択し、「イベント」を選択します。
-
商品として Adobe Experience Platform を選択します。
-
イベントのタイプとして「プラットフォーム通知」を選択します。
-
Slackで通知する特定のイベント(またはすべて)を選択し、次へを選択します。
-
OAuth資格情報🔗を選択または作成します。
-
イベント登録の詳細を設定します。
- 登録名:登録にわかりやすい名前を付けます。
- 登録の説明:他のコントリビューターが自分の行動を把握できるように、これが明示的であることを確認してください。
- 次へを選択
- 配信方法: ランタイムアクションを選択します(「Webhook」ではありません)。
- 実行時アクション: ドロップダウンから
webhook-proxyを選択します(表示されない場合はページを更新します)。
-
設定されたイベントを保存を選択します。
手順7:サンプルイベントによる検証
設定されたイベントの横にある「サンプルイベントを送信」アイコンをクリックすると、フロー全体をエンドツーエンドでテストできます。
サンプルイベントは、Slack アプリの作成時およびWebhookの作成時に設定したチャネルで送信されます。次のような内容が表示されます。
SlackとExperience Platform eventsの統合に成功しました。
一般的な問題
ここでは、プロキシを設定する際に発生する可能性のある問題と、その対処方法について説明します。
- IMS組織を表示できません:
aio app initの実行時にIMS組織のリストが表示されない場合は、次の操作を試してください。 ターミナルでaio logoutを実行し、デフォルトのweb ブラウザーでExperience Cloudからログアウトして、aio loginを再度実行します。 - アクションがドロップダウンに表示されません:
web: noがapp.config.yamlに設定されていることを確認してください。 ランタイムアクション ドロップダウンには、Web以外のアクションのみが表示されます。 デプロイ後にDeveloper Console ページを更新します。 - 署名の検証に失敗しました:これをアクティベーションログに表示すると、Adobeの組み込みバリデーターがリクエストを拒否したことを意味します。 これは、Adobeの正当なイベントのために行われるべきではありません。 イベント登録が正しく設定されていることを確認します。
- Slackがメッセージを受信しません:
SLACK_WEBHOOK_URLが.envファイルで正しく設定されており、Slack アプリで受信Webhookが有効になっていることを確認してください。 - アクションのタイムアウト:実行時アクションのタイムアウトは60秒です。 アクションに時間がかかる場合は、代わりにジャーナリングアプローチを使用することを検討してください。