Installer Search sur une storefront headless
Cette page installe Search sur une storefront qui n’est pas un thème Shopify : un front headless, un site custom, ou toute stack dont vous écrivez vous-même le frontend. Sur un thème Shopify, suivez plutôt Installer Search sur Shopify.
Search est une recherche par mots-clés sur votre catalogue Dialog : elle compare les mots de la requête à vos produits, avec tolérance aux fautes de frappe, synonymes et produits épinglés. Vous avez trois façons de la brancher, de la plus prête à l’emploi à la plus libre :
| Option | À utiliser quand |
|---|---|
| Composants React ou Vue | Votre storefront tourne sous React ou Vue 3 : une barre de recherche et un panneau de résultats, prêts à intégrer. |
| Search controller du SDK | Tout autre framework ou du JS vanilla : le SDK exécute la recherche, vous affichez les résultats. |
| API REST | Vous appelez Search depuis votre propre serveur ou client, sans le SDK. |
Avant de commencer
Section intitulée « Avant de commencer »- Votre clé API publique : chaque option s’authentifie avec la clé API publique Dialog. Consultez Où trouver vos clés API. N’utilisez jamais la clé privée dans une storefront.
- Votre catalogue dans Dialog : Search renvoie les produits de votre catalogue Dialog. Vérifiez d’abord qu’il est synchronisé (Intégration du catalogue).
- Une langue et une devise : un code langue ISO 639-1 (
fr) et une devise ISO 4217 (EUR). Search tient un index par langue et par devise ; une locale régionale commefr-FRest refusée comme langue.
Composants React ou Vue
Section intitulée « Composants React ou Vue »@askdialog/dialog-react et @askdialog/dialog-vue fournissent une barre de recherche (DialogSearchBar) et un panneau de résultats (DialogSearchResults) par-dessus le search controller du SDK : useDialogSearch({ client, language, currency }) crée le controller, les deux composants l’affichent. Le panneau affiche les produits (et les collections, si vous les demandez), met en évidence la correspondance avec la requête dans chaque titre et pagine.
L’exemple de code et la référence complète du hook et des composants (options, props, adaptateur de routeur, colonne des collections) se trouvent avec chaque package :
Search controller du SDK
Section intitulée « Search controller du SDK »En dehors de React et Vue, utilisez createSearchController de @askdialog/dialog-sdk. Le controller envoie les requêtes et tient l’état de la recherche ; vous affichez les résultats à partir de cet état.
import { createSearchController, Dialog } from '@askdialog/dialog-sdk'
const client = new Dialog({ apiKey: 'YOUR_PUBLIC_API_KEY', locale: 'fr-FR', currency: 'EUR' })
const controller = createSearchController({ search: (request, options) => client.search(request, options), language: 'fr', currency: client.currency, analytics: { surface: 'search_page', trackViewSearchResults: (params) => client.trackViewSearchResults(params), trackSelectSearchResult: (params) => client.trackSelectSearchResult(params), },})
controller.subscribe((state) => render(state)) // votre renduinput.oninput = () => controller.setQuery(input.value)La référence SDK : createSearchController donne le câblage complet (impressions, clics, pagination), les options, les méthodes et l’état.
API REST
Section intitulée « API REST »Le SDK et les composants appellent l’endpoint POST /public/search/lexical. Appelez-le directement quand vous n’utilisez pas le SDK, par exemple depuis votre propre serveur.
POST https://api.askdialog.ai/public/search/lexicalContent-Type: application/jsonx-dialog-api-key: YOUR_PUBLIC_API_KEYAuthentification
Section intitulée « Authentification »Envoyez votre clé API publique dans le header x-dialog-api-key. Une requête sans clé, ou avec une clé inconnue, répond 401.
L’endpoint est limité par adresse IP : 20 requêtes par seconde. Au-delà, il répond 429 avec un header Retry-After.
Le body contient une entrée par index à chercher, dans requests (de 1 à 10 entrées). Toutes les entrées doivent partager la même query, la même langue et la même devise.
{ "requests": [ { "indexName": "products_fr_eur", "query": "chaussures de running", "page": 0, "hitsPerPage": 20 }, { "indexName": "collections_fr_eur", "query": "chaussures de running", "hitsPerPage": 5 } ]}| Champ | Type | Requis | Description |
|---|---|---|---|
indexName |
string |
Oui | <index>_<langue>_<devise>. <index> vaut products, collections, articles ou pages ; la devise est en minuscules (products_fr_eur). Ne demandez qu’un index présent dans votre catalogue : un index absent fait échouer toute la requête. |
query |
string |
Oui | La requête du visiteur : de 2 à 200 caractères, après trim. |
page |
number |
Non | Page, à partir de 0. Défaut 0. |
hitsPerPage |
number |
Non | Résultats par page, de 1 à 100. Défaut 20. |
facetFilters |
array |
Non | Filtres sur des valeurs, sur les entrées products uniquement. Voir Filtres. |
numericFilters |
array |
Non | Filtres sur des nombres, sur les entrées products uniquement. Voir Filtres. |
Un champ inconnu dans le body ou dans une entrée répond 400.
Les filtres restreignent une entrée products sur les attributs filtrables de votre catalogue, ceux que vous publiez dans Filtres produits : un filtre sur un autre attribut répond 400. Les deux champs sont une liste de groupes : les groupes se combinent en ET, les filtres d’un même groupe en OU.
{ "indexName": "products_fr_eur", "query": "veste", "facetFilters": [[{ "attribute": "color", "value": "noir" }, { "attribute": "color", "value": "marine" }]], "numericFilters": [[{ "attribute": "price", "from": 50, "to": 150 }]]}- Un filtre de facette s’écrit
{ attribute, value, negated? }. Passeznegated: truepour exclure la valeur. - Un filtre numérique s’écrit soit
{ attribute, operator, value }, avecoperatorparmi<,<=,=,!=,>=,>, soit en intervalle{ attribute, from, to }.
La réponse contient un résultat par entrée, dans results, dans l’ordre de la requête.
{ "results": [ { "index": "products_fr_eur", "hits": [ { "objectID": "product-123", "title": "Chaussures de trail", "url": "https://maboutique.fr/products/chaussures-de-trail", "handle": "chaussures-de-trail", "imageUrl": "https://cdn.maboutique.fr/trail.jpg", "priceRange": { "min": { "amount": "89.90", "currencyCode": "EUR" }, "max": { "amount": "99.90", "currencyCode": "EUR" } } } ], "nbHits": 42, "page": 0, "nbPages": 3, "hitsPerPage": 20, "processingTimeMS": 12, "query": "chaussures de running", "queryID": "5f0c..." } ]}Chaque résultat :
| Champ | Type | Description |
|---|---|---|
index |
string |
L’indexName de l’entrée. |
hits |
array |
Les enregistrements de cette page. |
nbHits |
number |
Nombre total de correspondances, toutes pages comprises. |
page |
number |
Page renvoyée, à partir de 0. |
nbPages |
number |
Nombre de pages. |
hitsPerPage |
number |
Taille de page appliquée. |
processingTimeMS |
number |
Durée de la recherche, en millisecondes. |
query |
string |
La requête cherchée. |
queryID |
string |
Identifiant de cette recherche, un par entrée. |
filters |
array |
Optionnel : les filtres appliqués à l’entrée, un bloc par source. |
Chaque hit porte objectID (l’identifiant de l’enregistrement) et, quand ils sont connus, ses champs d’affichage : title, url, handle, imageUrl, et pour les produits un priceRange (min et max, chacun avec un amount en chaîne décimale comme "24.90" et un currencyCode optionnel).
Les hits produits peuvent aussi porter leurs données d’achat, toutes optionnelles :
| Champ | Type | Description |
|---|---|---|
totalVariants |
number |
Nombre de variantes. |
tracksInventory |
boolean |
Le produit suit-il son stock. |
totalInventory |
number |
Stock cumulé des variantes. |
options |
array |
Options du produit : { name, values }. |
variants |
array |
Variantes : id, title, url, imageUrl, price, compareAtPrice, inventoryQuantity, inventoryPolicy, selectedOptions ({ name, value }). |
Le stock d’une variante n’est pas stocké sous forme de booléen : déduisez-le de inventoryQuantity et inventoryPolicy, au regard du tracksInventory du produit.
| Statut | Cause |
|---|---|
400 |
Body invalide : champ inconnu, requête de moins de 2 caractères, entrées avec des requêtes, langues ou devises différentes, ou filtre sur un attribut non filtrable. |
401 |
Clé API publique absente ou inconnue. |
404 |
Nom d’index inexistant, par exemple un nom mal formé ou sans suffixe de devise (products_fr). |
429 |
Limite de débit atteinte : réessayez après le délai Retry-After. |
502, 503, 504 |
Search est momentanément indisponible : réessayez plus tard. |
Les bodies d’erreur portent un statusCode et un message.
Vérifier votre installation
Section intitulée « Vérifier votre installation »Sur votre storefront :
- Tapez un nom de produit dans votre champ de recherche : des produits Dialog apparaissent.
- Tapez-le avec une faute de frappe : les bons produits apparaissent toujours.
- Cliquez sur un résultat : sa page produit s’ouvre.
- Changez de page avec la pagination : les résultats suivants se chargent.
Si aucun résultat n’apparaît jamais, vérifiez votre clé API publique et la synchronisation de votre catalogue, puis l’onglet réseau : un 404 désigne le nom d’index, un 401 la clé.
Sur le même sujet
Section intitulée « Sur le même sujet »- Vue d’ensemble de Search : ce que fait Search et les conditions de la bêta.
- Référence SDK : Search : options, méthodes et état de
client.search()etcreateSearchController. - Composants React : Recherche storefront et Composants Vue : Recherche storefront.
- Vue d’ensemble développeurs : l’API, le SDK et les packages de composants.
