HubSpot - AI Studio|HubSpotと生成AIの技術特化メディア

HubSpotカスタムコードアクション活用法|Node.js/Pythonで実装する高度なワークフロー自動化

作成者: |2026/03/12 2:30:10

「HubSpotの標準ワークフローアクションでは、やりたいことが実現できない」「外部APIとの連携を自動化したいが、Zapierを挟むと遅延やコストが気になる」——HubSpotのワークフローを本格的に活用すると、標準機能だけでは対応しきれないケースに必ず遭遇します。

HubSpotのカスタムコードアクションは、ワークフロー内でNode.jsまたはPythonのコードを直接実行できる機能です。Data Hub Professional以上(旧Operations Hub Professional以上)のプランで利用可能で、外部APIの呼び出し、複雑なデータ変換、条件分岐ロジックなど、標準アクションでは不可能な処理をワークフローに組み込めます。

本記事では、カスタムコードアクションの基本設定から、Node.js・Pythonでの具体的な実装パターン、エラーハンドリング、実務での活用ユースケースまでを体系的に解説します。

この記事でわかること

  • カスタムコードアクションの利用要件と基本的な設定手順
  • Node.jsでの実装パターン(外部API呼び出し、データ変換、CRM操作)
  • Pythonでの実装パターン(計算ロジック、通知送信、データ処理)
  • エラーハンドリングとデバッグのベストプラクティス
  • 実務で使える5つのユースケースと設計の考え方

カスタムコードアクションの概要

利用要件

カスタムコードアクションを利用するには、以下の条件を満たす必要があります。

項目要件
プランData Hub Professional以上(旧Operations Hub Professional以上)
対応言語Node.js 20(JavaScript)、Python 3.9
実行時間制限最大20秒
メモリ制限128MB
シークレット最大5個(APIキー等の安全な保管)
利用可能なnpmパッケージaxios, @hubspot/api-client, lodash 等
出力データ最大5つの出力変数(後続アクションで使用可能)

標準アクションとの使い分け

カスタムコードアクションは強力な機能ですが、標準アクションで実現できる処理には使う必要はありません。以下の表で使い分けを判断してください。

処理内容標準アクションカスタムコード
プロパティ値の更新推奨不要
メール送信推奨不要
単純な条件分岐推奨不要
外部API呼び出し不可必須
複雑なデータ変換・計算不可必須
複数レコードの一括処理不可必須
カスタムバリデーション不可必須
動的な条件分岐ロジック限定的推奨

カスタムコードアクションの設定手順

ステップ1:ワークフローにアクションを追加

ワークフローエディタで「アクションを追加」→「カスタムコード」を選択します。言語(Node.jsまたはPython)を選び、コードエディタが表示されます。

ステップ2:入力プロパティの定義

コード内で使用するCRMプロパティを「プロパティを含める」セクションで定義します。たとえば、コンタクトのメールアドレスや会社名をコード内で参照する場合、ここで対象プロパティを選択します。

ステップ3:シークレットの設定

外部APIのAPIキーやトークンは、「シークレット」として安全に保管します。シークレットはコード内で環境変数として参照でき、ワークフローの設定画面にプレーンテキストで表示されることはありません。

ステップ4:コードの記述とテスト

コードエディタにロジックを記述し、「テスト」ボタンで動作を確認します。テスト実行時には実際のCRMレコードを選択して、リアルなデータで検証できます。

ステップ5:出力変数の定義

後続のワークフローアクションで使用するデータを「出力」として定義します。外部APIから取得したスコアやステータスを出力変数に格納し、次の条件分岐で使用する連携が可能です。

Node.jsでの実装パターン

パターン1:外部APIを呼び出してデータエンリッチメント

外部のデータエンリッチメントAPIを呼び出し、コンタクト情報を自動補完する例です。

`javascript

const axios = require('axios');

exports.main = async (event, callback) => {

const email = event.inputFields['email'];

const apiKey = process.env.ENRICHMENT_API_KEY;

try {

const response = await axios.get(

https://api.clearbit.com/v2/people/find,

{

params: { email: email },

headers: { Authorization: Bearer ${apiKey} }

}

);

const { company, title } = response.data;

callback({

outputFields: {

enriched_company: company?.name || '',

enriched_title: title || '',

enrichment_status: 'success'

}

});

} catch (error) {

callback({

outputFields: {

enriched_company: '',

enriched_title: '',

enrichment_status: 'failed'

}

});

}

};

`

パターン2:取引データに基づくカスタムスコアリング

