案件ごと・月ごとの粗利がHubSpotで見えないのは、原価を入れる場所が無いからではなく、会計に計上された実績がHubSpotに入ってくる経路と、案件×月で集計する器の2つが無いからです。 この記事では、その経路をつくる連携アプリと、器をつくるHubSpot標準機能の組み合わせで、この2つを補う方法を解説します。 2つがそろうと、締めた後ではなく進行中に、案件別・月別の売上・原価・粗利率が営業とPMの画面に出るようになります。
案件ごと・月ごとの粗利がHubSpotで見えないのは、原価を入れる場所が無いからではなく、会計に計上された実績がHubSpotに入ってくる経路と、案件×月で集計する器の2つが無いからです。 この記事では、その経路をつくる連携アプリと、器をつくるHubSpot標準機能の組み合わせで、この2つを補う方法を解説します。 2つがそろうと、締めた後ではなく進行中に、案件別・月別の売上・原価・粗利率が営業とPMの画面に出るようになります。
ブログ目次
HubSpotゴールドパートナーのStartLinkが、HubSpot導入・AI活用・CRM整備・業務効率化までをまとめて支援しています。記事で気になったテーマを、そのまま相談ベースで整理できます。
案件ごと・月ごとの粗利がHubSpotで見えないのは、原価を入れる場所が無いからではなく、会計に計上された実績がHubSpotに入ってくる経路と、案件×月で集計する器の2つが無いからです。 この記事では、その経路をつくる連携アプリと、器をつくるHubSpot標準機能の組み合わせで、この2つを補う方法を解説します。 2つがそろうと、締めた後ではなく進行中に、案件別・月別の売上・原価・粗利率が営業とPMの画面に出るようになります。
「今月、この案件はいくら儲かっているんだろう」——多くの会社で、この問いに即答できるのは経理が月次を締めた後だけです。
多くの会社では、案件の売上は営業が、原価は経理が、月次の請求状況はまた別の担当者が持っています。3つとも別々の場所で生まれ、別々のタイミングで確定するため、案件ごと・月ごとに突き合わせる作業は、結局は月末の手作業になります。手作業である以上、まだ進行中の案件には反映されません。「儲かっていそうだ」という感覚だけで、次の見積や人員の配置を決めることになります。
この記事では、なぜこの状態が起きるのかを構造的に説明したうえで、HubSpotの標準機能と連携アプリの組み合わせで、進行中の案件でも売上・原価・粗利率が見える状態を作る方法を解説します。次の5点がわかります。
まず、HubSpotという製品そのものの標準機能を確認します。プロパティとオブジェクトだけで、案件ごと・月ごとの売上と原価がどこまで出せるのかを見ていきます。
HubSpotの取引(Deal)が標準で持つ、金額に関わるプロパティは、契約金額や年間契約金額、月次経常収益など、いずれも売上側の数字です。原価や粗利にあたる標準プロパティは、取引には1つもありません。「HubSpotには原価を入れる場所がそもそも無い」と誤解されがちですが、正確には少し違います。
取引に紐づく商品項目(見積・契約の明細を1行ずつ表すレコード)には、原価にあたる項目が標準で用意されています。ただしこれは、見積を作る際に担当者が入力する想定の原価です。実際に外注先へいくら支払ったか、実績の金額とは連動していません。場所はあるが、そこに入っているのは実績ではなく見積時点の見立てである、というのが正確な理解です。
もう1つの問題は、単位のずれです。案件(取引)は1案件で1レコードですが、請求や支払いは月ごとに発生します。継続する案件であれば、1つの取引に対して、複数月分の請求と支出が発生し続けます。取引という単位のまま金額を足し込むと、「今月分」がどれなのかが分からなくなります。
売上は営業が受注時に入力し、原価は経理が支払い処理の中で把握し、しかも月単位で発生し続ける。この3つがHubSpotの標準機能の中でつながっていないため、案件ごと・月ごとの粗利は、会計が月次を締めて初めて算出できる数字になります。
足りないのは、原価を入れる入れ物ではありません。 ①会計に計上された実績がHubSpotに入ってくる経路、②その実績を案件×月で集計する器——この2つです。
足りない2つの正体がわかれば、打ち手は決まります。
| 足りないもの | 何が起きるか | 補う手段 |
|---|---|---|
| ① 実績が入ってくる経路 | 会計の実績データがHubSpotに存在しないため、原価は締めるまで分からない | 連携アプリ |
| ② 案件×月で集計する器 | 個々の取引が並ぶだけで、合計する場所が無い | HubSpot標準機能で作るパイプライン設計 |
この2つを補う構成の一例が、経路をつくる連携アプリ「Sync for freee」と、器をつくる「請求取引パイプライン」の組み合わせです。Sync for freeeは、HubSpotゴールドパートナーであるStartLinkが提供しています。次の章から、それぞれ具体的に見ていきます。
HubSpotの取引情報とfreee会計を双方向でつなぐ連携アプリが、Sync for freeeです。取引の商品項目をfreeeの見積書・請求書として発行し、逆にfreee側で発生した収入・支出をHubSpotのレコードとして取り込みます。この「逆方向」の連携が、経路の実体です。HubSpotマーケットプレイスで公開されており、StartLinkが開発・提供しています。

