salla-embedded-app について
salla-embedded-app は、Salla Merchant Dashboard にカスタムページを組み込むためのスキルです。ページ登録、SDK の設定、バックエンドでの安全なトークン検証に加え、ナビゲーションや UI などの連携方法を扱います。
主な機能
- 01埋め込みページの登録と管理
- 02Salla 埋め込み SDK の初期化
- 03バックエンドのセッション処理によるトークン検証
- 04ダッシュボードのテーマと言語の同期
- 05ナビゲーション・UI・チェックアウトの連携
活用シーン
- 01Salla のマーチャントダッシュボードへの独自ページ追加
- 02バックエンドで検証したトークンによる埋め込みアプリの認証
- 03ページナビゲーションとダッシュボード操作の連携
MCP 対応
Salla Partners MCP サーバーを使い、`salla_embedded_pages` ツールでダッシュボードの埋め込みページを登録・管理します。この手順には MCP サーバーへの接続が必要です。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sallaapp/ salla-partners-agent-kit --skill salla-embedded-appインストール後、Claude Code で/salla-embedded-appを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/auth-and-session.mddesign-guidelines.mdimplementation-guide.mdsdk-modules-guide.md詳細
Salla 埋め込みアプリのフロー
Salla マーチャントダッシュボード内にカスタムページを統合します。ステップ 1 では Salla Partners MCP にページを登録します。SDK のステップは、アプリに記述するコードです。手順に沿って進め、次に進む前に各ゲートを完了してください。
Salla の公式モデルは Trust-but-Verify です。Salla は有効期間の短いトークンを iframe の URL に渡します。フロントエンドは embedded.auth.getToken() でトークンを取得し、バックエンドに渡します。バックエンドは Salla の Introspection API でトークンを検証し、その後、独自のセッションを発行します。フロントエンドはトークンを運ぶだけであり、認可の判断は一切行いません。ステップ 3 は実装手順です。正式な情報源は references/auth-and-session.md です。
セキュリティルール(必須)
- **すべてのページをバックエンドで認証してください。**バックエンドは Salla トークンを検証(イントロスペクト)し、独自のセッションを発行して、各リクエストをそのセッションに照らして認可します。フロントエンドはトークンを中継するだけです。
- バックエンドからイントロスペクトして検証してください
(
POST https://api.salla.dev/exchange-authority/v1/introspect、ヘッダーS-Source: <YOUR_APP_ID>)。embedded.auth.introspect()(Client Introspect)は開発・デバッグ専用です。ドキュメントには「主な認証方法として使用すべきではない」と記載されています。リクエストとレスポンスの全容については、ステップ 3 とauth-and-session.mdを参照してください。 - **ID の取得元はイントロスペクションのみです。**イントロスペクションで返された
merchant_idに基づいて、すべてのルートとクエリをスコープしてください。ダッシュボードには Salla のネイティブな埋め込みアプリ対応機能からのみアクセスさせてください(クエリパラメーターやリファラーを信頼する、単独の/dashboard?store_id=…URL は使用しないでください)。
ツール
| ツール | アクション | 機能 |
|---|---|---|
salla_embedded_pages | list / create / update / delete | アプリの埋め込み(iframe)ダッシュボードページを管理します |
**前提条件:**Salla Partners MCP サーバーが接続済みで、アプリの
app_idが必要です。ツールが「Salla session expired」を返した場合は、ログインフローを再実行してください。
ステップ 0 — 確認
開始前に確認してください。
- このページでは何をしますか?(設定 UI、分析ダッシュボード、アドオン購入など)
- どの SDK モジュールが必要ですか?
auth—getToken、refresh、introspect(開発専用)、およびコア機能のinit/ready/destroypage—setTitle、navigate、redirect、navTonav— アクションボタン(setAction/onActionClick/clearAction)とサブナビゲーション項目ui— トースト、確認ダイアログ、ローディング、パンくずリストcheckout— アドオン購入
- アドオンを販売するページですか?(Checkout モジュールを有効にします)
ステップ 1 — ページを登録する
action: "create"、app_id と次の情報を指定して salla_embedded_pages を呼び出し、iframe ページを登録します。
route— ページのパスセグメント(kebab 形式、3 文字以上)。次の URL に表示されます。https://s.salla.sa/embedded/app/{appId}/{route}。iframe_url— Salla が iframe に読み込む完全な URL(例:https://dashboard.myapp.net/salla/embedded)。Salla はtoken、theme、langを追加します。default— 任意。このページをアプリのデフォルトのランディングページとして設定します。
create は新しいページを返します。update は Portal から本文を返さないため、ツールは変更したフィールド({ page: { id, route, iframe_url, default, updated: true } })を確認用に返します。現在の正式な状態を確認するには、salla_embedded_pages action=list を呼び出してください。ページを変更または削除するには、update/delete を使用します。
**手動での代替手順:**Portal → App Details → Embedded Pages → Add page。
ゲート:「salla_embedded_pages action=list にページが表示されています — マーチャントダッシュボードのサイドバーにも表示されていますか?」
埋め込みアプリの画像(公開時に設定)
埋め込み可能なアプリには2種類の App-Store 画像があり、どちらも SDK ではなく公開手続きで設定します。公開時に設定してください(ステップ 6 → salla-publication-consistency):
| 画像 | 設定場所 | 寸法/上限 | 表示先 |
|---|---|---|---|
Embedded App Banner (embedded_image) | app_publish の features セクション | 最小 710×260 px(推奨 1420×520)、最大 512 KB | アプリの埋め込み/iframe 表示 |
| Salla promotional image | app_publish の features セクション(promotional/featured) | 生成前に app_publish の readiness/salla-docs で寸法を確認 | Salla の promotional/featured(ビルド)セクション |
Salla promotional image は、Salla の promotional/featured セクションで使用される、Embedded App Banner に加えて必要な2枚目の画像です。アプリがその場所で featured 表示される場合は、必ず用意してください。
画像生成による補完は両方に適用されます。どちらかの画像がない場合(または初回公開時)に画像生成ツールを利用できる場合は、上記の寸法を確認し、生成してから salla_upload し、app_publish の features セクションで設定してください。それ以外の場合は、加盟店に実際の画像素材を依頼してください。手順を重複させないでください。標準の手順(およびその他すべての掲載画像フィールド)は
salla-app-ui-builder
に記載されています。
手動での代替手順:My Apps → App → App Details → Start publishing → App Features。
ステップ 2 — SDK のインストールと初期化
npm パッケージをインストールしてください。CDN のグローバル変数に依存しないでください。 パッケージから embedded をインポートすると、TypeScript でメソッド名を検証できます。CDN ビルドのグローバル変数名や形式は異なる場合があり、気付かないまま起動に失敗する可能性があります。
npm install @salla.sa/embedded-sdk
import { embedded } from "@salla.sa/embedded-sdk";
CDN を使う代替方法(バニラ/バンドルしていないページのみ。まずグローバル変数を確認してください):
<script src="https://unpkg.com/@salla.sa/embedded-sdk/dist/umd/index.js"></script>
<script>
const embedded = Salla.embedded; // or SallaEmbeddedSDK.embedded
</script>
ページを読み込むたびに初期化してください。init() は postMessage ブリッジを確立し、ダッシュボードの layout を返します。
const { layout } = await embedded.init({ debug: false });
// layout carries theme ("light"|"dark"), locale ("ar"|"en"), dir ("rtl"|"ltr"), …
SDK の呼び出しが正しくても、埋め込みアプリの初回起動を妨げる要因が2つあります。
- 埋め込み可能性 — ホスト側で Salla がページをフレーム内に表示できるようにする必要があります(
Content-Security-Policy: frame-ancestors https://s.salla.saを設定し、X-Frame-Optionsを削除してください)。設定しない場合、ダッシュボードには空白または「拒否された」ペインが表示されます。 - 開発ループ — ページではトークン取得のためにダッシュボードとのハンドシェイクが必要なため、通常のタブでは開けません。localhost をトンネル経由で公開し、
iframe_urlにトンネルの URL を指定して、デモストアにインストールし、Run App を実行してください。
ヘッダー、開発ループ、フレームワーク固有の注意点(React/Next、Vue)、実例全体、コピーして使えるスターターについては、references/implementation-guide.md を参照してください。
モジュールガイド → references/sdk-modules-guide.md
ステップ 3 — セッションを認証する(信頼しつつ検証する)
処理の流れは次のとおりです。
await embedded.init()— ブリッジを確立し、layoutを読み取ります。embedded.auth.getToken()— iframe の URL から有効期間の短いトークンを取得します (戻り値はstring | nullです。null(Salla の外部から開かれた場合)の処理を行ってください)。- トークンをお使いのバックエンドに送信します。 フロントエンドは受け渡し役です。ここで認証・認可の 判断を行わないでください。
- バックエンドで
POST https://api.salla.dev/exchange-authority/v1/introspectを使って検証します。 ヘッダーはS-Source: <YOUR_APP_ID>、本文は{ "token": "..." }です。→ 成功時、クレームはdataの下にネストされています。data.merchant_id/data.user_id/data.expを読み取ります (data.expは ISO-8601 形式の日時文字列であり、Unix タイムスタンプではありません)。バックエンドで 独自のセッション(JWT / セキュア Cookie)を発行します。 embedded.ready()— バックエンドでの確認が完了し、かつデータの読み込みが完了した後にのみ呼び出します。 呼び出すまでは、ダッシュボードに読み込みオーバーレイが表示されます。- 失敗した場合 —
embedded.destroy()を呼び出して正常に終了し、加盟店に読み込み中のまま 固まった画面を表示し続けないようにします。
// 1. Bridge + layout
const { layout } = await embedded.init({ debug: false });
try {
// 2. Capture the short-lived token from the URL
const token = embedded.auth.getToken();
if (!token) throw new Error("Opened outside Salla — no token");
// 3 + 4. Hand the token to YOUR backend; it introspects and mints a session.
const res = await fetch("/api/auth/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify({ token }),
});
if (!res.ok) throw new Error("Verification failed");
// 5. Backend confirmed + data loaded → reveal the iframe.
await loadDashboardData();
embedded.ready();
} catch (err) {
console.error("Auth failed", err);
embedded.destroy(); // exit gracefully instead of hanging on the loading overlay
}
embedded.auth.introspect() は開発/デバッグ専用です — イントロスペクションのフローを参照するための
フロントエンド用ヘルパーです。ドキュメントでは「主要な認証方法として使用しないこと」と明記されています。
本番環境での認可では、必ず上記のバックエンドでのイントロスペクションを使用します。
バックエンドから 401/有効期限切れが返された場合は、embedded.auth.refresh() を呼び出します。Salla が
新しいトークンを使って iframe を再読み込みし、ブートストラップが再実行されて、フローが再開します。
バックエンドでのイントロスペクション(S-Source を含む)、セッション発行、401→更新のループについて →
references/auth-and-session.md
確認事項:「ready() を呼び出す前に、バックエンドで S-Source ヘッダーを付けてトークンを
イントロスペクションし、独自のセッションを発行していますか? デモストアでテストしてください。」
ステップ 4 — テーマとロケールを同期する
テーマ、ロケール、方向は、embedded.init() が返す layout から取得します。クエリパラメーターを
手動で読み取らないでください。
if (layout) {
document.documentElement.setAttribute("data-theme", layout.theme);
document.documentElement.setAttribute("lang", layout.locale);
document.documentElement.setAttribute("dir", layout.dir); // "rtl" for ar, "ltr" for en
}
layout は外観設定の信頼できる情報源です。SDK が再初期化されるたび(例:embedded.auth.refresh() によって
iframe が再読み込みされた後)に、設定を再適用してください。ダッシュボードではテーマの動的な切り替えにも
対応しています。利用できる場合は embedded.onThemeChange() で変更を監視してください。
デザイントークン、ブランドカラー、RTL のパターン → references/design-guidelines.md
ステップ 5 — SDK モジュールを組み込む
画面に表示する UI を描画しますか? ここで作業を止めて、→ salla-embedded-ui を 読み込んでください。その確認項目(ネイティブトークン、No-Chrome、RTL、ライブスクリーンショット)は必須です。
salla-embedded-appに戻るのは、SDK の組み込みのためだけであり、スタイリングのためではありません。
ステップ 0 で確認したニーズに基づき、該当するモジュールを実装します。
認証 — 復旧可能な有効期限切れでは更新し、復旧不可能な場合にのみ破棄します。
// Backend reported the token expired (401): refresh — Salla re-renders the iframe with a fresh one.
embedded.auth.refresh();
// Only when auth is unrecoverable (a fresh token still can't verify, app suspended):
embedded.destroy(); // tears down the iframe so the dashboard doesn't hang
順序が重要です。一時的な有効期限切れでは destroy() ではなく refresh() を実行してください。
ページ — タイトルとダッシュボードのナビゲーション:
embedded.page.setTitle("My App");
embedded.page.navigate("/orders"); // internal SPA route (React Router)
embedded.page.redirect("https://docs.my-app.com/help"); // external / full reload
embedded.page.navTo("/orders"); // auto-picks navigate vs redirect
ナビゲーション — アクションボタンとサブナビ項目:
embedded.nav.setAction({
title: "Save",
value: "save",
icon: "hgi hgi-stroke hgi-tick-02",
}); // icon optional (Hugeicons class)
const off = embedded.nav.onActionClick((value) => {
if (value === "save") saveChanges();
});
embedded.nav.clearAction(); // when the merchant leaves this view
UI — トースト、読み込み表示、確認、パンくずリスト:
embedded.ui.toast.success("Saved!");
embedded.ui.toast.error("Something went wrong");
embedded.ui.loading.show();
embedded.ui.loading.hide();
const { confirmed } = await embedded.ui.confirm({
title: "Delete?",
message: "This cannot be undone.",
variant: "danger", // confirm() resolves to { confirmed }, not a bare boolean
});
embedded.ui.breadcrumbs.hide(); // or .show()
チェックアウト — アプリ内アドオン購入(該当する場合):
→ salla-addon-purchase-embedded スキルに従ってください(埋め込み/アプリ内購入フローです。
アドオンの料金設定や権限付与の仕組みについては salla-addon-purchase を参照してください)。
メソッドの全シグネチャ → references/sdk-modules-guide.md
確認事項:「本番環境に移行する前に、SDK Playground で使用する各モジュールをテストしてください。」 → Playground / Test Kit
ステップ 6 — 公開する
埋め込みページは、親アプリを公開すると利用可能になります。salla-app-builder の公開ステップにある
公開チェックリストに従ってください。
リソース
モジュールごとのページは
https://docs.salla.dev/embedded-sdk/modules/...(auth、page、nav、 ui、checkout)にあります。バンドル版のsdk-modules-guide.mdには、 それらのシグネチャが記載されています。