Aller au contenu

Transmettre le contexte

Le contexte pré-positionne le parcours de réservation. Le widget s’ouvre sur la première valeur non fournie, plutôt que sur la première étape.

Sept valeurs atteignent le widget par trois transports.

<!-- 1. Balise de script — pour un CMS, où il n'y a aucun JavaScript à écrire -->
<script src="https://app.useservice.app/widget/widget.js"
data-slug="chez-marie" data-date="2026-09-03" data-party-size="4" async></script>
2. URL — pour l'e-mail, le SMS, les QR codes, partout où votre site n'a aucun JavaScript
https://book.useservice.app/r/chez-marie?date=2026-09-03&party=4
// 3. JavaScript — pour un contexte qui change après le chargement de la page
widget.setContext({ date: "2026-09-03", partySize: 4 });

data-*, puis l’URL, puis setContext(). La dernière source à fournir une valeur l’emporte.

setContext() a la priorité la plus haute parce que le contexte change après le chargement : un client peut choisir ses dates dans le moteur de recherche de votre site avant d’ouvrir le widget.

La fusion se fait champ par champ. Une source qui ne fournit que partySize n’efface pas une date fournie auparavant.

Indicationdata-*URLFormat
datedata-datedateAAAA-MM-JJ
timedata-timetimeHH:MM, sur 24 heures
partySizedata-party-sizepartyEntier, 1 à 100
sectionKeydata-section-keysectionClé de groupe de salle, ou none
timeFromdata-time-fromfromHH:MM — créneau le plus tôt proposé
timeTodata-time-totoHH:MM — créneau le plus tard proposé
shiftIddata-shift-idshiftEntier — restreint le parcours à un service
localedata-localelocaleL’une des 11 langues client
guestNotesdata-guest-notesnotesTexte libre, jusqu’à 2 000 caractères

Les noms d’URL sont courts et faciles à taper à dessein : ils finissent dans des QR codes imprimés et des liens marketing, et ne reprennent donc volontairement pas l’orthographe des data-*.

timeFrom et timeTo ne proposent que les créneaux compris entre les deux, bornes incluses. C’est l’alternative portable à shiftId : un identifiant de service diffère d’un restaurant à l’autre, si bien qu’un groupe appliquant une même intégration à dix sites doit faire dix lectures, alors que 19:0022:30 signifie la même chose partout.

https://book.useservice.app/r/chez-marie?from=19:00&to=22:30

Les deux bornes sont nécessaires. Une borne seule est refusée plutôt que lue comme ouverte : vous avez écrit une plage, et une demi-plage appliquée en silence est pire que pas de plage du tout.

Elles se combinent avec shiftId au lieu de le remplacer, et chacune restreint indépendamment : un service et une plage donnent les créneaux qui satisfont les deux.

Trouver une clé de salle ou un identifiant de service

Section intitulée « Trouver une clé de salle ou un identifiant de service »

Les deux sont propres à chaque restaurant, et proviennent du même appel non authentifié que le widget effectue lui-même à l’ouverture :

Fenêtre de terminal
curl "https://app.useservice.app/api/v1/public/restaurants/chez-marie?include=section_groups,availability"

Les clés de salle figurent dans section_groups. Utilisez keyname est localisé et change, key non :

{ "section_groups": { "data": [
{ "key": "31", "name": "Terrasse", "area_type": "outdoor", "bookable_online": true }
] } }

Les identifiants de service figurent sur chaque jour d’availability, car les services d’un restaurant varient selon le jour :

{ "availability": { "months": { "2026-09": { "days": [
{ "date": "2026-09-03", "shifts": [ { "id": 1, "name": "Déjeuner", "start_time": "12:00", "end_time": "14:30" } ] }
] } } } }

Lisez-les une fois et mettez-les en cache par restaurant ; ils ne changent que lorsque le restaurant reconfigure son plan de salle ou ses services. Il n’existe pas d’endpoint de consultation distinct : c’est la charge utile même que le widget affiche, donc une valeur visible ici est une valeur que le tunnel acceptera.

