7-2 Custom Code Action の基礎
ワークフロー内で Node.js コードを直接実行し、外部サービスや HubSpot API と連携する。
⚡ Custom Code Action の仕様
ランタイム:Node.js 18.x(npm パッケージは @hubspot/api-client など一部プリインストール済み)
タイムアウト:20秒(超過するとワークフローはエラー扱い)
入力:ワークフローのコンタクト・プロパティ値を event.inputFields で受け取る
出力:callback() でプロパティ値を返し、後続ステップに渡せる
Custom Code Action — 基本構造
const hubspot = require(
'@hubspot/api-client');
exports.main =
async (event, callback) => {
const {
email,
firstname,
hs_object_id: contactId,
} = event.inputFields;
const client =
new hubspot.Client({
accessToken: process.env.HUBSPOT_ACCESS_TOKEN,
});
try {
const response =
await fetch(
`https://api.external-service.com/user?email=${email}`,
{ headers: {
'Authorization':
`Bearer ${process.env.EXTERNAL_API_KEY}` } }
);
const data =
await response.json();
callback({
outputFields: {
external_score: String(data.score),
external_status: data.status,
sync_timestamp:
new Date().toISOString(),
},
});
}
catch (err) {
console.error(
'Custom code error:', err.message);
callback({ outputFields: {} });
}
};
Custom Code Action — 実践例:Slack に通知する
const https = require(
'https');
exports.main =
async (event, callback) => {
const { firstname, lastname, email, dealname, amount } = event.inputFields;
const message = {
blocks: [
{
type:
'section',
text: {
type:
'mrkdwn',
text:
`🎉 *新規成約:${dealname}*\n担当者:${firstname} ${lastname} (${email})\n金額:¥${Number(amount).toLocaleString()}`,
},
},
],
};
await fetch(process.env.SLACK_WEBHOOK_URL, {
method:
'POST',
headers: {
'Content-Type':
'application/json' },
body: JSON.stringify(message),
});
callback({ outputFields: { slack_notified:
'true' } });
};
Custom Code Action — 実践例:AI でリードスコアリング
exports.main =
async (event, callback) => {
const {
jobtitle, company, num_employees,
hs_analytics_source, recent_conversion_event_name
} = event.inputFields;
const res =
await fetch(
'https://api.anthropic.com/v1/messages', {
method:
'POST',
headers: {
'x-api-key': process.env.ANTHROPIC_API_KEY,
'anthropic-version':
'2023-06-01',
'content-type':
'application/json',
},
body: JSON.stringify({
model:
'claude-haiku-4-5-20251001',
max_tokens:
256,
messages: [{
role:
'user',
content:
`以下のリード情報から0〜100のスコアと理由を JSON で返してください。
職種: ${jobtitle}, 会社: ${company}, 従業員数: ${num_employees},
流入元: ${hs_analytics_source}, コンバージョン: ${recent_conversion_event_name}
形式: {"score": 数値, "reason": "理由"}`,
}],
}),
});
const data =
await res.json();
const parsed = JSON.parse(data.content[
0].text);
callback({
outputFields: {
ai_lead_score: String(parsed.score),
ai_score_reason: parsed.reason,
},
});
};
⚠ シークレット管理:
API キーなどの機密情報は、HubSpot の「設定 → プライベートアプリ → シークレット」に登録し、
process.env.SECRET_NAME で参照します。コードに直書きしないでください。
7-3 Serverless Functions
HubSpot ホスト上で動く HTTP エンドポイント。フォーム後処理・Webhook 受信・外部連携に使う。
🌐 Serverless Functions の仕様
エンドポイント:https://your-portal.hs-sites.com/_hcms/api/function-name
ランタイム:Node.js 18.x
タイムアウト:10秒(レスポンスを返す必要がある)
認証:HubSpot Cookie(ログインユーザー)または API キーで保護可能
ファイル:テーマ内の serverless/ フォルダに配置
serverless/contact-lookup.js
const hubspot = require(
'@hubspot/api-client');
exports.main =
async (context, sendResponse) => {
const { email } = context.params;
if (!email) {
return sendResponse({
statusCode:
400,
body: { error:
'email is required' },
});
}
const client =
new hubspot.Client({
accessToken: process.env.HUBSPOT_ACCESS_TOKEN,
});
const result =
await client.crm.contacts.searchApi.doSearch({
filterGroups: [{
filters: [{ propertyName:
'email', operator:
'EQ', value: email }],
}],
properties: [
'firstname',
'lastname',
'email',
'lifecyclestage'],
limit:
1,
});
if (result.results.length ===
0) {
return sendResponse({ statusCode:
404, body: { found:
false } });
}
sendResponse({
statusCode:
200,
body: { found:
true, contact: result.results[
0].properties },
});
};
serverless.json — 関数の設定ファイル
{
"runtime":
"nodejs18.x",
"version":
"1.0",
"secrets": [
"HUBSPOT_ACCESS_TOKEN"],
"endpoints": {
"contact-lookup": {
"method":
"GET",
"file":
"contact-lookup.js"
},
"form-handler": {
"method":
"POST",
"file":
"form-handler.js"
}
}
}
7-4 Run Agent ステップ(Breeze AI 連携)
ワークフロー内で Breeze AI エージェントを呼び出し、コンタクトデータを AI で処理する。
🤖 Run Agent ステップでできること
ワークフローの「Run Agent」ステップでは、Breeze AI エージェントを指定し、コンタクトのプロパティを入力として渡すことができます。
メール文面の自動生成・問い合わせ内容の分類・スコアリング・翻訳・要約などの AI 処理を、ノーコードのワークフローステップとして組み込めます。
処理結果はコンタクトプロパティに書き戻すことも可能です。
💡 Run Agent の典型的なユースケース
リード分類:問い合わせ内容から「製品に興味あり」「サポート案件」「採用問い合わせ」を自動分類
パーソナライズ:コンタクトの属性を元に、営業メールの文面を AI が自動生成
センチメント分析:サポートチケットの感情スコアを算出し、優先度を自動設定
翻訳:多言語の問い合わせを日本語に自動翻訳してプロパティに保存
Custom Code Action との使い分け:
Run Agent は設定画面でプロンプトを書くだけで使えるノーコードの AI ステップです。
一方 Custom Code Action は Node.js でロジックを自由に書けます。
シンプルな AI 処理は Run Agent、複雑なロジックや外部 API 組み合わせは Custom Code Action を選択してください。