取引金額、ステージ、経過日数を組み合わせた独自のスコアリングロジックです。

`javascript

exports.main = async (event, callback) => {

const dealAmount = parseFloat(event.inputFields['amount']) || 0;

const dealStage = event.inputFields['dealstage'];

const createDate = new Date(event.inputFields['createdate']);

const now = new Date();

const daysSinceCreation = Math.floor(

(now - createDate) / (1000 60 60 * 24)

);

let score = 0;

// 金額ベースのスコア

if (dealAmount >= 10000000) score += 40;

else if (dealAmount >= 5000000) score += 30;

else if (dealAmount >= 1000000) score += 20;

else score += 10;

// ステージベースのスコア

const stageScores = {

'appointmentscheduled': 10,

'qualifiedtobuy': 20,

'presentationscheduled': 30,

'decisionmakerboughtin': 40,

'contractsent': 50

};

score += stageScores[dealStage] || 0;

// 経過日数によるペナルティ

if (daysSinceCreation > 90) score -= 10;

if (daysSinceCreation > 180) score -= 20;

const priority = score >= 60 ? 'high'

: score >= 30 ? 'medium' : 'low';

callback({

outputFields: {

deal_score: score.toString(),

deal_priority: priority

}

});

};

`

パターン3:HubSpot APIで関連レコードを取得

コンタクトに関連する会社情報をAPIで取得し、プロパティを更新する例です。

`javascript

const hubspot = require('@hubspot/api-client');

exports.main = async (event, callback) => {

const hubspotClient = new hubspot.Client({

accessToken: process.env.HUBSPOT_TOKEN

});

const contactId = event.object.objectId;

try {

const associations = await hubspotClient.crm.contacts

.associationsApi.getAll(contactId, 'companies');

if (associations.results.length > 0) {

const companyId = associations.results[0].id;

const company = await hubspotClient.crm.companies

.basicApi.getById(companyId, [

'industry', 'numberofemployees', 'annualrevenue'

]);

callback({

outputFields: {

company_industry: company.properties.industry || '',

company_size: company.properties.numberofemployees || '',

company_revenue: company.properties.annualrevenue || ''

}

});

} else {

callback({

outputFields: {

company_industry: '',

company_size: '',

company_revenue: ''

}

});

}

} catch (error) {

callback({

outputFields: {

company_industry: 'error',

company_size: '',

company_revenue: ''

}

});

}

};

`

Pythonでの実装パターン

パターン1:LTV(顧客生涯価値)の自動計算

`python

def main(event):

monthly_revenue = float(

event.get('inputFields', {}).get('monthly_revenue', 0)

)

churn_rate = float(

event.get('inputFields', {}).get('churn_rate', 5)

) / 100

gross_margin = float(

event.get('inputFields', {}).get('gross_margin', 70)

) / 100

if churn_rate > 0:

avg_lifespan_months = 1 / churn_rate

ltv = monthly_revenue gross_margin avg_lifespan_months

else:

ltv = monthly_revenue gross_margin 120

if ltv >= 10000000:

segment = 'enterprise'

elif ltv >= 3000000:

segment = 'mid-market'

elif ltv >= 500000:

segment = 'smb'

else:

segment = 'starter'

return {

"outputFields": {

"calculated_ltv": str(int(ltv)),

"customer_segment": segment,

"avg_lifespan_months": str(int(avg_lifespan_months))

}

}

`

パターン2:取引ステージ変更時のSlack通知

`python

import os

import json

from urllib.request import Request, urlopen

from urllib.error import URLError

def main(event):

deal_name = event.get('inputFields', {}).get('dealname', '不明')

deal_amount = event.get('inputFields', {}).get('amount', '0')

deal_stage = event.get('inputFields', {}).get('dealstage', '不明')

slack_webhook = os.environ.get('SLACK_WEBHOOK_URL')

message = {

"text": "取引ステージ変更通知",

"blocks": [

{

"type": "section",

"text": {

"type": "mrkdwn",

"text": (

f"取引名: {deal_name}\n"

f"金額: {deal_amount}\n"

f"新ステージ: {deal_stage}"

)

}

}

]

}

try:

req = Request(

slack_webhook,

data=json.dumps(message).encode('utf-8'),

headers={'Content-Type': 'application/json'}

)

urlopen(req)

status = 'sent'

except URLError as e:

status = f'failed: {str(e)}'

return {

"outputFields": {

"notification_status": status

}

}

`

エラーハンドリングのベストプラクティス

必ず対策すべきエラーパターン

