カスタム コード ワークフロー アクション

ワークフローでは、「カスタムコード」アクションを使用して、JavaScriptまたはPython(「ベータ版」)を作成し、実行します。カスタム コード アクションを使用すると、HubSpot内でもHubSpot外でもワークフロー機能を拡張できます。HubSpotのAPIについて詳しくは、最新バージョンを対象とした開発者ドキュメント(英語)または古いAPIを対象とした以前の開発者ドキュメント(英語)をご確認ください。一般的なカスタム コード アクションの例は、HubSpotのプログラマブルオートメーションのユースケースで確認できます。

カスタム コード アクションでは、JavaScriptをサポートするためにNode 16.xランタイムフレームワークが使用されます。カスタム コード アクションにPythonを使用する場合、カスタム コード アクションではPython 3.9ランタイムフレームワークが使用されます。アクションが実行されると、HubSpotとAWS Lambdaによるサーバーレス機能によって、ランタイム計算が管理されます。

カスタム コード アクションの実装で一般的な問題が発生した場合は、HubSpotのヘルプをご利用ください。ただし、自分で記述したカスタムコードで問題が発生した場合は、HubSpot開発者フォーラムで問題について検索、投稿して、コードのトラブルシューティングに関するヒント、アドバイス、サポートを受けることをお勧めします。

Node.js対応ライブラリー

Node.jsを使用する場合、コードアクション内で次のライブラリーを使用できます。これらのライブラリーを読み込むには、コードの先頭で通常のrequire()関数を使用します。

  • @hubspot/api-client ^10
  • async ^3.2.0
  • aws-sdk ^2.744.0
  • axios ^1.2.0
  • lodash ^4.17.20
  • mongoose ^6.8.0
  • mysql ^2.18.1
  • redis" ^4.5.1
  • request" ^2.88.2
  • bluebird ^3.7.2
  • random-number-csprng ^1.0.2
  • googleapis ^67.0.0
注:v4 Associations APIは、NodeJS HubSpot Clientのバージョン9.0.0以降、およびNodeJS HubSpot Clientのバージョン8でサポートされています。
 

Python対応ライブラリー

Pythonを使用する場合、コードの先頭でimportステートメントを使用して、次のライブラリーを読み込むことができます。importステートメントは、from [libraryname] import [item]の形式にする必要があります(例:from redis.client import redis)。

  • requests 2.28.2
  • @hubspot/api-client ^8
  • google-api-python-client 2.74.0
  • mysql-connector-python 8.0.32
  • redis 4.4.2
  • nltk 3.8.1

標準ライブラリーから何らかの要素を取り込んで使用する場合は、importを使用できます(例:import os)。

Get started

カスタム コード ワークフロー アクションを使用するには、以下のサンプルコードを使用します。 

Code samples

