利用可能 · v1

ウェブサイトとアプリの間の架け橋。

パブリック バックエンド サービスを使用せずに、ページ タイトル、ナビゲーション、バッジ、アプリのライフサイクル、共有、通知、その他のネイティブ動作を調整するための、バージョン管理された小規模な JavaScript SDK。

app-bridge.js
const context = await SiteToApp.ready();

if (context.available) {
  await SiteToApp.page.setTitle('Your cart');
  await SiteToApp.navigation.setBadge('cart', 3);
}
キー、トークン、またはパブリック REST エンドポイントなし
目的

1 つの Web サイトにアプリを意識した瞬間が含まれています。

SDK は、オプションのプログレッシブ拡張機能です。ページには引き続きコンテンツ、ルーティング、アカウント、カート、ビジネス ルールが含まれます。ネイティブ シェルは、アプリの Chrome とデバイスの統合を所有します。 SDK は、この 2 つの間で小さな検証済みメッセージを渡します。

SiteTo.App パブリック REST サービスは関係しません。 Web サイトには SiteTo.App キーは必要ありません。また、SDK にはストアの資格情報、顧客の秘密、または特権アカウントのトークンを含めてはいけません。

コンテキストに応じたページタイトル

ブラウザーのタイトルを正確に保ちながら、チェックアウト、アカウント、または記事ページでネイティブ ヘッダーを更新できるようにします。

ライブナビゲーションバッジ

既知の値をすぐにプッシュするか、同じ生成元の URL からカート、受信箱、または予約数を読み取ります。

ルートを意識したナビゲーション

アクティブなネイティブ ナビゲーション アイテムを従来のページおよび単一ページのアプリケーション ルートに合わせて配置します。

ライフサイクルイベント

アプリが再開、再接続するとき、または通知やディープリンクから開くときに、Web サイトの古い状態を更新します。

ネイティブアクション

システム共有シート、許可プロンプト、設定、およびサポートされている場合は微妙な触覚フィードバックを使用します。

ブラウザの安全な動作

すべての機能にはブラウザーのフォールバックまたは no-op が文書化されているため、1 つの Web サイトのコードベースがどこでも機能し続けます。

可用性とセットアップ

明示的にバージョン管理された 1 つのスクリプト。

CDN スクリプトを通常の Web サイトに追加するか、バンドルされたアプリケーションに npm パッケージをインストールします。どちらも同じ動作とプロトコル バージョンを公開します。

CDN スクリプトv1
<script
  src="https://cdn.siteto.app/sdk/v1/sitetoapp.min.js"
  defer
></script>
ESモジュールv1
import { SiteToApp } from '@sitetoapp/web-sdk';

メジャー バージョンは URL とパッケージ コントラクト内に存在します。非破壊的な追加は以内に出荷可能 v1;メソッドの名前変更、ペイロードの変更、または異なるフォールバック動作には必要があります v2.

準備状況と状況

ユーザーエージェントではなく、機能を検出します。

SiteToApp.ready() ネイティブ シェルとのハンドシェイクを開始し、 AppContext。また、存在しないブリッジを待機している間にアプリケーション コードがハングしないように、通常のブラウザでも解決する必要があります。

JavaScriptv1
const context = await SiteToApp.ready({ timeout: 1500 });

if (!context.available) {
  // Normal browser: keep using your existing web behavior.
  return;
}

await SiteToApp.page.setTitle('Order details');
await SiteToApp.navigation.setActive('orders');
コンテキストフィールド価値理由
利用可能ブール値ネイティブ シェルが有効なハンドシェイクを完了したかどうか。
プラットフォームios |アンドロイド |ウェブアクティブなランタイム。ユーザーエージェントから推測されることはありません。
appVersion文字列 |ヌルインストールされているネイティブ アプリのバージョン (利用可能な場合)。
sdkVersion弦ロードされた Web サイトの SDK バージョン。
protocolVersion番号 |ヌルブリッジ契約はアプリと交渉されました。
能力弦[]Navigation.badge や share などのコマンドがサポートされています。
colorSchemeライト |暗い現在のネイティブの外観。
safeArea上、右、下、左カスタム全画面レイアウト用の CSS ピクセルのインセット。
機能コードをチェックする必要があります context.capabilities インストールされているアプリのバージョンによってサポートが異なる場合。プラットフォームのチェックは最後の手段です。
ページのタイトルと状態

