Zoho CRM ウィジェットの仕組みを理解する ― アーキテクチャから開発の流れまで

2026年08月17日

標準機能やワークフローだけでは手が届かない独自の画面を、Zoho CRM のUIに溶け込ませて追加したい。そんなときに使うのが「ウィジェット」です。この記事では、ウィジェットが内部でどう動いているのか、その仕組みと開発の流れを整理します。個別の作り方というより、全体像をつかむことを目的にしています。

ウィジェットとは何か

ウィジェットは、Zoho CRM の画面内に自作の HTML / CSS / JavaScript をそのまま埋め込める仕組みです。標準機能やワークフローでは実現できない独自の表示・操作を、CRM のUIに違和感なく足すことができます。

典型的な使いどころは次のようなものです。

・リストビューから条件を指定して顧客を検索するポップアップ
・レコード詳細画面に、関連データをグリッドで表示するパネル
・外部サービスの情報を CRM 画面内に取り込んで表示するパネル

ウィジェットの正体は「iframe」

仕組みを一言でいうと、ウィジェットは「CRM画面の中に埋め込まれた iframe」です。中身は独立したWebアプリで、CRM本体とは別のドメインで動いています。

ここが最初に押さえるべきポイントです。ウィジェットは別ドメインの iframe なので、CRM のデータを直接読み書きすることはできません。CRM本体とウィジェットのやり取りは、すべて Zoho が用意した JavaScript SDK(Embedded App SDK)を経由して行われます。

「iframe+SDK」というこの構造を頭に入れておくと、後半で挙げるつまずきポイントの多くが腑に落ちます。

SDK の読み込みと初期化

ウィジェットの HTML にSDKを読み込みます。現在の最新は v1.5 です。

/code

/code

このURLはミスの起きやすいところです。ドメインは live.zwidgets.com、ファイル名は ZohoEmbededAppSDK(Embeded の d は1つ)です。URLを間違えるとエラーらしいエラーが出ず、コンソールに「ZOHO is not defined」とだけ出て静かに失敗します。

初期化は「先にイベントを購読してから init する」という順番が決まっています。

/code
// 先に PageLoad を購読してから
ZOHO.embeddedApp.on("PageLoad", function(data){
// data.Entity … モジュール名(例: Deals)
// data.EntityId … 開いているレコードのID
var recordId = data.EntityId;
});

// そのあとで初期化する
ZOHO.embeddedApp.init();
/code

詳細画面に置いたウィジェットが「今どのレコードを開いているか」を知る手段はこの PageLoad だけです。現在のレコードを取ってくるための ZOHO.CRM.getCurrentRecord() のようなメソッドは存在しないので、必ず PageLoad の data から受け取ります。

どこに配置できるか

ウィジェットは1種類ではなく、CRM のいろいろな場所に差し込めます。代表的な配置先は次のとおりです。

・リストビュー上のボタン(押すとポップアップでウィジェットが開く)
・レコード詳細画面の関連リストとして表示
・独立したWebタブとして1画面まるごと表示
・ボタン(レコード上のカスタムボタンから呼び出す)

配置先によって、開いた時点で渡ってくる情報が変わります。詳細画面ならレコードIDが渡ってきますが、リストビューのボタンからのポップアップでは渡ってこないので、ウィジェット側でユーザーに入力させる、といった設計の違いが出てきます。

なお、Canvas(詳細画面のレイアウトを自由に組める機能)に対しては、ウィジェットを直接埋め込むことはできません。Canvasで使いたい場合は、レイアウトエディタから「カスタム関連リスト」としてウィジェットを配置する形になります。

CRM のデータをどうやって扱うか

別ドメインの iframe である以上、ウィジェットから直接 CRM のレコードを検索したり更新したりはできません。ここで登場するのが、サーバー側の Deluge 関数を呼び出す方法です。

流れはこうです。ウィジェット(フロント)から SDK 経由で Deluge 関数を呼び、Deluge 側で検索やAPI呼び出しといった重い処理をこなし、結果だけをウィジェットに返す。役割分担がはっきりしていて、認証情報やAPIの詳細をフロントに晒さずに済むのが利点です。

呼び出しはこう書きます。

/code
ZOHO.CRM.FUNCTIONS.execute("your_function_name", {
arguments: JSON.stringify({ deal_id: recordId })
})
.then(function(resp){
var output = resp.details.output; // Deluge 関数の返り値
// output を使って画面を描画
});
/code

このとき、次の2点でよく詰まります。

