Documentation
Feedback, de la balise au rapport
Une balise script sur votre site. Toute personne qui regarde une page peut pointer ce qui ne va pas, dire pourquoi, et vous envoyer l'image. Cette page couvre chaque réglage et chaque fonction du widget.
Installer le widget
- 1
Créez un projet
Un par site ou application. Une adresse e-mail suffit, sans carte.
- 2
Collez la balise
Copiez-la depuis le panneau Installer du projet et ajoutez-la au gabarit que partagent toutes vos pages.
- 3
Envoyez un rapport de test
Ouvrez le bouton, pointez quelque chose, envoyez. Le rapport apparaît dans votre projet.
La balise que donne l'application porte déjà la clé de votre projet et les réglages que vous y avez choisis. Collez-la une fois, juste avant la balise de fermeture body. Écrite à la main, elle ressemble à ceci :
<script
src="https://cdn.feedback.o27.io/widget.js"
data-project-key="YOUR_PROJECT_KEY"
defer
></script>La balise se configure à partir de ses propres attributs data-* et charge la dernière version du widget : les mises à jour arrivent sur votre site sans toucher à la balise. Dans une application monopage, chargez-la une fois dans la page HTML de base : elle reste en place pendant que votre routeur change de page.
Sans clé de projet, le widget n'apparaît pas, et la console du navigateur dit pourquoi.
Si votre site envoie une Content Security Policy, autorisez l'adresse du src de la balise dans script-src, et https://feedback.o27.io dans connect-src : c'est là que partent les rapports.
Comment naît un rapport
Ce que voient vos visiteurs, pour pouvoir le leur expliquer.
- Ouvrir. Le bouton se déplie en un panneau que le rapporteur peut déplacer n'importe où. Il sert aussi de légende dans l'image.
- Pointer. Choisissez Pointer, puis cliquez sur un élément pour le sélectionner, ou faites glisser pour dessiner une zone. Échap annule.
- Commenter. Chaque sélection reçoit un contour numéroté sur la page et un champ de commentaire dans le panneau. Note ajoute un message sur toute la page, sans rien sélectionner.
- Cadrer. L'image montre la zone visible quand toutes les sélections y tiennent, sinon la bande de page qui les contient toutes. Un clic passe à la page entière.
- Copier ou envoyer. Copier met l'image dans le presse-papiers ; Envoyer l'enregistre dans votre projet avec les commentaires. L'aperçu est facultatif et montre d'abord l'image exacte.
- Réduire ou fermer. Réduire garde le rapport et masque les contours ; Fermer l'abandonne. Tout effacer retire toutes les sélections et propose Annuler pendant quelques secondes.
Les sélections appartiennent à la visite en cours et ne sont pas conservées. Une fois un rapport envoyé, Envoyer reste inactif tant qu'il ne change pas : votre équipe ne reçoit jamais deux fois le même.
Options
Réglez les options par des attributs sur la balise script, ou passez-les à init() sous le nom indiqué sous chaque attribut. Le panneau Installer du projet écrit pour vous les plus courantes.
- data-project-keyOption de init()
projectKey· Par défaut aucune - La clé d'intégration de votre projet. Les rapports sont envoyés à ce projet.
- data-positionOption de init()
position· Par défautbottom-right - Le coin où démarre le bouton :
top-left,top-right,bottom-leftoubottom-right. - data-offset-xOption de init()
offsetX· Par défaut20 - La distance en pixels par rapport au bord gauche ou droit auquel la position s'ancre.
- data-offset-yOption de init()
offsetY· Par défaut20 - La distance en pixels par rapport au bord haut ou bas auquel la position s'ancre.
- data-compactOption de init()
compact· Par défautauto alwaysn'affiche que l'icône.autoretire le libellé sous 480 pixels.- data-accentOption de init()
accent· Par défaut#6d5dfc - La couleur du bouton et des contours.
- data-localeOption de init()
locale· Par défaut navigateur - Forcer la langue du panneau :
en,frounl. Sinon, le choix du visiteur, puis celui de son navigateur. - data-visibilityOption de init()
visibility· Par défautprotected protectedpour une application qui affiche des données clients,publicpour un site vitrine ou de documentation. Voir Ce que montre une capture.- data-excludeOption de init()
exclude· Par défaut aucune - Des sélecteurs CSS, séparés par des virgules, pour les données à flouter que la page ne peut pas marquer elle-même.
- data-consoleOption de init()
console· Par défautoff onenregistre les niveaux et les horaires des journaux avec chaque rapport, jamais les messages. Voir Diagnostics de la console.- data-tag-<key>Option de init()
tags· Par défaut aucune - Une étiquette par attribut, par exemple
data-tag-environment="staging". Voir Étiquettes. - data-reporter-email
data-reporter-nameOption de init()
reporter· Par défaut aucune - Qui envoie le rapport. Voir Qui signale.
- data-storage-keyOption de init()
storageKey· Par défauto27-feedback - Où la position du bouton est enregistrée. Utile seulement quand deux widgets partagent un domaine.
- data-api-urlOption de init()
apiUrl· Par défauthttps://feedback.o27.io - Où partent les rapports. À changer uniquement pour une plateforme auto-hébergée.
- init() uniquementOption de init()
vocabulary· Par défaut aucune - Les textes de votre interface dans la langue active, pour qu'ils restent lisibles dans les captures. Voir Interface et données.
- init() uniquementOption de init()
consoleMessages· Par défaut aucune - Des messages de journal exacts et fixes dont le texte peut être conservé. Voir Diagnostics de la console.
Placer le bouton
Une application dont l'en-tête occupe le bord haut et dont la zone de saisie occupe le bas n'a aucun coin libre. Gardez le coin et écartez le bouton avec un décalage :
<script
src="https://cdn.feedback.o27.io/widget.js"
data-project-key="YOUR_PROJECT_KEY"
data-position="bottom-right"
data-offset-y="88"
defer
></script>Vos valeurs sont un point de départ, pas un verrou : un bouton que le visiteur a déplacé garde sa propre position, et choisir un coin dans les réglages du panneau revient aux vôtres.
Qui signale
Nommez la personne qui envoie le rapport, pour que votre équipe puisse revenir vers elle. Sur une page rendue par votre serveur, écrivez-la sur la balise :
<script
src="https://cdn.feedback.o27.io/widget.js"
data-project-key="YOUR_PROJECT_KEY"
data-reporter-email="ada@example.com"
data-reporter-name="Ada Lovelace"
defer
></script>Dans une application qui découvre l'utilisateur après le chargement de la page, appelez setReporter dès qu'il est connu, et avec null à la déconnexion :
function withFeedback(run, tries = 50) {
const feedback = window.o27?.feedback
if (feedback) run(feedback)
else if (tries > 0) setTimeout(() => withFeedback(run, tries - 1), 200)
}
withFeedback((feedback) => feedback.setReporter({ email: user.email, name: user.name }))
// on sign-out
withFeedback((feedback) => feedback.setReporter(null))Les deux champs sont facultatifs et nettoyés des espaces. Une adresse qui n'en est pas une est écartée, et une paire vide efface le rapporteur.
Non vérifié. Quiconque détient la clé d'intégration peut envoyer n'importe quelle valeur : le rapporteur est une étiquette, pas une preuve d'identité. Il apparaît sur le rapport dans Feedback, dans le message Slack et dans le ticket Linear : n'envoyez que ce que leurs lecteurs peuvent voir.
L'objet window.o27.feedback
Une fois chargé, le script expose quatre fonctions sur window.o27.feedback.
- init(options) → { destroy() }
- Remonte le widget avec ces options, fusionnées par-dessus celles de la balise et de l'appel précédent. Servez-vous-en pour passer les options que seul JavaScript peut porter, ou pour changer l'accent quand votre thème change.
- destroy()
- Retire le widget de la page.
init()le ramène. - setTags(tags)
- Fusionne des étiquettes dans l'ensemble que porte chaque rapport. Une valeur
nullretire une clé. - setReporter(reporter | null)
- Remplace le rapporteur, contrairement à
setTags, qui fusionne.nulll'efface.
La balise script est différée : l'objet n'existe pas encore quand votre propre code s'exécute pour la première fois, et un appel trop précoce est ignoré sans erreur. Attendez-le :
function withFeedback(run, tries = 50) {
const feedback = window.o27?.feedback
if (feedback) run(feedback)
else if (tries > 0) setTimeout(() => withFeedback(run, tries - 1), 200)
}
withFeedback((feedback) =>
feedback.init({ vocabulary: () => Object.values(i18n.messages) }),
)Le script ne fournit aucune déclaration de types. En TypeScript, déclarez la variable globale une fois :
declare global {
interface Window {
o27?: {
feedback?: {
init(options?: Record<string, unknown>): { destroy(): void }
destroy(): void
setTags(tags: Record<string, string | number | boolean | null>): void
setReporter(reporter: { email?: string; name?: string } | null): void
}
}
}
}
export {}Ce que montre une capture
Chaque image que produit le widget protège ce que le rapporteur n'a pas pointé. Cela vaut pour Copier, Envoyer et le téléchargement proposé quand un envoi échoue, sur toutes les formules, et le rapporteur ne peut pas le désactiver.
Une application (data-visibility="protected", la valeur par défaut) floute toute donnée hors des sélections du rapporteur. Dans l'image envoyée à votre projet, ce texte est d'abord remplacé par un texte de substitution de même longueur : on ne peut pas le retrouver sous le flou.
Un site public (data-visibility="public") ne floute rien, sauf ce que la page marque comme privé.
Ce que le rapporteur sélectionne est toujours montré tel quel. La page elle-même n'est jamais modifiée : seule l'image l'est.
Interface et données
Dans une application, ce qui compte comme interface, et reste lisible, se décide en trois couches. Chacune l'emporte sur la précédente.
- 1Structure. Le texte dans
nav,header,footer,button,label,th,legend,summaryet leurs rôles ARIA est de l'interface. Les champs de formulaire, iframes, images, cellules de tableau et tout autre texte sont des données, titres compris. L'ancêtre le plus proche décide : un champ dans une nav reste une donnée. - 2Vos textes. Passez les textes d'interface de la langue active dans
vocabulary; un texte identique à l'un d'eux reste lisible où qu'il soit. Passez une fonction si le catalogue se charge plus tard ou si la langue change : elle est lue au moment de la capture. - 3Vos marqueurs.
data-feedback="private"floute un élément et tout ce qu'il contient ;data-feedback="public"le garde lisible. L'ancêtre marqué le plus proche l'emporte : une barre publique peut contenir un compteur privé. Les marqueurs fonctionnent sur les deux types de site.
<header>Acme <span data-feedback="private">Jean Dupont</span></header>
<section data-feedback="private">Customer account details</section>
<nav data-feedback="public">…</nav>
<script
src="https://cdn.feedback.o27.io/widget.js"
data-project-key="YOUR_PROJECT_KEY"
data-exclude=".customer-details, #billing-summary"
defer
></script>Pas la main sur le HTML ? Listez des sélecteurs dans data-exclude ; ils sont traités comme privés. Un sélecteur invalide bloque la capture plutôt que de laisser passer des données.
Diagnostics de la console
Désactivés par défaut. Avec data-console="on", chaque rapport porte le niveau et l'horaire des 60 derniers appels à la console. Leur contenu, les messages d'erreur, les piles et les objets sont remplacés par [redacted].
Pour garder le texte de messages précis, approuvez-les via init(). Seul un appel avec un unique argument texte identique à une entrée garde son texte :
withFeedback((feedback) =>
feedback.init({
console: true,
consoleMessages: ['Checkout failed', 'Search unavailable'],
}),
)N'approuvez que des messages fixes qui ne nomment personne : ajouter un argument ou insérer un identifiant masque à nouveau tout le message.
Ce que contient un rapport
Il contient l'image protégée du cadre choisi, les commentaires écrits par le rapporteur, l'emplacement de chaque sélection, l'origine de la page, la taille de la fenêtre, et des informations sur le navigateur : agent utilisateur, langue, densité de pixels, taille d'écran, préférences d'apparence et fuseau horaire. Plus vos étiquettes, le rapporteur, et les diagnostics de la console si vous les avez activés.
Il ne contient pas le titre de la page, le chemin, les paramètres ou le fragment de l'URL, ni aucune classe ou id CSS.
Vérifier votre intégration
- Placez un contenu de test reconnaissable dans une zone protégée, choisissez Copier et regardez l'image : les données hors de vos sélections doivent être illisibles, les commandes et les sélections nettes.
- Recommencez avec des champs de formulaire remplis et avec les sélecteurs listés dans
data-exclude. - Dans les outils réseau du navigateur, ouvrez la requête de capture : pas de titre, seulement l'origine de l'URL, et pas de champ console sauf si vous avez activé les diagnostics.
Slack et Linear
Les rapports arrivent toujours dans votre projet Feedback. Connectez Slack ou Linear une fois, dans Intégrations, et chaque projet peut aussi les y envoyer. Les intégrations font partie de la formule Team.
Slack publie chaque rapport dans un canal, image comprise. Invitez l'application Feedback dans ce canal, sinon la publication est refusée.
Linear transforme un rapport en ticket dans une équipe, avec son image et ses commentaires. Choisissez le statut, le projet et les labels des nouveaux tickets.
Les destinations se règlent par projet et par environnement, lu dans l'étiquette environment : les rapports de staging peuvent partir dans un canal et ceux de production dans un autre. Chaque destination est automatique, et reçoit chaque nouveau rapport, ou à l'envoi, et reçoit un rapport quand quelqu'un l'envoie depuis sa page dans Feedback.
Dépannage
Le bouton n'apparaît pas
Vérifiez que la balise porte la clé de votre projet, ou utilise l'adresse de projet copiée depuis l'application. La console du navigateur signale une clé manquante. Sur un site avec une Content Security Policy, voir Installer le widget.
Le bouton recouvre un de mes propres boutons
Ajoutez data-offset-x ou data-offset-y, ou choisissez un autre coin. Voir Placer le bouton.
Les rapports arrivent sans rapporteur
setReporter a sans doute été appelé avant le chargement du script, et ignoré. Attendez window.o27.feedback, comme dans L'objet window.o27.feedback.
Des parties de mon interface sont floutées
Un texte hors d'un élément structurel compte comme donnée. Marquez la zone data-feedback="public", ou passez vos textes d'interface dans vocabulary.
Des données clients sont lisibles dans les captures
Vérifiez que la balise ne porte pas data-visibility="public". Puis marquez la zone data-feedback="private", ou listez-la dans data-exclude.
La capture échoue immédiatement
Un sélecteur invalide dans data-exclude bloque toutes les captures. Vérifiez la liste dans les options avancées du projet.
Une image, une police ou une vidéo s'affiche mal dans la capture
Voir Limites connues.
Limites connues
- Les images servies depuis un autre domaine sans CORS, certaines polices web, et le contenu des iframes, canvas et WebGL peuvent ne pas apparaître exactement comme à l'écran.
- Les sélections et les commentaires ne vivent que le temps de la visite. Seule la position du bouton est conservée.