ネイティブヘッダーをコンテキスト内に保ちます。

顧客が製品、記事、アカウント セクション、またはチェックアウトに移動するときに、ページでアプリのヘッダーを変更できます。デフォルトでは、 setTitle ネイティブヘッダーと document.title したがって、ブラウザの履歴も役に立ちます。

JavaScriptv1
// Update both the document title and the app header.
await SiteToApp.page.setTitle('Your cart');

// Change only the native header.
await SiteToApp.page.setTitle('Checkout', {
  document: false,
  native: true,
});

// Return to the title derived from the page or app configuration.
await SiteToApp.page.resetTitle();
page.setLoading(boolean)

Web サイトの遷移をシェル読み込みインジケーターに接続します。ページが永久に実行されたままにならないように、アプリは自動タイムアウトを強制する必要があります。

page.setPullToRefresh(boolean)

ジェスチャがページの動作と競合する描画サーフェス、マップ、またはインタラクションについては、プルして更新を無効にします。

ナビゲーションバッジ

現在重要なカウントを表示します。

ナビゲーション項目は、SiteTo.App ビルダーで構成された安定した ID を使用します。 cart, inbox、 または bookings。ラベルは変更される可能性がありますが、それらの ID は Web サイトとアプリの間の契約のままです。

既知の値を設定する

JavaScriptv1
// Numbers are formatted by the native app: 100 becomes “99+”.
await SiteToApp.navigation.setBadge('cart', 3);

// Zero, null, or false hides the badge.
await SiteToApp.navigation.setBadge('cart', 0);

// Short status labels are also allowed.
await SiteToApp.navigation.setBadge('inbox', 'NEW');

URLから更新する

ウォッチャーは、別の SiteTo.App サービスからではなく、Web サイトのコンテキストで取得します。通常のサイトの Cookie とセキュリティ ルールがそのまま維持されるため、相対的な同じオリジン URL が推奨されます。

Shopify スタイルのカートの例v1
const cartBadge = SiteToApp.navigation.watchBadge('cart', {
  url: '/cart.js',
  jsonPath: 'item_count',
  interval: 30_000,
  refreshOn: ['ready', 'resume', 'focus', 'urlchange'],
  hideWhenZero: true,
  stale: 'keep',
});

// Refresh after a local add-to-cart action.
await cartBadge.refresh();

// Stop fetching when this page no longer owns the badge.
cartBadge.stop();
オプションデフォルト行動
URL必須JSON またはプレーン テキストを返す HTTPS または相対 URL。
jsonPathなしcart.item_count などのドット パス。 JSON 自体がバッジ値ではない場合に必須です。
間隔無効ポーリング間隔はミリ秒単位で、最小値は 15 秒です。
refreshOn準備完了、再開Ready、Resume、focus、urlchange の任意の組み合わせ。
資格同起源ブラウザーの資格情報の取得モードを使用します。クロスオリジンリクエストには引き続き CORS が必要です。
タイムアウト5000ミリ秒単位の最大フェッチ時間。
hideWhenZero真実マッピングされた結果が 0、null、または false の場合、バッジを非表示にします。
古い保つエラー後は最後の有効な値を保持します。クリアが代替手段です。
  • 数値は 1 ~ 99 で表示されます。より大きな値はネイティブを使用します 99+ treatment.
  • テキスト値はトリミングされ、サニタイズされ、表示される文字は 4 文字に制限されます。
  • アプリがバックグラウンドで実行されている間はポーリングが一時停止され、1 回の即時更新で再開されます。
  • 重複するリクエストはキャンセルされます。最新の有効な応答が優先されます。
  • HTTP、解析、およびマッピングのエラーが発生する sdk:error ページを壊さずに。
ネイティブアクション

デバイスの動作を適切な場所で使用します。

