···11# UXET
2233-**UX Evaluation Tool** — a browser-based framework for running usability tests with eye-tracking, interaction capture, and heatmap generation. Load any web app, give a user a task, and get back a full session debrief with gaze heatmaps and interaction stats.
33+**UX Evaluation Tool** — a browser-based framework for running usability tests against same-origin web apps with webcam eye-tracking, interaction capture, heatmap generation, and deterministic offline analysis.
4455## What it does
6677-1. **Load** a testable web app into a sandboxed iframe.
77+1. **Load** a configured same-origin test app into an iframe.
882. **Calibrate** eye-tracking via webcam (powered by [WebGazer](https://webgazer.cs.brown.edu/)).
993. **Record** a session — gaze data, mouse movement, clicks, keypresses, and scroll events are all captured while the user completes a task.
1010-4. **Debrief** — when the task is done (or a win condition fires automatically), UXET renders per-screen gaze heatmaps, v3 ranked findings, element-level issues, and interaction stats.
1111-5. **Export / Import** session data as JSON so UXET can re-analyze prior sessions offline, including temporary cohort comparison from multiple imported files.
1010+4. **Debrief** — when the task is done, either by app `postMessage` completion or manual stop, UXET renders per-screen gaze heatmaps, v3 ranked findings, element-level issues, data-quality warnings, and interaction stats.
1111+5. **Export / Import** session data as JSON so UXET can re-analyze prior sessions offline, including temporary cohort comparison from multiple imported files or repeated live runs of the same app/task.
12121313## Getting started
1414···40404141Once the server is up, open the URL in your browser, usually `http://127.0.0.1:8080`.
42424343-> **Requires:** `python3` (used for `python3 -m http.server`). That's it.
4343+> **Requires:** `python3` for the local static server. Real eye tracking also requires a modern browser with webcam permission and network access to the WebGazer/html2canvas CDNs loaded by `index.html`.
44444545### Run a test
46464747-1. Pick an app from the dropdown.
4747+1. Pick one of the configured apps from the dropdown.
48482. Click **Load App** — this launches eye-tracking calibration.
49493. Follow the calibration prompts (look at each dot and click it).
50504. When calibration passes, click **Start Test** to begin recording.
5151-5. Complete the task. The session ends automatically when the win condition is met, or press **Shift+Escape** to end it manually.
5252-6. Review the debrief screen — heatmaps, timing, click counts, fixation stats, etc.
5151+5. Complete the task. The session ends automatically when the iframe app sends `UXET_TASK_COMPLETE`, or press **Shift+Escape** to end it manually.
5252+6. Review the debrief screen — heatmaps, timing, click counts, fixation stats, ranked findings, element findings, and confidence warnings.
53537. Click **Test Again** to rerun the same app from the debrief screen, or **Export Data** to download the session as JSON.
54545555When you use **Test Again** on the same app, UXET keeps the completed live runs in memory and adds comparison insights after the second run. The comparison highlights repeated findings, repeated element-level patterns, and outlier sessions for that app/task until you reset or reload.
···60602. Select a UXET JSON export.
61613. UXET validates the file and renders the same debrief pipeline used for live sessions.
62626363-To compare sessions, select multiple UXET JSON exports in the import dialog. UXET analyzes the files in memory, reports repeated findings, element patterns, outlier sessions, and data-quality warnings, then discards the cohort when you reset or reload.
6363+To compare sessions, select multiple UXET JSON exports in the import dialog. UXET analyzes the files in memory, reports repeated findings, element patterns, outlier sessions, and data-quality warnings, then discards the cohort when you reset or reload. Exporting from cohort mode downloads the cohort analysis rather than a single session artifact.
64646565Legacy exports are still supported, but they may lack screenshots, dense mouse traces, or element snapshots. In those cases UXET shows fidelity warnings and limits the analysis accordingly.
6666···74747575## Export schema
76767777-New exports use `schemaVersion: "3"` and include:
7777+Session exports use `schemaVersion: "3"` and include:
78787979- full `screenRecords` with screenshots, gaze points, interaction events, and element snapshots
8080+- summary `screens` for compatibility with older UXET exports
8081- `mouseTrace` sampled during recording
8182- `fixations`
8283- `calibration`
8484+- `debug` metadata, including whether calibration was skipped or mouse-derived gaze was used
8385- `analysisContext`
8486- recomputed deterministic `analysis` with ranked findings, confidence, screen metrics, and element metrics
8587···93959496Element-level findings are generated when exports include element snapshots or click fingerprints. Future recordings capture more clickable/card-like elements as areas of interest, including `[data-id]`, `[onclick]`, `[tabindex]`, and pointer-cursor elements. If element snapshots are missing, UXET falls back to spatial zone metrics and shows a confidence warning.
95979696-### Analysis tests
9898+### Test status
97999898-Run the lightweight module tests with:
100100+There is currently no committed automated test suite or build step in this repository. Validate changes by running the static server, completing at least one live or mouse-gaze session, importing/exporting JSON, and checking the browser console for runtime errors.
99101100100-```bash
101101-node tests/analysis.test.js
102102-```
102102+## Adding your own apps
103103104104-Or open `tests/run-analysis-tests.html` from the local server.
104104+UXET discovers apps dynamically from folders under `testable-apps/`. Each app folder must include:
105105106106-## Adding your own apps
106106+- `index.html` for the app UI
107107+- `app.json` with the app name and task
107108108108-Drop your app into the `testable-apps/` directory and add a new `<option>` to the select in `index.html`:
109109+Example `testable-apps/your-app/app.json`:
109110110110-```html
111111-<option
112112- value="testable-apps/your-app/index.html"
113113- data-task="Describe the task for the user"
114114- data-win="postMessage">
115115- Your App Name
116116-</option>
111111+```json
112112+{
113113+ "name": "Your App Name",
114114+ "task": "Describe the task for the user"
115115+}
117116```
118117119119-UXET now uses one standardized win condition: `postMessage`. When the task is complete, the app inside the iframe should send:
118118+UXET always uses the standardized automatic win condition: `postMessage`. Do not include win-condition metadata in `index.html` or `app.json`. When the task is complete, the app inside the iframe should send:
120119121120```js
122121window.parent.postMessage({ type: 'UXET_TASK_COMPLETE' }, '*');
123122```
124123125124This keeps UXET app integration task-specific inside the app while giving UXET only one completion signal to listen for.
125125+126126+Because UXET directly reads iframe DOM, scroll, and event data, custom apps must be served from the same origin as UXET.
+1-9
index.html
···9393 <label class="field field-app" for="app-select">
9494 <span>App under test</span>
9595 <select id="app-select">
9696- <option value="">Select an app...</option>
9797- <option value="testable-apps/shop-app/index.html" data-task="Find and purchase a blue t-shirt"
9898- data-win="postMessage">THREAD Store</option>
9999- <option value="testable-apps/example-app/index.html"
100100- data-task="Fill out the feedback form with your details"
101101- data-win="postMessage">Feedback Terminal</option>
102102- <option value="testable-apps/long-page-app/index.html"
103103- data-task="Review the comparison sections and subscribe at the bottom of the page"
104104- data-win="postMessage">Signal Intelligence Report</option>
9696+ <option value="">Loading apps...</option>
10597 </select>
10698 </label>
10799