Un sito Web, con momenti compatibili con le app.
L'SDK è un miglioramento progressivo facoltativo. Le tue pagine possiedono ancora contenuti, routing, account, carrelli e regole aziendali. La shell nativa possiede il Chrome dell'app e le integrazioni del dispositivo. L'SDK trasmette messaggi piccoli e convalidati tra i due.
Non è coinvolto alcun servizio REST pubblico SiteTo.App. I siti Web non necessitano di una chiave SiteTo.App e l'SDK non deve mai contenere credenziali del negozio, segreti del cliente o token di account privilegiati.
Titoli delle pagine contestuali
Consenti a una pagina di pagamento, account o articolo di aggiornare l'intestazione nativa mantenendo corretto il titolo del browser.
Badge di navigazione in tempo reale
Invia immediatamente un valore noto o leggi il conteggio del carrello, della posta in arrivo o delle prenotazioni da un URL della stessa origine.
Navigazione consapevole del percorso
Mantieni l'elemento di navigazione nativo attivo allineato con le pagine tradizionali e i percorsi delle applicazioni a pagina singola.
Eventi del ciclo di vita
Aggiorna lo stato del sito Web obsoleto quando l'app riprende, si riconnette o si apre da una notifica o da un collegamento diretto.
Azioni native
Utilizza il foglio di condivisione del sistema, le richieste di autorizzazione, le impostazioni e il feedback tattile discreto, quando supportato.
Comportamento sicuro del browser
Ogni funzionalità ha un fallback o un no-op documentato del browser, quindi la base di codice di un sito Web continua a funzionare ovunque.
Uno script, con versione esplicita.
Aggiungi lo script CDN a un normale sito Web o installa il pacchetto npm in un'applicazione in bundle. Entrambi espongono lo stesso comportamento e la stessa versione del protocollo.
<script
src="https://cdn.siteto.app/sdk/v1/sitetoapp.min.js"
defer
></script>import { SiteToApp } from '@sitetoapp/web-sdk';Le versioni principali risiedono nell'URL e nel contratto del pacchetto. Le aggiunte non-breaking possono essere spedite all'interno v1; richiedono metodi rinominati, payload modificati o comportamenti di fallback diversi v2.
Rileva le capacità, non gli user agent.
SiteToApp.ready() inizia una stretta di mano con la shell nativa e si risolve in an AppContext. Deve anche risolversi in un normale browser, quindi il codice dell'applicazione non si blocca mai in attesa di un bridge non presente.
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');| Campo contesto | Valore | Motivo |
|---|---|---|
| disponibile | booleano | Se una shell nativa ha completato un handshake valido. |
| piattaforma | io | androide | web | Il runtime attivo; mai dedotto dall'agente utente. |
| appVersion | stringa | nullo | La versione dell'app nativa installata, quando disponibile. |
| sdkVersion | corda | La versione dell'SDK del sito Web caricata. |
| protocolVersion | numero | nullo | Il contratto ponte negoziato con l'app. |
| capacità | corda[] | Comandi supportati come navigazione.badge o condividi. |
| colorScheme | luce | buio | L'attuale aspetto nativo. |
| safeArea | in alto, a destra, in basso, a sinistra | Inserti in pixel CSS per layout personalizzati a schermo intero. |
context.capabilities quando il supporto varia in base alla versione dell'app installata. I controlli sulle piattaforme sono l’ultima risorsa.Mantieni l'intestazione nativa nel contesto.
Una pagina può modificare l'intestazione dell'app mentre i clienti si spostano tra prodotti, articoli, sezioni dell'account o checkout. Per impostazione predefinita, setTitle aggiorna sia l'intestazione nativa che document.title quindi anche la cronologia del browser rimane utile.
// 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)Collega la transizione di un sito Web all'indicatore di caricamento della shell. L'app deve comunque applicare un timeout automatico in modo che una pagina non possa lasciarla in esecuzione per sempre.
page.setPullToRefresh(boolean)Disabilita il pull-to-refresh per disegnare superfici, mappe o interazioni in cui il gesto è in conflitto con il comportamento della pagina.
Mostra il conteggio che conta adesso.
Gli elementi di navigazione utilizzano ID stabili configurati nel builder SiteTo.App, ad esempio cart, inbox, O bookings. Le etichette possono cambiare, ma tali ID rimangono il contratto tra il sito Web e l'app.
Imposta un valore noto
// 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');Aggiornamento da un URL
Un osservatore recupera nel contesto del sito Web, non da un servizio SiteTo.App separato. Si consigliano URL relativi della stessa origine perché mantengono intatti i normali cookie del sito e le regole di sicurezza.
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();| Opzione | Predefinito | Comportamento |
|---|---|---|
| URL | necessario | HTTPS o URL relativo che restituisce JSON o testo semplice. |
| jsonPath | nessuno | Percorso punto come cart.item_count. Obbligatorio quando JSON non è di per sé il valore del badge. |
| intervallo | disabilitato | Intervallo di polling in millisecondi, con un minimo di 15 secondi. |
| refreshOn | pronto, riprendi | Qualsiasi combinazione di ready, curriculum, focus e urlchange. |
| credenziali | stessa origine | Utilizza la modalità Recupera credenziali del browser. Le richieste multiorigine richiedono ancora CORS. |
| tempo scaduto | 5000 | Tempo di recupero massimo in millisecondi. |
| hideWhenZero | VERO | Nascondi il badge quando il risultato mappato è 0, null o false. |
| stantio | Mantenere | Conserva l'ultimo valore valido dopo un errore; chiara è l'alternativa. |
- I valori numerici vengono visualizzati da 1 a 99; valori più grandi utilizzano il nativo 99+ treatment.
- I valori del testo vengono ritagliati, ripuliti e limitati a quattro caratteri visibili.
- Il polling viene interrotto mentre l'app è in background e riprende con un aggiornamento immediato.
- Le richieste sovrapposte vengono annullate; prevale la risposta valida più recente.
- Vengono generati errori HTTP, di analisi e di mappatura
sdk:errorsenza rompere la pagina.
Utilizza il comportamento del dispositivo dove merita il suo posto.
Le azioni native dovrebbero migliorare un flusso web esistente, non diventare un requisito per l'utilizzo del sito web. Le richieste di autorizzazione devono seguire una chiara azione dell'utente e spiegare prima il loro valore nella pagina.
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');Condividi con un utile fallback
Utilizza il foglio di condivisione nativo nell'app, navigator.share ove disponibile, quindi un fallback negli appunti dopo un'azione dell'utente.
Mantieni semplice lo stato delle autorizzazioni
Ritorno default, granted, denied, O unsupported. Non esporre mai un token push non elaborato al codice della pagina.
Apri deliberatamente i link esterni
Gli URL approvati internamente rimangono nell'app. I collegamenti HTTPS esterni si aprono nel browser di sistema a meno che la configurazione dell'app non indichi diversamente.
Feedback fisico con limite di frequenza
Gli aspetti tattili vengono ignorati quando non supportati e limitati in modo nativo per evitare che una pagina produca ripetuti feedback di disturbo.
Lascia che il sito web risponda al ciclo di vita dell'app.
Gli eventi fluiscono dalla shell nativa all'SDK dopo la convalida dello schema e dell'origine. I gestori ricevono payload pubblici e minimi e restituiscono una funzione di annullamento dell'iscrizione in modo che i siti basati su componenti possano ripulirli.
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:resumeL'app è tornata in primo piano. Aggiorna i dati delle pagine sensibili al fattore tempo e i badge guardati.
app:pauseL'app è passata in background. Metti in pausa il lavoro costoso che non è già gestito dal browser.
navigation:reselectL'utente ha toccato nuovamente l'elemento di navigazione nativo attualmente attivo. In genere scorre un feed verso l'alto.
route:openLa shell ha ricevuto un collegamento profondo attendibile che il router della pagina dovrebbe gestire senza un ricaricamento completo.
notification:openedL'utente ha aperto una notifica push. Il payload contiene un URL in-app approvato e metadati pubblici facoltativi.
network:changeLa connettività è cambiata tra online e offline. Il browser rimane la fonte della verità per il successo effettivo del recupero.
appearance:changeL'aspetto nativo chiaro o scuro è cambiato. Il carico utile include la nuova combinazione di colori.
sdk:errorUn watcher, un comando bridge o una convalida del messaggio non sono riusciti. Destinato alla diagnostica, alla registrazione non sensibile.
Il sito web deve rimanere un sito web.
Non essere all'interno dell'app è uno stato normale, non un'eccezione. L'SDK deve evitare il rumore della console e restituire risultati prevedibili quando la sua controparte nativa è assente.
| Caratteristica | Comportamento normale del browser |
|---|---|
| pronto | Si risolve con available: false e platform: web dopo il timeout. |
| page.setTitle | Aggiorna document.title quando il documento è abilitato; la consegna nativa riporta falsi. |
| badge e stato dell'articolo | Non recuperare o eseguire il rendering per impostazione predefinita. Reso consegnato: falso senza lanciare. |
| navigation.open | Utilizza location.assign, location.replace o window.open in base alla destinazione. |
| navigation.back | Utilizza History.back quando è disponibile la cronologia del browser. |
| condividere | Utilizza navigator.share, quindi appunti dopo un gesto dell'utente. |
| notifiche | Resi non supportati; non sostituisce il sistema di notifica del browser. |
| aptica | Safe no-op con consegna: falso. |
{ delivered: false, reason: 'not-in-app' }. Gli argomenti non validi e i rifiuti nativi utilizzano tipizzati SiteToAppError codes.Riferimento completo al metodo.
SiteToApp.ready(options?)Attendi l'handshake, quindi risolvi l'AppContext corrente. Si risolve sempre; un normale browser restituisce available: false.
SiteToApp.getContext()Restituisce l'ultima piattaforma negoziata, le versioni, i valori dell'area sicura, la combinazione di colori e l'elenco delle funzionalità.
SiteToApp.isAvailable()Segnala in modo sincrono se un bridge nativo convalidato è attualmente connesso.
SiteToApp.page.setTitle(title, options?)Aggiorna document.title, l'intestazione nativa o entrambi. I titoli vuoti vengono rifiutati.
SiteToApp.page.setLoading(loading)Mostra o nascondi l'indicatore di caricamento della shell per una transizione di pagina o un'azione a lunga esecuzione.
SiteToApp.page.setPullToRefresh(enabled)Abilita o disabilita il pull-to-refresh nativo per le schermate in cui il gesto è appropriato.
SiteToApp.navigation.setBadge(itemId, value)Imposta un badge per l'elemento di navigazione configurato. Zero, null e false lo cancellano.
SiteToApp.navigation.watchBadge(itemId, options)Recupera e mappa il valore di un badge sugli attivatori del ciclo di vita o su un intervallo controllato. Restituisce i controlli di aggiornamento e interruzione.
SiteToApp.navigation.setActive(itemId)Seleziona un elemento di navigazione nativo configurato senza navigare nel sito web.
SiteToApp.navigation.syncWithLocation(rules)Osserva la cronologia del browser e mantieni l'elemento attivo allineato alle regole di corrispondenza degli URL. Restituisce una funzione di annullamento dell'iscrizione.
SiteToApp.navigation.setItem(itemId, state)Aggiorna l'etichetta, la visibilità o lo stato abilitato di un elemento configurato esistente.
SiteToApp.navigation.open(url, options?)Apri un URL interno approvato nella visualizzazione Web corrente o un URL HTTPS esterno nel browser di sistema.
SiteToApp.navigation.back()Chiedi alla shell di tornare indietro, passando alla cronologia del browser quando non è disponibile alcun percorso nativo.
SiteToApp.share(data)Apri il foglio di condivisione nativo, con navigator.share e i fallback degli appunti sul web.
SiteToApp.notifications.requestPermission()Richiedi l'autorizzazione alla notifica dopo un gesto dell'utente e restituisci lo stato risultante.
SiteToApp.notifications.openSettings()Apri le impostazioni del sistema operativo per questa app quando l'autorizzazione è stata precedentemente negata.
SiteToApp.haptics.impact(style)Richiedi feedback sull'impatto leggero, medio o pesante. Questa operazione non è consentita quando non è supportata.
SiteToApp.on(event, handler)Iscriviti a un evento dell'app convalidato e ricevi una funzione di annullamento dell'iscrizione.
SiteToApp.once(event, handler)Iscriviti al prossimo evento corrispondente, quindi rimuovi automaticamente il gestore.
Errori digitati: INVALID_ARGUMENT, UNSUPPORTED, NOT_ALLOWED, TIMEOUT, FETCH_FAILED, PROTOCOL_MISMATCH, E NATIVE_ERROR.
Una piccola busta del messaggio con conferma.
Il livello JavaScript normalizza i dettagli di trasporto della piattaforma. Nell'app, i messaggi viaggiano sul trasporto React Native WebView come JSON serializzato window.ReactNativeWebView.postMessage. La busta è indipendente da tale trasporto.
Dal sito web all'app
{
"channel": "sitetoapp",
"protocolVersion": 1,
"id": "sta_01J8ZQ6JY1",
"type": "navigation.badge.set",
"payload": {
"itemId": "cart",
"value": 3
},
"timestamp": 1789584000000
}Riconoscimento dell'app
{
"channel": "sitetoapp",
"protocolVersion": 1,
"type": "response",
"replyTo": "sta_01J8ZQ6JY1",
"ok": true,
"payload": null
}Dall'app al sito web
// 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() },
});- L'SDK inizia con
bridge.hello; l'app risponde con versioni e funzionalità del protocollo supportate. - Ogni comando riceve un ID univoco. I comandi che necessitano di conferma ricevono una risposta che fa riferimento a quell'ID.
- Il timeout di riconoscimento predefinito è di due secondi. Le risposte tardive vengono ignorate una volta stabilito il timeout.
- I messaggi sono solo JSON, limitati a 64 KB e analizzati esattamente una volta su ciascun lato.
- Le modifiche ripetute al titolo e al badge vengono rimbalzate; prevale l'ultimo valore valido.
__receiveè di sola implementazione, non enumerabile ove possibile e rifiuta i messaggi esterni allo schema.
Il ponte è stretto per progettazione.
Un bridge WebView crea un'autorità nativa all'interno del contenuto web, quindi la shell dell'app tratta ogni messaggio della pagina come input non attendibile, anche quando la pagina appartiene a te. Fa rispettare queste regole:
Il bridge è abilitato solo sulle origini HTTPS esatte e sui pattern URL configurati per la tua app e disabilitato prima di spostarsi altrove.
I tipi di messaggio sono consentiti e ogni payload viene convalidato rispetto allo schema del protocollo negoziato. I campi sconosciuti vengono ignorati e i comandi sconosciuti rifiutati.
Le credenziali dell'archivio, i token push, gli identificatori del dispositivo, i cookie di autenticazione e i percorsi del file system nativo non vengono mai esposti al JavaScript della pagina.
Sono accettati solo URL relativi o destinazioni HTTPS convalidate. javascript:, data:, file:, intent: e gli schemi personalizzati vengono bloccati a meno che un comando specifico non li consenta.
Le richieste di autorizzazione, la condivisione di fallback, i collegamenti alle impostazioni e le azioni native di disturbo richiedono un gesto recente dell'utente.
La velocità dei comandi è limitata, i messaggi hanno un limite di 64 KB e le stringhe e le chiamate native hanno limiti di lunghezza e timeout.
I payload vengono oscurati dai registri di produzione. Gli errori diagnostici contengono codici e ID messaggio, mai contenuti o segreti del cliente.
Le richieste di badge controllati seguono le regole di recupero del browser. Le credenziali della stessa origine sono quelle predefinite; gli URL multiorigine devono superare CORS.
Metti alla prova la tua integrazione.
L'SDK modifica solo il comportamento all'interno della tua app. Controlla entrambi i percorsi in modo che gli utenti dell'app ottengano l'esperienza nativa e i visitatori del browser mantengano il sito Web funzionante esattamente come prima.
- Apri le pagine che chiamano l'SDK in un normale browser mobile e conferma che non si interrompe nulla quando
context.availableè falso. - Test nell'app su iOS e Android, incluse reti lente, stato offline e ripresa dopo un lungo periodo in background.
- Controlla titoli, badge e navigazione attiva dopo i ricaricamenti e le modifiche al percorso lato client.
- Per le azioni native, testa i percorsi gesto utente, autorizzazione negata e non supportato.
- Se il tuo sito utilizza una politica di sicurezza dei contenuti, consenti l'origine dello script SDK.
Hai un caso d'uso che non rientra in questo contratto?
Condividi il flusso del sito web, il comportamento dell'app di cui hai bisogno e cosa dovrebbe accadere in un normale browser. Questo ci basta per valutarlo.