ネイティブ アクションは、既存の Web フローを改善するものであり、Web サイトを使用するための要件となるものではありません。権限プロンプトは明確なユーザーアクションに続き、最初にページ内でその値を説明する必要があります。

共有、通知、触覚v1
await SiteToApp.share({
  title: 'Spring collection',
  text: 'These just arrived.',
  url: window.location.href,
});

// Must be called from a user click or tap.
const permission = await SiteToApp.notifications.requestPermission();

// Use sparingly for confirmation, not decoration.
await SiteToApp.haptics.impact('light');

便利なフォールバックを使用して共有する

アプリ内のネイティブ共有シートを使用し、 navigator.share 利用可能な場合は、ユーザーアクション後のクリップボードフォールバック。

許可ステータスをシンプルにする

戻る default, granted, denied、 または unsupported。生のプッシュ トークンをページ コードに公開しないでください。

外部リンクを意図的に開く

内部で承認された URL はアプリ内に残ります。アプリ構成で特に指定されていない限り、外部 HTTPS リンクはシステム ブラウザーで開きます。

レート制限の物理的フィードバック

サポートされていない場合、ハプティクスは無視され、ページが破壊的なフィードバックを繰り返し生成するのを防ぐためにネイティブに調整されます。

アプリイベント

Web サイトがアプリのライフサイクルに対応できるようにします。

イベントは、スキーマとオリジンの検証後にネイティブ シェルから SDK に流れます。ハンドラーはパブリックで最小限のペイロードを受け取り、購読解除関数を返すため、コンポーネントベースのサイトはペイロードをクリーンアップできます。

イベントのサブスクリプションv1
const unsubscribe = SiteToApp.on('app:resume', () => {
  cartBadge.refresh();
});

SiteToApp.on('navigation:reselect', ({ itemId }) => {
  if (itemId === 'home') window.scrollTo({ top: 0, behavior: 'smooth' });
});

SiteToApp.on('notification:opened', ({ url }) => {
  if (url) window.location.assign(url);
});

// Remove a listener when its owning component unmounts.
unsubscribe();
app:resume

アプリがフォアグラウンドに戻りました。時間に敏感なページ データと監視されたバッジを更新します。

app:pause

アプリがバックグラウンドに移動しました。ブラウザーによってまだ処理されていない高コストの作業を一時停止します。

navigation:reselect

ユーザーは、現在アクティブなネイティブ ナビゲーション項目を再度タップしました。通常、フィードを一番上までスクロールします。

route:open

シェルは、ページ ルーターが完全にリロードせずに処理する必要がある信頼できるディープ リンクを受け取りました。

notification:opened

ユーザーがプッシュ通知を開いた。ペイロードには、承認されたアプリ内 URL とオプションのパブリック メタデータが含まれます。

network:change

オンラインとオフラインの間で接続が変更されました。ブラウザは、実際のフェッチの成功に関する信頼できる情報源であることに変わりはありません。

appearance:change

ネイティブの明るいまたは暗い外観が変更されました。ペイロードには新しい配色が含まれています。

sdk:error

ウォッチャー、ブリッジ コマンド、またはメッセージの検証が失敗しました。機密性の高いログではなく、診断を目的としています。

ブラウザのフォールバック

ウェブサイトはウェブサイトであり続けなければなりません。

アプリ内にいないことは通常の状態であり、例外ではありません。 SDK は、ネイティブの対応物が存在しない場合でも、コンソールのノイズを回避し、予測可能な結果を​​返さなければなりません。

特徴通常のブラウザの動作
準備ができてタイムアウト後に、available: false および platform: web で解決されます。
page.setTitleドキュメントが有効になっている場合は document.title を更新します。ネイティブ配信レポートは誤りです。
バッジとアイテムの状態デフォルトではフェッチまたはレンダリングを行いません。返されたリターン: スローせずに false。
navigation.openターゲットに応じて、location.assign、location.replace、または window.open を使用します。
navigation.backブラウザ履歴が利用可能な場合は、history.back を使用します。
共有navigator.share を使用し、ユーザー ジェスチャの後にクリップボードを使用します。
通知返品はサポートされていません。ブラウザ通知システムの代わりにはなりません。
ハプティクス配信済みの安全な no-op: false。
コマンドは次のような小さな結果に解決される必要があります。 { delivered: false, reason: 'not-in-app' }。無効な引数とネイティブの拒否には型付きを使用します SiteToAppError codes.
v1 サーフェス