NODE16X、v8
const hubspot = require('@hubspot/api-client'); exports.main = async (event, callback) => { /***** How to use secrets Secrets are a way for you to save API keys or private apps and set them as a variable to use anywhere in your code Each secret needs to be defined like the example below *****/ const hubspotClient = new hubspot.Client({ accessToken: process.env.SECRET_NAME }); let phone; try { const ApiResponse = await hubspotClient.crm.contacts.basicApi.getById(event.object.objectId, ["phone"]); phone = ApiResponse.properties.phone; } catch (err) { console.error(err); // We will automatically retry when the code fails because of a rate limiting error from the HubSpot API. throw err; } /***** How to use inputs Inputs are a way for you to take data from any actions in your workflow and use it in your code instead of having to call the HubSpot API to get that same data. Each input needs to be defined like the example below *****/ const email = event.inputFields['email']; /***** How to use outputs Outputs are a way for you to take data from your code and use it in later workflows actions Use the callback function to return data that can be used in later actions. Data won't be returned until after the event loop is empty, so any code after this will still execute. *****/ callback({ outputFields: { email: email, phone: phone } }); } /* A sample event may look like: { "origin": { // Your portal ID "portalId": 1, // Your custom action definition ID "actionDefinitionId": 2, }, "object": { // The type of CRM object that is enrolled in the workflow "objectType": "CONTACT", // The ID of the CRM object that is enrolled in the workflow "objectId": 4, }, "inputFields": { // The property name for defined inputs }, // A unique ID for this execution "callbackId": "ap-123-456-7-8" } */
NODE16X、v3
const hubspot = require('@hubspot/api-client'); exports.main = async (event, callback) => { /***** How to use secrets Secrets are a way for you to save API keys or private apps and set them as a variable to use anywhere in your code Each secret needs to be defined like the example below *****/ const hubspotClient = new hubspot.Client({ apiKey: process.env.SECRET_NAME }); let phone; try { const ApiResponse = await hubspotClient.crm.contacts.basicApi.getById(event.object.objectId, ["phone"]); phone = ApiResponse.body.properties.phone; } catch (err) { console.error(err); // We will automatically retry when the code fails because of a rate limiting error from the HubSpot API. throw err; } /***** How to use inputs Inputs are a way for you to take data from any actions in your workflow and use it in your code instead of having to call the HubSpot API to get that same data. Each input needs to be defined like the example below *****/ const email = event.inputFields['email']; /***** How to use outputs Outputs are a way for you to take data from your code and use it in later workflows actions Use the callback function to return data that can be used in later actions. Data won't be returned until after the event loop is empty, so any code after this will still execute. *****/ callback({ outputFields: { email: email, phone: phone } }); } /* A sample event may look like: { "origin": { // Your portal ID "portalId": 1, // Your custom action definition ID "actionDefinitionId": 2, }, "object": { // The type of CRM object that is enrolled in the workflow "objectType": "CONTACT", // The ID of the CRM object that is enrolled in the workflow "objectId": 4, }, "inputFields": { // The property name for defined inputs }, // A unique ID for this execution "callbackId": "ap-123-456-7-8" } */
PYTHON(全てのバージョンに適用)
import os from hubspot import HubSpot from hubspot.crm.contacts import ApiException def main(event): # How to use secrets # Secrets are a way for you to save API keys or private apps and set them as a variable to use anywhere in your code # Each secret needs to be defined like the example below hubspot = HubSpot(access_token=os.getenv('SECRET_NAME')) phone = '' try: ApiResponse = hubspot.crm.contacts.basic_api.get_by_id(event.get('object').get('objectId'), properties=["phone"]) phone = ApiResponse.properties.get('phone') except ApiException as e: print(e) # We will automatically retry when the code fails because of a rate limiting error from the HubSpot API. raise # How to use inputs # Inputs are a way for you to take data from any actions in your workflow and use it in your code instead of having to call the HubSpot API to get that same data. # Each input needs to be defined like the example below email = event.get('inputFields').get('email') # How to use outputs # Outputs are a way for you to take data from your code and use it in later workflows actions # Use the callback function to return data that can be used in later actions. # Data won't be returned until after the event loop is empty, so any code after this will still execute. return { "outputFields": { "email": email, "phone": phone } } # A sample event may look like: # { # "origin": { # # Your portal ID # "portalId": 1, # # Your custom action definition ID # "actionDefinitionId": 2, # }, # "object": { # # The type of CRM object that is enrolled in the workflow # "objectType": "CONTACT", # # The ID of the CRM object that is enrolled in the workflow # "objectId": 4, # }, # "inputFields": { # # The property name for defined inputs # }, # # A unique ID for this execution # "callbackId": "ap-123-456-7-8" # }

カスタム コード アクションを作成する

カスタム コード アクションをワークフローに追加するには、次の手順に従ってください。

  • HubSpotアカウントで、[自動化]>[ワークフロー]に移動します。
  • ワークフローの名前をクリックするか、新しいワークフローを作成します。 
  • +(プラス)アイコンをクリックし、ワークフローアクションを追加します。
  • 右側のパネルで[カスタムコード]を選択します。
 

custom-code-action-select

  • 右側のパネルで、プロパティーを設定します。
    • デフォルトでは、カスタム コード アクションはNode.js 16.xを使用します。Pythonベータ版でPythonを使ってアクションを作成する場合は、[言語]ドロップダウンメニューをクリックし、[Python]を選択します。
    • 新しいシークレット非公開アプリのアクセストークンなど)を追加するには、[シークレットを追加]をクリックします。アプリには、contactsformsなど、HubSpotから取得しようとしているデータのスコープを含める必要があります。詳しくは、HubSpotの非公開アプリに関するぺージをご確認ください。
    • ダイアログボックスで、[シークレット名]と[シークレット値]に値を入力します。
    • [保存]をクリックします。これで、以降のカスタム コード アクションでこのシークレットを選択できるようになります。
    • 既存のシークレットを編集または削除する場合は、[シークレットを管理]をクリックします。
  • カスタムコードにプロパティーを含めるには、[プロパティーを選択]ドロップダウンメニューをクリックし、プロパティーを選択します。ワークフローでは、既存のプロパティーまたは以前に書式設定されたプロパティー値を使用できます。プロパティーを選択したら、コード内で使用するプロパティー名を入力します。こちらで、カスタムコードでプロパティーを参照する方法をご確認いただけます。
  • 別のプロパティーを追加するには、[プロパティーを追加]をクリックします。各プロパティーは1回のみ追加できます。また、プロパティーには一意の「変数ID」が割り当てられている必要があります。カスタムコードでは最大50個のプロパティーを使用できます。 
  • プロパティーを削除するには、削除アイコンをクリックします。
  • コードフィールドにJavaScriptまたはPythonを入力します。
  • 例えば[プロパティー値をコピー]アクションなどで、後にワークフローにて入力として使用できるデータ出力を定義するには、次のようにします。
    • [データ出力]で、[データタイプ]ドロップダウンメニューをクリックし、データのタイプを選択します。
    • [名前]フィールドに、データ出力の名前を入力します。
    • 複数の出力を追加する場合は、[出力を追加]をクリックします。 
  • [保存]をクリックします。

workflow-custom-code

 

注:Pythonを使用している場合、コードフィールドにリントエラーは表示されません。 

カスタム コード アクションを作成する際は、次の点に留意してください。

  • コードスニペットのアクションが実行されると、def main(event):関数が呼び出されます。
  • event引数は、ワークフロー実行の詳細を含むオブジェクトです。
  • ワークフローにデータを返すには、callback()関数を使用します。この関数は、exports.main関数内で呼び出す必要があります。これは、Node.jsでのみ使用できます。 

eventオブジェクトには、以下のデータが格納されます。

//example payload { "origin": { // Your portal ID "portalId": 1, // Your custom action definition ID "actionDefinitionId": 2, }, "object": { // The type of CRM object that is enrolled in the workflow "objectType": "CONTACT", // The ID of the CRM object that is enrolled in the workflow "objectId": 4, }, // A unique ID for this execution. "callbackId": "ap-123-456-7-8" }

アクションのテストを行う

ワークフローにカスタム コード アクションを追加する際は、ワークフローを有効にする前に、コードが想定どおりに実行されることを確認するために、アクションのテストが行えます。

カスタム コード アクションをテストするには、まず、コードのテストで使用するレコードを選択してから、コードを実行します。このテストでは、カスタムアクションのコードのみが実行され、ワークフローの他のアクションは実行されません。コードの実行が完了したら、コードの出力とテストのログを表示できます。

注:カスタムコードをテストすると、コードが実行され、選択したテストレコードにあらゆる変更が適用されます。ライブレコードの更新を避けたい場合は、テスト専用のレコードを作成することをお勧めします。 

カスタム コード アクションをテストするには、以下の手順に従ってください。

  • ワークフローのタイムラインで、カスタム コード アクションをクリックします。
  • 右のサイドバーの下部にある[テストアクション]をクリックしてテストセクションを展開します。
    workflow-custom-code-test-expand
  • コードのテストで使用するレコードを選択するには、[オブジェクト]ドロップダウンメニューをクリックし、レコードを選択します。
    workflow-custom-code-action-test2
  • ワークフローで過去に書式設定されたプロパティー値を使用する場合は、書式設定されたデータのテスト値を入力します。  

  • コードを実行するには、[テスト]をクリックします。
  • 表示されるダイアログボックスで、[テスト]をクリックして、選択したレコードに対してコードをテストすることを確認します。
  • コードの実行が完了すると、サイドバーにテスト結果が表示されます。
    • ステータス:カスタム コード アクションの成功または失敗のステータス。
    • データ出力:定義されたデータ出力に対して得られた値。コードによって生成された、[データ出力]セクションでもコードエディターでも定義されていない出力の横にはアラートが表示されます。ワークフローで後で使用するには、これらの出力を追加する必要があります。
    • ログ:テスト自体に関する情報(アクションで使用されたメモリーの量、合計実行時間など)。 

      workflow-custom-code-action-test0results0
  • カスタム コード アクションを更新するには、[アクションを作成]をクリックしてアクションエディターを展開します。必要に応じてコードの更新とテストを続けます。
  • アクションのテストが完了したら、[保存]をクリックして変更を保存します。

シークレット

広く共有すべきではないものをコードに参照させなければならないこともあります。これは多くの場合、非公開アプリのアクセストークンなどの認証手段です。ワークフローアクションの定義で直接、関数がアクセスするシークレットを管理できます。カスタムコード内で複数のシークレットを使用する場合、全てのシークレット値の合計長は1,000文字以下でなければなりません。

workflow-custom-code-secrets

追加されたシークレットは環境変数として使用可能になり、以下に示すように、カスタムコードでその環境変数にアクセスできます。

const hubspot = require('@hubspot/api-client'); exports.main = (event, callback) => { return callback(processEvent(event)); };function processEvent(event) { // secrets can be accessed via environment variables const hubspotClient = new hubspot.Client({ accessToken: process.env.secretName }); hubspotClient.crm.contacts.basicApi.getById(event["object"]["objectId"], ["email", "phone"]) .then(results => { let email = results.body["properties"]["email"] let phone = results.body["properties"]["phone"] // ... }) .catch(err => { console.error(err) }) }

カスタムコードにHubSpotプロパティーを追加する

場合によって、カスタム コード アクションでオブジェクトのプロパティーを取得しなければならないことがあります。その際にはHubSpotのAPIを使用する代わりに、必要なオブジェクトのプロパティーをワークフローアクション定義に直接追加できます。プロパティーを追加して、コード内でプロパティーを参照するためのプロパティー名を設定します。カスタム コード アクションごとに最大50個のプロパティーの追加が可能です。  

プロパティーを追加すると、カスタムコードで参照できるようになります。 

const email = event.inputFields['email']; email = event.get('inputFields').get('email')

ログ

開発者にとって重要なツールは、コードによる結果を出力する機能です。問題をデバッグし、エンドユーザーへのサポートを改善するのに役立ちます。ログの出力を確認するには、ワークフローの[履歴]タブでログを表示します。  

custom_code_logs

How to Define Outputs

ワークフローの後半で使用する出力フィールドを関数で定義します。次に、右側のサイドバーで、出力するデータの型(数値、文字列、ブール値、日時、列挙、日付、電話番号など)を選択し、出力するフィールドを入力します。

出力フィールドは、使用されている言語に応じて書式設定された、JSONオブジェクトの一部にする必要があります。

callback({ outputFields: { email: email, phone: phone } }); return { "outputFields": { "email": email, "phone": phone } }
custom-code-output

コードアクションからの出力は、[プロパティー値をコピー]アクションへの入力として使用できます。これにより、値をオブジェクトのプロパティーとして保存するために別のAPI呼び出しを行う必要がなくなります。

出力を定義する際は、以下の点に留意してください。

  • 出力するデータの型が文字列形式の場合、文字列の出力値の上限は65,000文字です。この制限を超えると、OUTPUT_VALUES_TOO_LARGEエラーが発生します。
  • [プロパティー値をコピー]アクションを使用する場合は、対応するソースプロパティーとターゲットプロパティーがあることにも注意してください。
  • また、日時型プロパティーに出力をコピーする場合、出力はUNIXミリ秒形式でなければならないことにも注意してください。
custom_code_actions_output_usage

Limitations

カスタム コード アクションは20秒以内に実行を完了する必要があり、使用できるメモリーは最大128 MBです。これらの制限に違反すると、エラーが発生します。 

Retries

HubSpot APIを使用してオブジェクトのプロパティーを取得するか、カスタム コード アクションで別のHubSpot APIエンドポイントを呼び出す必要がある場合があります。他のAPI呼び出しと同様に、HubSpot APIのレート制限に従う必要があります。

  • Node.jsを使用している場合、レート制限エラーが発生してもHubSpotに呼び出しを再試行させるには、カスタム コード アクションのcatchブロックでエラーをスローする必要があります。

  • Pythonを使用している場合、レート制限エラーが発生してもHubSpotに呼び出しを再試行させるには、カスタム コード アクションのexceptブロックでエラーを報告する必要があります。

注:レート制限エラー、またはaxiosあるいは@hubspot/api-clientからの429もしくは5XXエラーによりリクエストが失敗すると、HubSpotはエラー発生の1分後から最大3日間、そのアクションを再試行します。その後の失敗は、徐々に間隔を延ばして再試行されます。再試行の間隔は最大で8時間になります。

Caveats

カスタムコードにNode.jsを使用している場合は、次の注意事項に留意してください。

  • 乱数の生成:乱数を生成するにはMath.random(英語)を使用するのが一般的ですが、異なる実行で同じ数値が生成される場合があります。これは、Math.randomは現在の時刻でシードされるためです。HubSpotは、多数のオブジェクトを同時にワークフローに登録し、実行ごとに状態をクリアするため、異なる実行でMath.randomへのシードが同じように行われる結果になります。代わりに、random-number-csprng 1.0.2ライブラリー(英語)を使用すると、暗号論的疑似乱数の生成が保証されます。
  • 変数の再利用:メモリーを節約するには、exports.main関数の外部で宣言した変数を、カスタム コード アクションの以降の実行で再利用できます。これは、データベースなどの外部サービスに接続する場合に便利ですが、カスタム コード アクションの実行ごとに一意でなければならないロジックや情報は、exports.main関数に含める必要があります。

カスタムコードにPythonを使用している場合は、次の注意事項に留意してください。

  • 変数の再利用:上記と同様に、def main関数の外部で宣言した変数は、カスタム コード アクションの以降の実行で再利用できます。
    • def main関数の外部で変数を宣言した場合、その変数に対するアラートを計画していないとしても、変数を直接参照できます。
    • 変数のアラートを計画する場合、その変数を参照する前にグローバルキーワードを使用したdef main関数内で変数を宣言できます。
a = 1 def main(event): global a a += 1

参考になりましたか?
こちらのフォームではドキュメントに関するご意見をご提供ください。HubSpotがご提供しているヘルプはこちらでご確認ください。