Sur plusieurs restaurants, ne présumez pas que les identifiants coïncident. « Terrasse » correspond à une key différente dans chaque restaurant, et « Déjeuner » à un shift_id différent : un groupe qui applique une même intégration à dix sites doit faire une lecture par site.

sectionKey est le seul champ dont l’absence est elle-même une valeur. « Aucune préférence de salle, et le client ne peut pas la changer » se distingue de « aucune indication sur la salle ».

Les deux sont indiscernables sur le fil : après un nettoyage et un encodeur JSON, une clé absente, null et "" sont identiques. Le premier sens voyage donc sous la forme de la chaîne "none" :

widget.setContext({ sectionKey: "none" }); // aucune préférence, et c'est verrouillé
widget.setContext({ sectionKey: null }); // ne dit rien sur la salle

null est lu comme « aucune indication », et le sélecteur de salle est affiché. Envoyer null à la place de "none" produit donc le résultat inverse de celui recherché.

"none" est sans ambiguïté comme littéral : les clés de salle sont des identifiants convertis en chaîne, aucun restaurant ne peut donc porter ce nom de salle.

En tant qu’indice, "any" est également accepté (insensible à la casse) et signifie la même chose que null — « aucune indication sur le placement », sélecteur affiché. Il existe parce qu’any se lit naturellement dans une URL saisie à la main :

https://book.useservice.app/r/chez-marie?section=any

Les deux mots ne sont donc pas synonymes, et la différence tient au niveau de confiance, pas au placement :

ValeurSignification
"any"indice uniquementAucune indication — le client choisit, sélecteur affiché
nullindice uniquementIdentique à "any"
"none"jeton signéAucune préférence, et épinglé — sélecteur masqué

Seul un jeton signé peut épingler le placement ; "any" dans une URL ne le peut pas, car une URL que n’importe qui peut modifier n’est pas une contrainte.

locale choisit la langue dans laquelle le parcours démarre. Le widget en embarque onze :

CodeLangueCodeLangueCodeLangue
frFrançaisitItalianosvSvenska
enEnglishnlNederlandsnoNorsk
deDeutschptPortuguêsfiSuomi
esEspañoldaDansk

La correspondance est exacte. Les indicatifs régionaux et les autres orthographes ne sont pas reconnus : fr-CA, en-GB et FR sont ignorés comme toute autre valeur qui ne s’analyse pas. Envoyez le code seul.

Chaque restaurant choisit lesquelles des onze il propose à ses clients. Le widget affiche un sélecteur de langue lorsqu’un restaurant en propose plus d’une, et le choix du client est conservé par restaurant et l’emporte sur la valeur que vous fournissez — voir liens profonds.

Fournissez locale sur chaque surface où vous connaissez la langue du client. C’est la seule indication dont l’absence se remarque immédiatement.

Chaque valeur de cette page est une indication. Les indications sont falsifiables et le client peut toutes les modifier : le widget les traite donc comme une saisie du client.

L’identité n’est pas une indication et ne voyage pas ainsi. parseUrlHints n’a aucun nom d’URL pour un nom, un e-mail ou un téléphone : des champs d’identité ne peuvent donc pas apparaître dans une URL par accident. L’identité passe par un jeton signé — voir identifier le client.

Une valeur qui ne s’analyse pas est ignorée. Elle n’est jamais partiellement appliquée ni fatale : ?date=n-importe-quoi ouvre le calendrier ordinaire.

Les indications ne contraignent pas : le widget affiche la valeur et le client la modifie librement. Pour l’afficher comme fixe, verrouillez-la — depuis les trois mêmes transports :

<script data-locked="date" data-lock-reason="Bon cadeau BC-4471" async></script>

Un verrou posé ainsi est affiché, pas appliqué. Le serveur accepte une réservation qui le contredit, car une chaîne de requête ou un attribut peut être écrit par n’importe qui et il n’a aucun moyen de distinguer le vôtre du sien. Pour une valeur qui doit réellement tenir, placez le champ dans locked à l’intérieur du jeton signé, que le serveur applique bel et bien.

Les deux sont traités dans Verrouiller des champs.