完全なメソッドリファレンス。

SiteToApp.ready(options?)

ハンドシェイクを待ってから、現在の AppContext に解決します。それは常に解決されます。通常のブラウザは、available: false を返します。

SiteToApp.getContext()

最後にネゴシエートされたプラットフォーム、バージョン、セーフエリア値、カラースキーム、および機能リストを返します。

SiteToApp.isAvailable()

検証されたネイティブ ブリッジが現在接続されているかどうかを同期的に報告します。

SiteToApp.page.setTitle(title, options?)

document.title、ネイティブ ヘッダー、またはその両方を更新します。空のタイトルは拒否されます。

SiteToApp.page.setLoading(loading)

ページ遷移または長時間実行アクションのシェル読み込みインジケーターを表示または非表示にします。

SiteToApp.page.setPullToRefresh(enabled)

ジェスチャが適切な画面のネイティブのプルツーリフレッシュを有効または無効にします。

SiteToApp.navigation.setBadge(itemId, value)

設定済みのナビゲーション項目バッジを設定します。ゼロ、null、および false はそれをクリアします。

SiteToApp.navigation.watchBadge(itemId, options)

ライフサイクル トリガーまたは制御された間隔でバッジ値を取得してマッピングします。リフレッシュおよび停止コントロールを返します。

SiteToApp.navigation.setActive(itemId)

Web サイトに移動せずに、構成済みのネイティブ ナビゲーション項目を選択します。

SiteToApp.navigation.syncWithLocation(rules)

ブラウザの履歴を観察し、アクティブなアイテムを URL 一致ルールに合わせて維持します。購読解除関数を返します。

SiteToApp.navigation.setItem(itemId, state)

既存の構成アイテムのラベル、可視性、または有効な状態を更新します。

SiteToApp.navigation.open(url, options?)

現在の Web ビューで承認された内部 URL を開くか、システム ブラウザで外部 HTTPS URL を開きます。

SiteToApp.navigation.back()

使用可能なネイティブ ルートがない場合は、ブラウザ履歴に戻るようにシェルに要求します。

SiteToApp.share(data)

Web 上の navigator.share およびクリップボード フォールバックを含むネイティブ共有シートを開きます。

SiteToApp.notifications.requestPermission()

ユーザーのジェスチャ後に通知許可を要求し、その結果のステータスを返します。

SiteToApp.notifications.openSettings()

以前に許可が拒否されたときに、このアプリのオペレーティング システム設定を開きます。

SiteToApp.haptics.impact(style)

軽度、中度、または重度の影響のフィードバックをリクエストします。サポートされていない場合、これは何も行われません。

SiteToApp.on(event, handler)

検証されたアプリのイベントをサブスクライブし、サブスクライブ解除機能を受け取ります。

SiteToApp.once(event, handler)

次に一致するイベントをサブスクライブし、ハンドラーを自動的に削除します。

入力されたエラー: INVALID_ARGUMENT, UNSUPPORTED, NOT_ALLOWED, TIMEOUT, FETCH_FAILED, PROTOCOL_MISMATCH、 そして NATIVE_ERROR.

ブリッジプロトコル

確認済みの小さなメッセージ エンベロープ。

JavaScript レイヤーは、プラットフォームのトランスポートの詳細を正規化します。アプリでは、メッセージはシリアル化された JSON として React Native WebView トランスポートを経由して送信されます。 window.ReactNativeWebView.postMessage。エンベロープはそのトランスポートから独立しています。

ウェブサイトからアプリへ

コマンドエンベロープv1
{
  "channel": "sitetoapp",
  "protocolVersion": 1,
  "id": "sta_01J8ZQ6JY1",
  "type": "navigation.badge.set",
  "payload": {
    "itemId": "cart",
    "value": 3
  },
  "timestamp": 1789584000000
}