ひとつは「REST APIとして利用」のトグルです。呼び出したい Deluge 関数ごとに、関数の … メニューから「REST APIとして利用」を開き、ウィジェット向けの利用を明示的にONにしておく必要があります。これを忘れると関数が呼ばれず、resp.details.output が undefined のまま返ってきます。

もうひとつは引数の受け取り方です。フロントから渡した引数は crmAPIRequest というエンベロープに包まれて関数に届きます。Deluge 側では map crmAPIRequest を受け取り、そこから params → arguments と辿って展開する、という一手間が要ります。

Deluge 側でのデータ取得

呼び出された Deluge 関数の中では、CRM のデータを自由に扱えます。単純な検索なら searchRecords、複雑な条件やJOINを含む取得なら COQL を使うのが定番です。

COQL は SQL に似たクエリ言語で、Deluge の invokeurl から COQL エンドポイントへ POST して実行します。このとき connection パラメーターには接続名を文字列リテラルで直接書く必要があります。変数に入れて渡すと動きません。また COQL は WHERE 句のないクエリを受け付けないので、全件取得したい場合でも必ず条件を付けます。

表示の高さを自動で合わせる

Canvas などに埋め込んだウィジェットは、中身の量に応じて iframe の高さを自分で調整しないと、下が切れたり余白が空いたりします。高さの調整には Resize を使います。

/code
ZOHO.CRM.UI.Resize({ height: String(h), width: "100%" });
/code

コンテンツの高さは変わり続けるので、ResizeObserver で中身の変化を監視し、少しのデバウンス(例: 120ミリ秒)と最小変化のしきい値(例: 8ピクセル)を入れて、無限リサイズのループを防ぐと安定します。

開発から公開までの流れ

ウィジェットの開発には、Zoho が提供する zet というCLIツールを使います。ローカルで動かしながら開発し、最後にパッケージ化してアップロードする流れです。

まず Node.js を入れたうえで、CLIをインストールします。

/code
npm install -g zoho-extension-toolkit
/code

プロジェクトの作成から公開までは、おおむね次のコマンドで進みます。

/code
zet init # サービスに「Zoho CRM」を選んでプロジェクト作成
zet run # ローカルサーバー起動(http://localhost:5000)
zet validate # 構成チェック。エラーが残るとアップロードできない
zet pack # アップロード用のzipを生成(dist フォルダ)
/code

ウィジェットの実体は app フォルダ内の HTML / JS / CSS で、エントリーとなるHTMLと plugin-manifest.json が中心です。zet run で立ち上げたローカルサーバーを Sandbox に向けてテストし、問題がなければ validate → pack、生成された zip を開発者コンソールにアップロードして、CRM側で配置場所を指定すれば公開完了です。

実務でつまずきやすいポイント

最後に、実装で引っかかりやすい点をまとめておきます。

SDKのURLは正確に。live.zwidgets.com、ファイル名は Embeded(dは1つ)。間違えると「ZOHO is not defined」で静かに失敗します。

関数が呼ばれないときは「REST APIとして利用」のウィジェットトグルを疑う。output が undefined なら、まずここです。

現在のレコードは PageLoad の data から取る。getCurrentRecord のようなメソッドはありません。

Canvas にウィジェットは直接埋め込めない。カスタム関連リストとして配置します。

ウィジェットと Client Script は別物。Client Script には setTimeout や localStorage が使えないなど独自の制約があり、同じ感覚で書くとハマります。

補足: 新しい呼び出し方式 ZRC

SDK v1.5 からは ZRC(Zoho Request Client)という仕組みが加わりました。これは CRM API・接続経由の外部API・公開APIを、統一された構文で呼び出せるようにするものです。従来のように Deluge 関数を経由しなくても、ウィジェットから直接APIを叩けるケースが増え、記述がすっきりします。既存のウィジェットを Deluge 関数ベースで組んでいる場合はそのままで問題ありませんが、新規に作るなら選択肢として押さえておくとよいでしょう。

まとめ

Zoho CRM のウィジェットは「別ドメインの iframe を SDK でCRMと会話させる」仕組みです。この一点さえ押さえれば、レコードIDの受け取り方、Deluge 関数を介したデータのやり取り、高さの調整、そして開発から公開までの流れが、ひとつの筋として見えてきます。標準機能では届かない要件が出てきたときの、強力な引き出しになります。

Zoho CRM ウィジェットの仕組みを理解する ― アーキテクチャから開発の流れまで | Zoho CRMを活用した中小企業へのDX支援は【And So株式会社】。全ての企業にDXを!