取引に登録した商品項目は、そのままfreee側の見積書・請求書として発行できます。営業がHubSpotで入力した金額と、実際に発行される請求書の金額がずれることがなく、売上側の実績はここで確定します。
取引の画面から、外注費や仕入といった支出も直接freeeへ登録できます。案件ごとに支出まで実績で追いたい企業向けの機能で、エンタープライズプラン以上でご利用いただけます。 下の画面は、ある取引に紐づけて登録した支出の一覧です。

freee側で確定した収入・支出は、「freee取引」というレコードとして自動的にHubSpotへ取り込まれます。ここまでで、①の経路は完成しています。会計の実績が、確かにHubSpotの中に存在するようになりました。
ただし、取り込まれた直後のfreee取引は、下の画面のように1件ずつフラットに並ぶだけです。「この案件の、この月はいくら儲かったのか」を出すには、これを案件×月でまとめる場所が別に必要になります。②の器が、まだ無いということです。

より詳しい設定手順は、Sync for freeeユーザーガイドにまとめています。
経路ができたら、次は器です。ここはHubSpotの標準機能だけで作ります。データ連携や自動化を高度に扱うなら Data Hub という選択肢がありますが、この構成に限っては、標準のワークフローで組み立てられます。
考え方はシンプルです。案件そのものを表す取引(以下、親取引)とは別に、「請求取引パイプライン」という専用のパイプラインを1つ作り、そこに請求月ごとの取引(以下、子取引)を作ります。たとえば1つの案件が3か月続くなら、その下に「1月分」「2月分」「3月分」という3つの子取引がぶら下がる形です。freee取引は、該当する月の子取引と、案件本体である親取引の両方に関連付けます。両方に直接関連付けることで、月次の粗利も、案件全体の累計粗利も、それぞれ別々の場所で単純に合計するだけで出せるようになります。

デモ環境で実際に組んだ請求取引パイプラインです。取引名を「{親取引のレコードID}_{請求年月}」にしておくと、どの案件の何月分かが一覧のまま読み取れます。
子取引を毎月手作業で作るのでは、結局また「誰かが忘れる」問題に戻ってしまいます。ここはワークフロー(HubSpotの自動化機能)で完全に自動化します。freee取引が取り込まれたタイミングで、その発生月に対応する子取引が無ければ新しく作り、既にあればそこに関連付けるだけ、という動きです。この「無ければ作る、あれば紐づける」という判定は、案件と発生月から機械的に組み立てた識別用の文字列(請求キー)を、取引側で重複禁止の項目として持たせることで実現しています。担当者が意識する場面は、実質的にありません。具体的なプロパティの内部名とワークフローの設定値は、7章にまとめています。
子取引・親取引には、それぞれ「収入合計」「支出合計」というロールアップ集計プロパティ(関連付いたレコードの値を自動で合計するプロパティ)を用意します。ここに、関連付いたfreee取引の金額が自動で積み上がります。粗利・粗利率はその2つから計算式で求めるだけなので、freee取引が増えるたびに、案件全体の数字も、その月の数字も、両方リアルタイムに近い形で更新されます。粗利・原価率・粗利率の計算式は、7章にそのまま転記できる形で載せています。