アプリの承認

応答エンベロープv1
{
  "channel": "sitetoapp",
  "protocolVersion": 1,
  "type": "response",
  "replyTo": "sta_01J8ZQ6JY1",
  "ok": true,
  "payload": null
}

アプリからウェブサイトへ

検証されたネイティブ イベントv1
// Native shell → website. Internal SDK method; not public surface.
window.SiteToApp.__receive({
  channel: 'sitetoapp',
  protocolVersion: 1,
  type: 'event',
  event: 'app:resume',
  payload: { occurredAt: Date.now() },
});
  • SDK は次から始まります bridge.hello;アプリは、サポートされているプロトコルのバージョンと機能で応答します。
  • すべてのコマンドは一意の ID を取得します。確認が必要なコマンドは、その ID を参照する応答を受け取ります。
  • デフォルトの確認応答タイムアウトは 2 秒です。タイムアウトが解決すると、遅い応答は無視されます。
  • メッセージは JSON のみで、64 KB に制限され、両側で 1 回ずつ解析されます。
  • タイトルとバッジの繰り返しの変更はデバウンスされます。最新の有効な値が優先されます。
  • __receive 実装のみであり、可能な限り列挙不可能であり、スキーマ外のメッセージを拒否します。
セキュリティルール

橋は設計上狭いです。

WebView ブリッジは Web コンテンツ内にネイティブ権限を作成するため、アプリ シェルは、ページがユーザーに属している場合でも、すべてのページ メッセージを信頼できない入力として扱います。次のルールを適用します。

1

ブリッジは、アプリに設定された正確な HTTPS オリジンと URL パターンでのみ有効になり、他の場所に移動する前に無効になります。

2

メッセージ タイプはホワイトリストに登録され、すべてのペイロードはネゴシエートされたプロトコル スキーマに対して検証されます。不明なフィールドは無視され、不明なコマンドは拒否されます。

3

ストア資格情報、プッシュ トークン、デバイス識別子、認証 Cookie、およびネイティブ ファイル システム パスがページ JavaScript に公開されることはありません。

4

相対 URL または検証された HTTPS 宛先のみが受け入れられます。 javascript:、data:、file:、intent:、およびカスタム スキームは、特定のコマンドで許可リストに登録されていない限りブロックされます。

5

許可プロンプト、共有フォールバック、設定リンク、および中断を伴うネイティブ アクションには、最近のユーザー ジェスチャが必要です。

6

コマンドにはレート制限があり、メッセージには 64 KB の上限があり、文字列とネイティブ呼び出しには長さ制限とタイムアウトがあります。

7

ペイロードは運用ログから編集されます。診断エラーにはコードとメッセージ ID が含まれますが、顧客のコンテンツや秘密は含まれません。

8

監視されたバッジ リクエストはブラウザーのフェッチ ルールに従います。同一生成元の資格情報がデフォルトです。クロスオリジン URL は CORS を渡す必要があります。

ライブに行く前に

統合をテストします。

SDK はアプリ内の動作のみを変更します。両方のパスを確認して、アプリ ユーザーがネイティブ エクスペリエンスを取得し、ブラウザー訪問者が Web サイトを以前とまったく同じように機能し続けるようにします。

  • 通常のモバイル ブラウザで SDK を呼び出すページを開き、何も壊れていないことを確認します。 context.available は誤りです。
  • iOS および Android のアプリで、低速ネットワーク、オフライン状態、バックグラウンドでの長時間後の再開などをテストします。
  • リロードおよびクライアント側のルート変更後に、タイトル、バッジ、およびアクティブなナビゲーションを確認します。
  • ネイティブ アクションの場合は、ユーザー ジェスチャ、アクセス許可が拒否されたパス、およびサポートされていないパスをテストします。
  • サイトでコンテンツ セキュリティ ポリシーを使用している場合は、SDK スクリプトのオリジンを許可します。

この契約に欠けているユースケースはありますか?

Web サイトのフロー、必要なアプリの動作、通常のブラウザーで何が起こるかを共有します。それは私たちが評価するのに十分です。

ユースケースを送信する