Desenvolupem la teva web presencial SPA DES DE 300€. Si, es una bogeria. Web SPA DES DE 300€ — Si, es una bogeria. Parlem →

Com recollir incidències dels teus usuaris sense muntar un Jira

Com recollir incidències dels teus usuaris sense muntar un Jira

Quan un usuari reporta una errada, el que costa car no és obrir el tiquet: és la setmana de correus fins a aconseguir reproduir-la. Muntar un gestor d'incidències complet ordena els tiquets, però no arregla això. Aquí veuràs quin context capturar automàticament, com gravar la pantalla sense llibreries externes i per què el vídeo ha de poder gravar-se amb el formulari tancat. Els exemples van en Laravel, que és un dels stacks amb què més treballem, però la part important és JavaScript de navegador i serveix amb qualsevol backend.

El cost d'una incidència no és el tiquet, és reproduir-la

Pensa en el cicle complet d'una errada reportada per un usuari. Escriu «no em deixa desar». Algú li pregunta en quina pantalla. Contesta l'endemà. Li demanen una captura. Envia una foto del monitor feta amb el mòbil. Li pregunten quin navegador fa servir. No ho sap.

Aquí se'n van tres dies i quatre correus, i el tiquet encara no diu res útil. Muntar un gestor d'incidències complet no ho arregla: ordena tiquets, no els fa reproduïbles.

El que arregla el problema és capturar el context en el mateix instant en què l'usuari està veient l'errada, sense demanar-li res que no sàpiga contestar.

El context tècnic es captura sol, i és la meitat de la feina

De tot el que un desenvolupador necessita per reproduir alguna cosa, l'usuari només en pot aportar una part: què intentava fer i què va passar. La resta ho sap el navegador.

Un widget de report ben fet adjunta sense preguntar:

La URL exacta on era, que resol el «en quina pantalla» d'una tacada. El navegador i la seva versió, sense que ningú hagi d'anar-ho a buscar en un menú. La mida de la finestra, que és on s'amaguen la meitat de les errades de maquetació. L'idioma de l'aplicació, crític si és multiidioma. Qui ho reporta, si hi ha sessió iniciada. I d'on venia, que moltes vegades és la pista.

L'usuari només escriu el missatge. Tota la resta va sola, i surt de franc.

Gravar la pantalla ja no necessita cap llibreria

Gravar la pantalla sona a funcionalitat que exigeix una dependència pesada, i per això gairebé ningú no l'ofereix en un formulari d'incidències. La captura de pantalla fa anys que és part del navegador, i són quatre línies:

const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false });
const mime = ['video/webm;codecs=vp9', 'video/webm', 'video/mp4']
    .find(t => MediaRecorder.isTypeSupported(t)) || '';
const recorder = new MediaRecorder(stream, { mimeType: mime, videoBitsPerSecond: 2000000 });

Amb això l'usuari pot reproduir l'errada davant teu en comptes de descriure-la. I un vídeo de noranta segons amb l'errada passant val més que qualsevol descripció escrita per algú que no és tècnic.

Hi ha tres coses que cal acotar i no són opcionals. Un límit de durada, perquè ningú no es mirarà set minuts. Un límit de bitrate, perquè el vídeo s'acumula a la memòria del navegador abans de pujar-se i dos megabits per segon ja sobren per llegir una interfície. I detectar si el navegador pot fer-ho: la captura de pantalla exigeix context segur i no existeix al mòbil, així que el botó només ha d'aparèixer on funciona.

El formulari s'ha d'apartar perquè l'usuari pugui reproduir l'errada

Una funcionalitat pot estar sencera i perfectament provada i tot i així no fer-la servir ningú, perquè fa nosa justament en el moment que es necessita. Gravar la pantalla és l'exemple més clar que conec.

Si l'usuari prem «gravar» i el formulari de report es queda a sobre de la pantalla, no pot reproduir res: l'errada és a sota del diàleg. Així que en començar a gravar el formulari es tanca i al seu lloc queda una barra petita amb el cronòmetre i un botó d'aturar. L'usuari fa el que estava fent, atura, i el formulari es torna a obrir amb el vídeo ja adjuntat.

I cal contemplar que l'usuari talli des de la barra nativa del navegador, que apareix sempre que es comparteix pantalla:

stream.getVideoTracks()[0].addEventListener('ended', () => this.stopRecording());

Sense aquesta línia, qui premi «Deixar de compartir» a l'avís del navegador es queda amb una gravació penjada i sense manera de recuperar-la.

Andie recomana

L'enregistrament viu al navegador fins que s'envia, i per això no consumeix res del teu servidor mentre l'usuari reprodueix l'error. Perquè aguanti la navegació d'una aplicació tipus SPA, munta el widget dins d'un @persist: així l'usuari pot anar fins a la pantalla del problema amb l'enregistrament en marxa i enviar-lo des d'allà.

No acceptar SVG com a captura és una decisió de seguretat

Detall petit amb motiu real. A la validació de l'adjunt, la llista de formats acceptats inclou JPG, PNG, GIF i WebP, i deixa fora l'SVG a propòsit.

