mcpField
O
omni-embed

omni-embed

github.com/exploreomni開発45168 回インストール1 日前に更新
リポジトリ

omni-embed について

omni-embedは、Omniのダッシュボードを外部アプリに埋め込む開発者向けスキルです。署名付きURL、テーマ設定、iframeとの双方向イベント処理を扱います。

主な機能

  1. 01署名付きダッシュボードURLの生成
  2. 02埋め込みコンテンツのテーマ設定
  3. 03iframeメッセージイベントの処理
  4. 04行レベルセキュリティ用属性の設定
  5. 05フィルターとドリルデータの受け渡し

活用シーン

  1. 01外部アプリでOmniダッシュボードを表示
  2. 02埋め込み画面をブランドテーマに調整
  3. 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エンティティ名 — ユーザーのフォルダーのスコープを設定します(メールドメインから導出するなど)
entityFolderContentRoleEDITOR を指定すると、ユーザーはエンティティフォルダー内でダッシュボードを作成・編集できます
mode作成機能を有効にするには Application にする必要があります
uiSettingsOmni の組み込み 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 — 埋め込みイベントデータで利用可能なフィールドを把握する

コメント