子取引のレコードから見た、その月に関連付いたfreee取引です。この収入と支出がそのまま合計され、次章の「収入合計」「支出合計」になります。
経路と器がそろうと、取引のレコード画面に次のような数字が並びます。下の画面は、デモ環境で実際に組んだものです。
| 表示される数字 | 案件(親取引)レコード | 月次(子取引)レコード |
|---|---|---|
| 売上 | 案件全体の累計 | その月に確定した分 |
| 原価 | 案件全体の累計 | その月に確定した分 |
| 粗利 | 累計の売上 − 累計の原価 | 当月の売上 − 当月の原価 |
| 粗利率 | 累計ベースで自動計算 | 当月ベースで自動計算 |

こちらが月次(子取引)のレコードです。その月に確定した売上と原価だけが集計され、粗利率がその場で出ています。

同じプロパティが、案件(親取引)では案件全体の累計として集計されます。画面の作りは同じで、集計される範囲だけが違います。
営業やPMは、freeeの画面を開かなくても、HubSpotの取引レコードを見るだけでこの数字を確認できます。
| 見る人 | 見る場面 | レポートで見るもの |
|---|---|---|
| 営業・PM | 案件の進行中 | 案件別の粗利率一覧(低い順) |
| 経営層 | 月次会議 | 月次の粗利推移(受注額ではなく粗利で見る) |
| 案件責任者 | 月末の振り返り | 想定していた原価との差分 |
| 経理 | 締め後の確認 | 未入金の請求一覧 |
ここから先は、実際に設定を行う担当者向けの内容です。仕組みの理解としては前章までで完結しています。
| # | 作るもの | 内容 |
|---|---|---|
| ① | 請求取引パイプライン | 1本。ステージは「未決済」「決済済み」の2つだけ |
| ② | プロパティ | freee取引に5項目(発生年月・親取引ID・請求キー・収入額・支出額)を追加し、取引に新しいグループ「原価・粗利」で7項目を作る |
| ③ | ワークフロー | 1本。アクションは2つ(レコードを作成/関連付けを作成)だけで、分岐もカスタムコードも使いません |
freee取引はSync for freeeが作成するオブジェクトです。「設定」>「プロパティー」でオブジェクトを「freee 取引」に切り替え、次の5項目を自分で作成します(表の1行目「発生日」だけは連携時点ですでに用意されています)。
| ラベル | 内部名 | 型 | 内容 |
|---|---|---|---|
| 発生日 | a31008970_issue_date |
日付 | freeeでの取引発生日。連携時点ですでに用意されている |
| 発生年月 | issue_month |
1行テキスト(計算) | 発生日から YYYY-MM の形式を生成 |
| 親取引ID | parent_deal_id |
数値(プロパティー同期) | 同期元=取引のレコードID。複数一致する場合は「最初に作成されたレコード」 |
| 請求キー | billing_key |
1行テキスト(計算) | 親取引IDと発生年月をつなげた、識別用の文字列 |
| 収入額 | income_amount |
数値(計算) | 収支区分が「収入」のときだけ金額が入り、それ以外は0 |
| 支出額 | expense_amount |
数値(計算) | 収支区分が「支出」のときだけ金額が入り、それ以外は0 |
計算式はそのまま転記できます。
発生年月 issue_month
if(is_known([properties.発生日]),
concatenate(number_to_string(year([properties.発生日])), "-",
if((month([properties.発生日]) < 10),
concatenate("0", number_to_string(month([properties.発生日]))),
number_to_string(month([properties.発生日])))),
"")
親取引ID parent_deal_id は計算式ではなく「プロパティー同期」です。次の3点を設定します。
| 項目 | 設定値 |
|---|---|
| 同期元オブジェクト | 取引 |
| 同期元プロパティー | レコードID |
| 複数一致する場合 | 最初に作成されたレコード |
案件の親取引は子取引よりも先に作られるため、「最初に作成されたレコード」を選ぶことで、あとから子取引が関連付いても値が変わりません。なお、Sync for freeeが同梱する「合算親取引ID」(consolidated_parent_deal_id)とは別物です。 こちらは合算請求機能で使うプロパティで、今回作成する親取引IDとは用途が異なるため、プロパティを探すときに取り違えないよう注意してください。
請求キー billing_key
if(is_known([properties.親取引ID]),
if(is_known([properties.発生日]),
concatenate(number_to_string([properties.親取引ID]), "_",
number_to_string(year([properties.発生日])), "-",
if((month([properties.発生日]) < 10),
concatenate("0", number_to_string(month([properties.発生日]))),
number_to_string(month([properties.発生日])))),
""),
"")
発生年月をそのまま使わず、発生日から年月を組み立て直している点に注意してください。文字列のプロパティを concatenate() にそのまま渡すと、式の検証は通っても実行結果が空になることがあります。number_to_string() を通した値であれば問題なく連結できます。
収入額 income_amount / 支出額 expense_amount
収入額: if([properties.収支区分] == "income", [properties.金額], 0)
支出額: if([properties.収支区分] == "expense", [properties.金額], 0)
この請求キーが、次の取引側のプロパティと合流する接着剤になります。
取引には(子取引・親取引で共通の設定として)「原価・粗利」という新しいプロパティグループを作り、次の7項目を用意します。
| ラベル | 内部名 | 型 | 内容 |
|---|---|---|---|
| 請求キー | billing_key_unique |
単一行テキスト(一意の値) | ワークフローが書き込む。freee取引側の請求キーと一致させる文字列 |
| 請求対象年月 | billing_month |
計算 | パイプラインが請求取引パイプラインのときだけ、クローズ日から年月を取り出す |
| 収入合計 | rollup_income_total |
ロールアップ集計 | 関連付いたfreee取引の収入額を合計 |
| 支出合計 | rollup_expense_total |
ロールアップ集計 | 関連付いたfreee取引の支出額を合計 |
| 粗利 | gross_profit |
計算 | 収入合計 − 支出合計 |
| 原価率 | cost_rate |
計算(表示形式:パーセンテージ) | 支出合計 ÷ 収入合計 |
| 粗利率 | gross_margin_rate |
計算(表示形式:パーセンテージ) | (収入合計 − 支出合計)÷ 収入合計 |
計算式はそのまま転記できます。
請求対象年月 billing_month
if string(pipeline) equals '{請求取引パイプラインのID}' then (if is_present(closedate)
then concatenate(number_to_string(year(closedate)), '-',
if month(closedate) < 10 then concatenate('0', number_to_string(month(closedate)))
else number_to_string(month(closedate))) else '') else ''
粗利 gross_profit
rollup_income_total - rollup_expense_total
原価率 cost_rate
if rollup_income_total > 0 then round_nearest((rollup_expense_total / rollup_income_total), 4) else 0
粗利率 gross_margin_rate
if rollup_income_total > 0 then round_nearest(((rollup_income_total - rollup_expense_total) / rollup_income_total), 4) else 0
{請求取引パイプラインのID} の部分は、実際には請求取引パイプラインのIDに置き換えます。IDは、パイプラインの設定画面のURLから確認できます。
billing_key_unique は「単一行テキスト・一意の値(重複禁止)」で作成します。一意の値のフラグはプロパティの作成時にしか指定できず、あとから追加することはできません。 作成の時点で必ず設定してください。
対象はfreee取引オブジェクトです。
| 項目 | 設定値 |
|---|---|
| 登録トリガー | 請求キーに値がある(値が入力されている) |
| 再登録 | オフ |
| アクション1 | レコードを作成(取引)。取引ステージ=未決済、取引名=freee取引の請求キー、クローズ日=freee取引の発生日をコピー、請求キー=freee取引の請求キー。作成と同時に、登録中のfreee取引と関連付ける |
| アクション2 | 関連付けを作成。「プロパティーが一致するレコード」を選択し、freee取引の請求キー ↔ 取引の請求キー で一致させる |
分岐もカスタムコードも要りません。billing_key_unique を一意の値にしているため、同じ請求キーの取引がすでにあれば、アクション1の「レコードを作成」は重複作成されず、アクション2が請求キーの一致で関連付けるだけになります。初回は作成+関連付け、2件目以降は関連付けのみ、という動きです。
concatenate() に渡す前に、必ず number_to_string() を経由させます。親取引IDのような数値をそのまま渡しても空文字になりますし、発生年月のようにすでに計算プロパティ化された文字列をそのまま渡しても、式の検証は通るのに実行結果が空になることがあります。請求キーの式が発生年月を再利用せず発生日から年月を組み立て直しているのはこのためで、原因は逆方向でも対処は同じ、「number_to_string() を通した値だけを連結する」に集約されますround_nearest)をかけたうえで、プロパティの表示形式を「パーセンテージ」にします。丸めないと、画面に長い小数がそのまま表示されます| 項目 | 内容 |
|---|---|
| Sync for freeeのプラン | 案件ごとの原価を取引の画面から登録する機能は、エンタープライズプラン以上でご利用いただけます |
| HubSpotのプラン | Professional以上(ワークフロー・計算プロパティ・ロールアップ集計を使うため) |
| Data Hub | データ連携や自動化を高度に扱える選択肢です。この構成に限っては、標準のワークフローアクションだけで完結します |
| 権限 | プロパティ・パイプライン・ワークフローの作成、レコードページの編集ができる権限 |
正直な限界も共有します。1つのfreee取引を複数の案件に按分することはできません。社内の人件費・工数も含まれません。freeeに計上されるのは外注費など実際の支払いだけなので、自社の人件費を原価に含めたい場合は別の仕組みが必要です。また、子取引は案件数×継続月数の分だけ増えていくため、レポートやビューは必ずパイプラインで絞り込んで使う必要があります。
案件単位の粗利を見る方法は、この記事で扱った「会計の実績を集約する」やり方のほかに、見積の商品項目に想定原価を持たせて、受注前から粗利を追う方法もあります。
| 観点 | 本記事の方法(会計の実績を集約) | 想定原価を商品項目で持つ方法 |
|---|---|---|
| 原価の出どころ | freeeに計上された実際の支出 | 見積時の想定原価・外注費の手入力 |
| 向いている場面 | 実績ベースで、進行中〜締め後の粗利を追いたい | 受注前の見積段階から粗利を追いたい |
後者の詳しい設計は、受託・コンサル業の案件別収支をHubSpotで可視化するで解説しています。両方を併用し、見積段階は想定原価、確定後は会計の実績で見る、という運用も可能です。
まずは、直近3か月の案件を1つ選び、その案件の売上・外注費が、今どこに(誰の頭の中に、どのExcelに)散らばっているかを書き出してみてください。書き出せた項目の数だけ、経路と器で拾える情報があります。
Money Forwardをお使いの場合は、同じ考え方をSync for Money Forwardで実現できます。経路をアプリで作り、器をパイプラインで作るという基本構造は共通です。
入りません。freeeに計上されるのは外注費など実際の支払いだけで、自社の人件費は会計上の支出として発生しないためです。社内工数まで含めた原価管理を行いたい場合は、プロジェクト別原価管理で扱う工数集計の仕組みを別途組み合わせる必要があります。
パイプライン・プロパティ・ワークフローの作成権限があれば、社内でも設定できる範囲です。ただし、案件×月の識別方法や関連付けの設計は、自社のパイプライン構成に合わせた判断が必要になるため、初回は数時間から半日程度の設計作業を見込んでおくとよいでしょう。設計から代行することも可能です。
自動化の仕組みを有効にする際に、条件を満たす既存のレコードをまとめて処理するオプションを選べば、過去分もまとめて案件×月の器に振り分けられます。
粗利率が実態とずれる原因になります。freee取引の金額が税込・税抜のどちらで計上されているかを、売上側・原価側それぞれで確認したうえで、同じ基準に揃えることをおすすめします。
Sync for freeeをすでにご利用中の方は、ユーザーガイドから具体的な設定手順をご確認いただけます。自社の案件構造に合わせた設計・設定の代行も承っています。StartLinkの無料相談からお問い合わせください。
株式会社StartLinkは、事業推進に関わる「販売促進」「DXによる業務効率化(ERP/CRM/SFA/MAの導入)」などのご相談を受け付けております。 サービスのプランについてのご相談/お見積もり依頼や、ノウハウのお問い合わせについては、無料のお問い合わせページより、お気軽にご連絡くださいませ。
株式会社StartLink 代表取締役。累計150社以上のHubSpotプロジェクト支援実績を持ち、Claude CodeやHubSpotを軸にしたAI活用支援・経営基盤AXのコンサルティング事業を展開。
HubSpotのトップパートナー企業や大手人材グループにて、エンタープライズCRM戦略策定・AI戦略ディレクションを経験した後、StartLinkを創業。現在はCRM×AIエージェントによる経営管理支援を専門とする。