Boucle de feedback analytique
Comment une requête de recherche devient un SearchUsageEvent, comment les clics et conversions sont enregistrés, et comment l'agrégation alimente le tableau de bord pour l'ajustement de pertinence.
Chaque interaction publique de recherche émet une ligne dans la table unifiée
SearchUsageEvent. Une seule table avec un discriminateur type (search_query,
zero_results, click, conversion, widget_open, filter_applied, visit)
garde le schéma petit et rend l'agrégation peu coûteuse.
Boucle de bout en bout
Description
Le diagramme montre comment une requête de recherche, un clic résultat et une conversion atterrissent tous dans la table unifiée SearchUsageEvent avec une corrélation queryId, puis sont agrégés par index × heure × type en métriques CTR, CVR et taux zéro-résultat. Le tableau de bord d'analytique Studio expose ces métriques, et les actions de l'éditeur (synonymes, curations, poids de champ, presets) refluent par policy-cache jusqu'au read path — la boucle se referme sans déploiement.
flowchart LR
classDef http fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef db fill:#fef3c7,stroke:#b45309,color:#78350f
classDef agg fill:#dcfce7,stroke:#15803d,color:#14532d
classDef ui fill:#ede9fe,stroke:#6d28d9,color:#4c1d95
subgraph Stage1["1 · Query"]
SDK1["Customer SDK / Widget"] --> Search["/api/search/public/multi"]:::http
Search --> Hit["TS multi_search<br/>returns hits"]
Hit --> Resp["Response sanitized<br/>queryId attached"]
Resp --> Ev1["recordSearchUsageAsync<br/>type=search_query"]:::db
Hit --> Zero{"hits.length == 0?"}
Zero -- yes --> Ev2["type=zero_results"]:::db
end
subgraph Stage2["2 · Click"]
SDK2["Widget / SDK click handler"] --> Track1["/api/events/track<br/>type=result_click"]:::http
Track1 --> Ev3["type=click<br/>{ queryId, productId, position }"]:::db
end
subgraph Stage3["3 · Conversion"]
SDK3["Checkout / add-to-cart"] --> Track2["/api/events/track<br/>type=conversion"]:::http
Track2 --> Ev4["type=conversion<br/>{ queryId, productId, conversionType }"]:::db
end
subgraph Stage4["4 · Aggregation (async)"]
Ev1 --> Agg["analytics aggregation<br/>group by indexId × hour × type"]:::agg
Ev2 --> Agg
Ev3 --> Agg
Ev4 --> Agg
Agg --> CTR["CTR = clicks / search_query"]
Agg --> CVR["CVR = conversion / click"]
Agg --> ZRR["zero-rate = zero_results / search_query"]
end
subgraph Stage5["5 · Dashboard refresh"]
CTR --> Studio["apps/saas analytics dashboard"]:::ui
CVR --> Studio
ZRR --> Studio
Studio --> Tune["relevance tuning:<br/>synonyms, curations,<br/>field weights, presets"]
end
Tune -. feeds .-> SearchLes types d'événements
| Type | Émis par | Porte |
|---|---|---|
search_query | public-handler.ts (fire-and-forget) | query, filters, sort, locale, queryId, referrer, ua |
zero_results | public-handler.ts quand found == 0 | même forme que search_query |
result_click → click | widget / SDK → /api/events/track | queryId, productId, position, sessionId |
widget_open | widget hébergé au montage | sessionId, anonymousUserId |
filter_used → filter_applied | widget au toggle de facet | filters (la facette/valeur choisies), queryId |
conversion | intégration checkout → /api/events/track | queryId, productId, conversionType (purchase, add_to_cart, ...) |
visit | widget optionnel au chargement de page | sessionId, anonymousUserId, referrer |
click (brut) | clic non lié à une recherche | productId, position |
Tous les événements partagent la forme de ligne
{ indexId, organizationId, type, count, metadata, createdAt }. La colonne JSON
metadata est le seul champ schéma-flexible ; elle est plafonnée à 4 Ko.
Ce qui relie un clic à une recherche
L'événement search_query côté serveur frappe un queryId stable et le renvoie dans
la réponse. Le widget renvoie le queryId dans chaque événement click /
conversion ultérieur. L'agrégation joint sur (organizationId, indexId, queryId)
pour calculer le click-through et la conversion par requête, par slot de ranking.
Boucle d'ajustement
Le tableau de bord analytique du Studio expose les trois ratios clés (CTR, CVR, taux de zéro-résultat) plus des drilldowns par requête. Un éditeur peut agir dessus en :
- ajoutant une règle de synonyme ou de stemming pour une requête à fort taux de zéro,
- promouvant une SKU via un curation set pour une requête peu cliquée,
- ajustant les poids de champs ou construisant un preset pour une requête à conversion lente.
Ces éditions arrivent dans le chemin de lecture via policy-cache (LRU 60 s) — la
boucle se ferme sans déploiement.
Liens associés
- Chemin de lecture — où
recordSearchUsageAsyncest appelé. - Cycle de vie du connecteur — la contrepartie côté ingest qui produit les documents recherchés et cliqués.
Cycle de vie du connecteur
Les six opérations du connecteur — handshake, heartbeat, full-sync, delta-sync, delete, diagnostics — et leur mapping sur la surface de la Connector API.
Vue d'ensemble de Relevance Studio
Qu'est-ce que Relevance Studio, les 16 panneaux d'administration organisés en 5 domaines (Pertinence, LTR, Health & Scale, Multi-région, Analytics & Debug) et quand utiliser Studio.