omni-embed について
omni-embedは、Omniのダッシュボードを外部アプリに埋め込む開発者向けスキルです。署名付きURL、テーマ設定、iframeとの双方向イベント処理を扱います。
主な機能
- 01署名付きダッシュボードURLの生成
- 02埋め込みコンテンツのテーマ設定
- 03iframeメッセージイベントの処理
- 04行レベルセキュリティ用属性の設定
- 05フィルターとドリルデータの受け渡し
活用シーン
- 01外部アプリでOmniダッシュボードを表示
- 02埋め込み画面をブランドテーマに調整
- 03フィルターや読み込みイベントへの対応
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ exploreomni/ omni-agent-skills --skill omni-embedインストール後、Claude Code で/omni-embedを入力して読み込まれたか確認します。
同梱ファイルevals/evals.json
詳細
Omni Embed
署名付き iframe URL を使用して、Omni のダッシュボードを外部アプリケーションに埋め込みます。@omni-co/embed SDK は URL の署名とテーマのカスタマイズを処理します。Omni の postMessage イベントにより、親アプリと埋め込み iframe の間で双方向に通信できます。
Tip:
omni-content-explorerを使用して埋め込むダッシュボードを見つけ、omni-adminを使用して埋め込みユーザーの権限と、行レベルのセキュリティに使用するユーザー属性を管理します。
前提条件
npm install @omni-co/embed
# Verify the Omni CLI is installed — if not, ask the user to install it
# See: https://github.com/exploreomni/cli#readme
command -v omni >/dev/null || echo "ERROR: Omni CLI is not installed."
# Show available profiles and select the appropriate one
omni config show
# If multiple profiles exist, ask the user which to use, then switch:
omni config use <profile-name>
# Confirm the active profile is authenticated and inspect your permissions:
omni whoami whoami
export OMNI_EMBED_SECRET="your-embed-secret" # Admin → Embed (for URL signing)
認証:プロファイルの認証には API キー または OAuth を使用します(以下の埋め込みシークレットとは別です)。
whoami(またはその他の呼び出し)が 401 を返した場合は、ユーザーに引き継いでください。ユーザーに! omni config login <profile>の実行を依頼します(OAuth 2.1 のブラウザーフロー。ブラウザー上で約 2 分間処理がブロックされます)。ヘッドレス/CI セッションではconfig loginを実行しないでください(ブラウザーがないためタイムアウトします)。ローカルの対話型マシンでは実行してもかまいません。プロファイルのセットアップ(omni config init --auth oauth)と、--schemaを使ったコマンドやリクエストボディの形式の確認については、omni-api-conventionsルールを参照してください。
埋め込みシークレットは、Omni インスタンスの Admin → Embed にあります。OMNI_BASE_URL が埋め込みホストだと決めつけないでください。CLI/API の URL では .omniapp.co、カスタムドメイン、または内部のプレイグラウンドドメインが使われることがあります。iframe URL に署名する際は、OMNI_EMBED_HOST にホスト名のみを設定します(例:yourorg.embed-omniapp.co)。
安全な署名のデフォルト設定
- SDK の署名機能を使用してください —
@omni-co/embedのembedSsoDashboard()を使って署名付き URL を生成します。ユーザーから低レベルの実装を明示的に求められない限り、HMAC 署名を独自に実装しないでください。 OMNI_API_TOKENを埋め込みシークレットとして使用しないでください — API トークンは REST/CLI 呼び出しの認証に使うもので、埋め込みの署名シークレットとしては無効です。Admin → Embed のOMNI_EMBED_SECRETを使用してください。- 埋め込みシークレットを利用できない場合 — 署名付き URL を捏造しないでください。
secret: process.env.OMNI_EMBED_SECRETを指定してembedSsoDashboard()を呼び出すサーバーサイドのコードを返し、その環境変数を設定するようユーザーに伝えてください。 - iframe URL には埋め込みホストを使用してください —
hostには、https://、パス、ポートを含まない.embed-omniapp.coのホスト名のみを指定する必要があります。 - 埋め込みホストがすでに埋め込みホストである場合を除き、
OMNI_BASE_URLから埋め込みホストを推測しないでください — CLI/API のベース URL では、.omniapp.coやカスタム API ドメインがよく使われます。API のベース URL しかわからない場合は、サーバーコードのhost: process.env.OMNI_EMBED_HOST(またはyourorg.embed-omniapp.coのようなプレースホルダー)をそのままにして、別途設定が必要であることを伝えてください。 - Node.js を利用できない場合 — 引き続き
@omni-co/embedを使用する TypeScript/Node サーバーコードを提示してください。ローカルでデモを実行できるようにするためだけに、Python やブラウザー側での手動 HMAC 署名に切り替えないでください。
コマンドの確認
omni scim --help # Embed user lookup
omni documents --help # Document listing
omni folders --help # Folder listing
Tip:プログラムによる解析向けに構造化出力を強制するには
-o jsonを、読みやすい表形式で出力するには-o humanを使用します。デフォルトはautoです(TTY では人が読みやすい形式、パイプに接続されている場合は JSON)。
埋め込み URL の署名
@omni-co/embed SDK の embedSsoDashboard() を使用してサーバーサイドで署名付き URL を生成し、クライアントサイドで iframe に読み込みます。
import { embedSsoDashboard, EmbedSessionMode } from "@omni-co/embed";
const embedUrl = await embedSsoDashboard({
contentId: "dashboard-uuid",
secret: process.env.OMNI_EMBED_SECRET,
host: process.env.OMNI_EMBED_HOST ?? "yourorg.embed-omniapp.co",
externalId: "[email protected]",
name: "Jane Doe",
userAttributes: { brand: ["Acme"] }, // For row-level security
mode: EmbedSessionMode.SingleContent,
prefersDark: "false",
});
パラメーター
| パラメーター | 必須 | 説明 |
|---|---|---|
contentId | はい | ダッシュボード UUID(URL または Admin → Dashboards から取得) |
secret | はい | Admin → Embed から取得する埋め込みシークレット |
host | はい | 埋め込みホスト名のみ。プロトコルやポートは含めません |
externalId | はい | 一意のユーザー識別子(通常はメールアドレス) |
name | はい | ユーザーの表示名 |
userAttributes | いいえ | 行レベルのセキュリティに使用する Record<string, string[]> |
mode | いいえ | SingleContent(デフォルト)または Application(作成機能を有効化) |
prefersDark | いいえ | "true" または "false"。ライト/ダークモードを切り替えます |
customTheme | いいえ | テーマオブジェクト(下記の「カスタムテーマ」を参照) |
entity | いいえ | ワークスペースのエンティティ名(下記の「エンティティワークスペース」を参照) |
注意点:host パラメーターにはホスト名のみを指定する必要があります(例:yourorg.embed-omniapp.co)。プロトコル(https://)やポート(:3000)を含めると、Omni は 400 を返します。
OMNI_EMBED_SECRET が設定されていない場合でも、process.env.OMNI_EMBED_SECRET を使った、この SDK 形式のサーバーサイドコードを生成してください。OMNI_API_TOKEN や別の API 認証情報で代用しないでください。
カスタムテーマ
embedSsoDashboard() に customTheme オブジェクトを渡すと、埋め込みダッシュボードのコンテンツ(タイルの背景、テキストの色、コントロール、ボタン)をスタイル設定できます。これは iframe 内側の表示を制御するものであり、親アプリのスタイル設定は別途必要です。
const embedUrl = await embedSsoDashboard({
// ...signing params
prefersDark: "false",
customTheme: {
"dashboard-background": "#FEF2F2",
"dashboard-tile-background": "#FFF5F5",
"dashboard-key-color": "#E60000",
"dashboard-key-text-color": "#ffffff",
// ...
},
});
プロパティリファレンス
ページ:
| プロパティ | 説明 |
|---|---|
dashboard-background | ダッシュボードページの背景 |
dashboard-page-padding | ダッシュボードページのパディング |
タイル:
| プロパティ | 説明 |
|---|---|
dashboard-tile-margin | タイル周囲の間隔 |
dashboard-tile-background | タイルの背景色 |
dashboard-tile-shadow | タイルのボックスシャドウ |
dashboard-tile-text-body-color | タイル内の本文の基本色 |
dashboard-tile-text-secondary-color | タイル内の本文の補助色 |
dashboard-tile-border-color | タイルの境界線の色 |
dashboard-tile-border-radius | タイルの境界線の角丸 |
dashboard-tile-border-style | タイルの境界線のスタイル |
dashboard-tile-border-width | タイルの境界線の幅 |
dashboard-tile-title-font-size | タイトルのフォントサイズ |
dashboard-tile-title-font-weight | タイトルのフォントの太さ |
dashboard-tile-title-text-color | タイトルの文字色 |
dashboard-tile-title-font-family | カスタムタイトルフォント(woff2 URL) |
dashboard-tile-text-body-font-family | カスタム本文フォント |
dashboard-tile-text-code-font-family | カスタムコードフォント |
コントロール(フィルターのドロップダウン):
| プロパティ | 説明 |
|---|---|
dashboard-control-background | フィルターコントロールの背景 |
dashboard-control-radius | フィルターコントロールの境界線の角丸 |
dashboard-control-border-color | フィルターコントロールの境界線の色 |
dashboard-control-text-color | フィルターコントロールの文字色 |
dashboard-control-placeholder-color | プレースホルダーの文字色 |
dashboard-control-label-color | コントロール上部のラベルの文字色 |
dashboard-control-outline-color | フォーカス時のアウトラインの色 |
コントロールのポップオーバー(ドロップダウンメニュー):
| プロパティ | 説明 |
|---|---|
dashboard-control-popover-background | ポップオーバーの背景 |
dashboard-control-popover-text-color | ポップオーバーの文字色 |
dashboard-control-popover-secondary-text-color | ポップオーバー内の補助文字色 |
dashboard-control-popover-link-color | ポップオーバー内のリンクの色 |
dashboard-control-popover-divider-color | 区切り線の色 |
dashboard-control-popover-radius | ポップオーバーの境界線の角丸 |
dashboard-control-popover-border-color | ポップオーバーの境界線の色 |
dashboard-filter-input-background | フィルター入力欄の背景 |
dashboard-filter-input-radius | フィルター入力欄の境界線の角丸 |
dashboard-filter-input-border-color | フィルター入力欄の境界線の色 |
dashboard-filter-input-text-color | フィルター入力欄の文字色 |
dashboard-filter-input-placeholder-color | プレースホルダーの文字色 |
dashboard-filter-input-icon-color | フィルター入力欄内のアイコンの色 |
dashboard-filter-input-outline-color | フィルター入力欄のフォーカス時のアウトライン |
dashboard-filter-input-accent-color | チェックボックス、ラジオボタン、トグルの色 |
dashboard-filter-input-accent-invert-color | 入力欄内のチェックマーク/ドットの色 |
dashboard-filter-input-token-color | 複数選択トークンの背景色 |
dashboard-filter-input-token-text-color | 複数選択トークンの文字色 |
ボタン:
| プロパティ | 説明 |
|---|---|
dashboard-key-color | 主なアクションの色(更新ボタン) |
dashboard-key-text-color | 主ボタンの文字色 |
dashboard-button-radius | ボタンの境界線の角丸 |
dashboard-button-transparent-text-color | 透明ボタンの文字色 |
dashboard-button-transparent-interactive-color | 透明ボタンのホバー時の色 |
dashboard-menu-item-interactive-color | メニュー項目のホバー時の背景色 |
サポートされている CSS 値
- 16進数カラー:
"#FEF2F2","#E60000" - rgba によるボックスシャドウ:
"0 2px 8px rgba(230, 0, 0, 0.1)"(シャドウ関連のプロパティのみ) - URL によるカスタムフォント:
"url(https://fonts.gstatic.com/...) format('woff2')" - デフォルト値をクリアする空文字列:
"" - 背景/色のプロパティでは
linear-gradient()とrgba()を Omni の UI テーマエディターで使用できますが、SDK 経由で渡すと失敗する場合があります。確実に使用するには、単色の16進数カラーを使用してください
テーマ設定のヒント
効果的にブランディングするには、ボタンだけに色を付けるのではなく、背景全体に色合いを付けます。
dashboard-background→ ブランドカラーの明るい色合い(Tailwind の color-50 など)dashboard-tile-background→ ページ背景よりやや明るい色dashboard-tile-title-text-color→ ブランドのプライマリーカラー(タイトルをブランドカラーにする)dashboard-control-label-color→ ブランドのプライマリーカラー(ラベルをブランドカラーにする)dashboard-tile-border-color→ ブランドカラーの中程度に明るい色合い(color-200 など)dashboard-key-color→ ブランドのプライマリーカラーdashboard-filter-input-accent-color→ ブランドのプライマリーカラー(チェックボックス、トグル)
埋め込みイベント
Omni は postMessage を介して親アプリと通信します。Omni のイベントはすべて source: "omni" を持ちます。
イベントのリッスン
window.addEventListener("message", (event) => {
if (event.data?.source !== "omni") return;
switch (event.data.name) {
case "dashboard:loaded":
// Dashboard ready
break;
case "error":
// Handle error
break;
case "dashboard:tile-drill":
// Handle drill action
break;
}
});
イベントリファレンス
dashboard:loaded — 埋め込みダッシュボードの読み込みが完了したときに発生します。
{ "source": "omni", "name": "dashboard:loaded" }
dashboard:filters — 埋め込みダッシュボード内でフィルターの状態が変化したときに発生します。
{
"source": "omni",
"name": "dashboard:filters",
"payload": { /* filter state */ }
}
error — 埋め込みページで検出可能なエラーが発生したときに発生します。
{
"source": "omni",
"name": "error",
"payload": {
"href": "https://...",
"message": "Error description"
}
}
dashboard:tile-drill — ユーザーがダッシュボードのタイル(チャート、テーブル、マップ)をドリル操作したときに発生します。Omni 側での設定は不要です。
{
"source": "omni",
"name": "dashboard:tile-drill",
"payload": {
"userId": "string",
"dashboard": {
"filters": {
"filterName": {
"filter": {},
"asJsonUrlSearchParam": "string"
}
},
"href": "string",
"urlId": "string",
"path": "string",
"title": "string"
},
"tile": {
"id": "string",
"title": "string",
"appliedFilters": {
"filterName": {
"filter": {},
"asJsonUrlSearchParam": "string"
}
}
},
"drill": {
"field": "string",
"fieldLabel": "string",
"drillQueryLabel": "string",
"rowToDrill": { "field_name": "value" }
}
}
}
ドリルした行のデータには drill.rowToDrill を使用します。異なるダッシュボードにフィルターを適用して署名・埋め込みするには、tile.appliedFilters または dashboard.filters の asJsonUrlSearchParam を使用します。
page:changed — iframe 内で URL が変化したとき(新しいダッシュボードの保存後など)に発生します。
{
"source": "omni",
"name": "page:changed",
"payload": {
"pathname": "string",
"type": "string"
}
}
カスタムビジュアライゼーションイベント — ユーザーが設定済みのテーブル行または Markdown リンクをクリックしたときに発生します。Omni での設定が必要です。テーブル列の「Display」を Link → Embed event に設定し、イベント名を入力します。Markdown では <omni-message> タグを使用します。
{
"source": "omni",
"name": "<your-event-name>",
"payload": {
"data": "comma-separated values"
}
}
テーブルの設定:フィールドのドロップダウン → Display タブ → Display as: Link → URL: Embed event → イベント名を入力します。
Markdown の設定:
<omni-message event-name="product-click" event-data="{{products.name.raw}},{{products.retail_price.raw}}">
Click here
</omni-message>
iframe へのイベント送信
dashboard:filter-change-by-url-parameter — 親アプリから埋め込みダッシュボードにフィルターを渡します。
iframe.contentWindow.postMessage({
source: "omni",
name: "dashboard:filter-change-by-url-parameter",
payload: {
filterUrlParameter: 'f--<filter_id>={"values":["value1","value2"]}'
}
}, iframeOrigin);
ダッシュボードを Omni で開き、フィルター値を変更して、URL から f-- パラメーターをコピーすると、filterUrlParameter 文字列を取得できます。
エンティティワークスペース
エンティティワークスペースを使うと、埋め込みユーザーはスコープされたフォルダー内で独自のダッシュボードを作成し、保存できます。
import {
embedSsoDashboard,
EmbedSessionMode,
EmbedEntityFolderContentRoles,
EmbedUiSettings,
EmbedConnectionRoles,
} from "@omni-co/embed";
const embedUrl = await embedSsoDashboard({
// ...standard signing params
entity: "acme",
entityFolderContentRole: EmbedEntityFolderContentRoles.EDITOR,
mode: EmbedSessionMode.Application,
uiSettings: {
[EmbedUiSettings.SHOW_NAVIGATION]: false,
},
connectionRoles: {
"connection-uuid": EmbedConnectionRoles.RESTRICTED_QUERIER,
},
});
| パラメーター | 説明 |
|---|---|
entity | エンティティ名 — ユーザーのフォルダーのスコープを設定します(メールドメインから導出するなど) |
entityFolderContentRole | EDITOR を指定すると、ユーザーはエンティティフォルダー内でダッシュボードを作成・編集できます |
mode | 作成機能を有効にするには Application にする必要があります |
uiSettings | Omni の組み込み UI を制御します(独自の UI を提供する場合に Omni のサイドバーを非表示にするなど) |
connectionRoles | クエリアクセスを許可します。データ探索には RESTRICTED_QUERIER を使用します |
埋め込みユーザーと権限
権限を考慮したエクスペリエンス(ユーザーがアクセスできるダッシュボードだけを表示するサイドバーなど)を構築する場合は、まず Omni ユーザー ID を検索し、次にそのユーザーにスコープされたドキュメントを一覧表示します。API/CLI 呼び出しでは、.embed-omniapp.co の埋め込みホストではなく、Omni API ホスト/プロファイルを使用します。
埋め込みユーザーの検索
omni scim embed-users-list --filter 'embedExternalId eq "[email protected]"'
指定された externalId の Omni ユーザー ID を返します。ユーザーが見つからない場合、そのユーザーはまだ埋め込みダッシュボードにアクセスしていません。
埋め込みユーザーのフィルターで行が返されなくても、同じ メールアドレス/userName を持つ通常の SCIM ユーザーが明らかに存在する場合は、 そのユーザーの Omni ID を代替として使用し、どちらの検索方法を使ったかを 明示してもかまいません。サイドバーの結果として、フィルターなしのドキュメント一覧に フォールバックしてはいけません。
ユーザー権限に基づいてドキュメントを一覧表示する
omni documents list --user-id <omniUserId>
メールアドレスやexternalIdを直接使わず、embed-users-listが返すOmniユーザーIDを使用してください。サイドバーの項目を表示する前に、レスポンスをhasDashboard: trueで絞り込んでください。documents listにはAPIホスト/プロファイルを使用し、embedSsoDashboard()でiframe URLに署名する場合にのみembedホストを使用してください。デモアプリでも、URLの署名処理は手動でHMACプロトコルをPythonやブラウザーコードで再現するのではなく、SDK署名機能を使うサーバーサイドのTypeScript/Node関数にしてください。
CLIを直接実行せず、サーバーコードを記述する場合、同等のdocuments APIの形式は次のとおりです。
GET /api/v1/documents?userId=<omniUserId>
Authorization: Bearer <OMNI_API_TOKEN>
API呼び出しではキャメルケースのuserIdを使用してください。CLIフラグは小文字の--user-idです。
レスポンスではdocumentsではなく、records配列が使用されます。
{
"pageInfo": {
"hasNextPage": false,
"nextCursor": null,
"pageSize": 20,
"totalRecords": 5
},
"records": [
{
"identifier": "fb007aa3",
"name": "Sales Dashboard",
"hasDashboard": true,
"folder": {
"id": "...",
"name": "Sales",
"path": "sales/regional"
}
}
]
}
署名用のcontentIdにはidentifierを使用してください。埋め込み可能なダッシュボードのみを取得するには、hasDashboard: trueで絞り込んでください。
分かりやすい名前でフォルダーを一覧表示する
エンティティフォルダーのパスは、omni-system-sso-embed-entity-folder-pocのような技術的な名前です。パスを表示名に対応付けます。
omni folders list
レスポンスからpath → nameのマッピングを作成し、分かりやすいフォルダー名を表示してください。
ドメインの対応付け
embedドメイン(.embed-omniapp.co)とAPIドメイン(.omniapp.co)は異なります。
Embed: yourorg.embed-omniapp.co → used for iframe URLs
API: yourorg.omniapp.co → used for REST API calls
アプリにembedドメインを保存する場合は、.embed-omniapp.coを.omniapp.coに置き換えてAPI呼び出し用に変換してください。
ドキュメントリファレンス
関連スキル
- omni-content-explorer — 埋め込むダッシュボードを探す
- omni-content-builder — 埋め込み前にダッシュボードを作成する
- omni-admin — 埋め込みユーザーの権限、RLS用のユーザー属性、接続を管理する
- omni-model-explorer — 埋め込みイベントデータで利用可能なフィールドを把握する