エラーパターン原因対処法
タイムアウト(20秒超過)外部APIの応答遅延タイムアウト設定、リトライ上限
API認証エラー(401/403)トークン期限切れ、権限不足シークレットの定期更新、エラー通知
レート制限(429)API呼び出し頻度超過リトライ待機、バッチ処理
データ型エラーnull値、予期しない型デフォルト値設定、型チェック
メモリ超過大量データの処理データの分割処理、不要変数の解放

エラーが発生した場合でも、callback(Node.js)またはreturn(Python)で必ず出力を返すように実装してください。エラー時の出力にステータス情報を含めることで、後続のワークフローアクションで条件分岐による制御が可能になります。

実務で使える5つのユースケース

ユースケース1:リードエンリッチメント

フォーム送信時に、メールアドレスから企業情報を自動取得してCRMに補完します。ClearbitやApolloなどのエンリッチメントAPIと連携し、会社名、従業員数、業種、売上規模などを自動入力します。

ユースケース2:カスタムリードスコアリング

HubSpotの標準スコアリングでは対応できない、独自の重み付けロジックを実装します。行動データ(ページ閲覧、メール開封)とデモグラフィックデータ(企業規模、業種)を組み合わせた多変量スコアリングが可能です。

ユースケース3:外部システムへのリアルタイムデータ同期

取引のステージ変更や新規コンタクト作成をトリガーに、基幹システムやERPにリアルタイムでデータを同期します。REST API呼び出しで、HubSpotを起点とした双方向のデータ連携を実現します。

ユースケース4:動的な通知・アラート制御

取引金額、顧客セグメント、チームの状況に応じて、通知の内容や送信先を動的に切り替えます。標準の通知アクションでは固定的な通知しかできませんが、カスタムコードなら条件に応じた柔軟な制御が可能です。

ユースケース5:データ品質の自動チェック

CRMに入力されたデータの品質を自動検証し、不正データを検出・修正します。電話番号のフォーマット統一、住所の正規化、重複検出アラートなどに活用できます。

制約事項と注意点

セキュリティの考慮

APIキーやトークンは必ず「シークレット」機能を使って保管してください。コード内にハードコードすると、ワークフローの編集権限を持つすべてのユーザーに露出します。また、外部APIへの通信はHTTPS(TLS 1.2以上)を使用することが必須です。

パフォーマンスの最適化

20秒の実行時間制限があるため、大量のデータ処理や複数の外部API呼び出しを1回のアクションで行うことは推奨されません。処理が重い場合は、複数のカスタムコードアクションに分割するか、非同期処理の設計を検討してください。

よくある質問(FAQ)

Q1. カスタムコードアクションで使用できるライブラリに制限はありますか?

Node.jsの場合、axios、@hubspot/api-client、lodashなど一部のnpmパッケージが利用可能です。任意のパッケージをインストールすることはできません。Pythonの場合も、標準ライブラリに加えて一部の外部ライブラリが利用可能です。最新の対応パッケージリストはHubSpotの公式ドキュメントで確認してください。

Q2. デバッグはどのように行いますか?

ワークフローエディタの「テスト」機能で、実際のCRMレコードを使ったテスト実行が可能です。console.log(Node.js)やprint(Python)の出力はテスト結果画面に表示されるため、変数の値やAPIレスポンスの確認に活用できます。ワークフローの実行履歴からも各アクションの入出力値を確認できます。

Q3. カスタムコードが失敗した場合、ワークフローは停止しますか?

デフォルトでは、カスタムコードアクションがエラーで失敗すると、それ以降のワークフローステップは実行されません。エラーハンドリングを適切に実装し、エラー時にもcallback/returnで出力を返すようにすれば、後続アクションを条件分岐で制御できます。

Q4. Node.jsとPython、どちらを選ぶべきですか?

外部API連携やHubSpot APIの操作にはNode.jsが適しています。@hubspot/api-clientパッケージが利用できるため、HubSpot APIとの連携がスムーズです。一方、数値計算やデータ分析のロジックにはPythonが適しています。チームの技術スタックに合わせて選択してください。

HubSpotのカスタムコードアクションは、標準ワークフローの制約を超えた高度な自動化を実現する強力な機能です。外部API連携、複雑なデータ処理、カスタムロジックの実装により、HubSpotを企業の業務自動化基盤として最大限に活用できます。まずは小さなユースケースから始めて、段階的に活用範囲を広げていくことを推奨します。

カテゴリ: HubSpotエンタープライズ | HubSpot