Un SVG és un document XML que pot contenir scripts. Si algun dia serveixes aquest adjunt des d'una URL pública, has acceptat pujar contingut executable al teu domini. És exactament el tipus de cosa que no es pensa quan s'escriu la llista de formats i es paga després.

Els adjunts van a disc privat, i això obliga a servir-los tu

Per defecte les captures i els vídeos van a emmagatzematge privat, sense URL pública. És el correcte, perquè una captura de pantalla d'un usuari pot contenir dades dels seus clients, i una URL endevinable en un bucket públic és una filtració esperant a passar.

La contrapartida és que cal servir-los a mà, amb una ruta protegida:

Route::get('/bugs/{report}/screenshot', [AdminController::class, 'bugScreenshot'])
    ->middleware(['web', 'auth', 'is_admin']);

Són deu línies i són les que separen un sistema de reports d'una fuita de dades. Si algú configura el disc com a públic «per provar», això ja no es desfà: les URL queden exposades.

Desar no és avisar

Una incidència desada en una taula que ningú no mira no serveix de gaire més que no haver-la recollit. És la part que s'ajorna sempre, perquè el formulari ja funciona i la confirmació apareix.

Un widget de report desa a la teva base de dades i retorna una confirmació, que és exactament la seva feina. L'avís i el flux de tiquets són decisions teves, i convé resoldre-les el mateix dia que l'instal·les: un usuari que es molesta a gravar un vídeo espera notar que algú l'ha vist.

El que cal afegir són dues coses i són petites. Una safata amb estats, encara que siguin tres: nou, vist, resolt. I un avís al canal on de debò mireu, que pot ser un correu o un missatge a un bot. A Crowd Legal la safata marca automàticament com a vist en obrir un report i esborra els adjunts del disc en eliminar-lo, que és el detall que evita acumular vídeos d'errades resoltes fa un any.

Què hi ha al mercat i en què es diferencia

El que es ven com a eines de report d'errors inclou coses que no competeixen entre elles: unes escolten l'aplicació, altres l'usuari, i altres només ordenen el que arriba. Confondre-les porta a comprar la que no tocava.

Sentry i similars capturen els errors sols, amb traça de pila i tot el context de l'excepció. És una categoria diferent i complementària: només veu el que peta. Un botó que no fa res, un total mal calculat o un text en l'idioma equivocat no llancen cap excepció, així que mai no hi arriben.

Marker.io, BugHerd i Usersnap estan pensades per a cicles de revisió amb client: anotar a sobre de la pàgina, marcar l'element, i empènyer el report directament a Jira o Trello. Per a una agència amb clients revisant lliuraments, això és valor real. El compromís: subscripció per usuari, un script d'un tercer carregat a les teves pàgines de producció i els reports vivint en un sistema que no és el teu.

Jira amb el seu widget et dona el flux de treball complet, i aquest és el seu punt fort i el seu cost: és una eina de gestió de projectes sencera per recollir quatre incidències.

La diferència de resoldre-ho dins de l'aplicació és que el report és una fila de la teva base de dades, amb una relació polimòrfica a l'usuari que el va enviar, així que pots creuar-lo amb el que ja saps d'ell. No hi ha script extern, no hi ha cost per usuari, i el widget té l'aspecte del teu producte. A canvi, la safata i els avisos els escrius tu.

I si no treballes amb Laravel

Els criteris són els mateixos i serveixen per valorar qualsevol solució:

  • Que capturi el context sense preguntar. URL, navegador, mida de finestra i identitat. Si els hi demanes a l'usuari, no te'ls donarà bé.
  • Que permeti gravar la pantalla i que el formulari s'aparti mentre grava.
  • Que els adjunts vagin a emmagatzematge privat per defecte.
  • Que no accepti formats executables com a imatge.
  • I que hi hagi algú mirant la safata. És la part que no dona cap eina.

On és el codi

El paquet és a Packagist, el codi a GitHub i la documentació del paquet recull totes les opcions. És MIT, sense dependències d'npm i sense peticions a tercers.

A Crowd Legal està només darrere de l'inici de sessió, com a pestanya al lateral, amb la safata d'administració i les rutes protegides que descriu aquest article.

Si tens un producte en producció i les incidències t'arriben per WhatsApp, això es munta en una tarda i canvia la relació amb els teus usuaris. Ho treballem a aplicacions web i SaaS a mida, i si ens expliques com us arriben avui et diem què muntar.

Escrit per
Edu Lazaro
Edu Lazaro
Founder & Lead Developer en AndorraDev

Desenvolupador full-stack amb més de 15 anys d'experiència en Laravel, React, Node.js i arquitectures cloud. Ajudo empreses a Andorra a construir la seva presència digital.

Partner de diseño · ionospace.
Necessites ajuda? ×
Andie by AndorraDev
Assistent IA + equip humà
Assistent IA d'AndorraDev
Andie
Hola! Soc Andie, l'assistent IA d'AndorraDev. En què et puc ajudar? Si necessites parlar amb Edu, només demana-ho.
17:31