learning ai progress-tracking bug ux

AI Field guide page doesn't mark as complete the seen lessons

ramirobrescia

Student · 2024-01-17

Laravel Company

Hello Jeff and colleagues. I'm watching the 'AI Field Guide' course, and I've noticed that the lessons I've already watched aren't marking as complete. Thank you. A hug from Argentina

Learning platforms gain trust by reflecting user progress accurately; when completion state disappears, engagement drops sharply. The failure to mark a watched lesson as complete can stem from incomplete event dispatch, race conditions between video playback and progress APIs, or client-side storage that is cleared before the server acknowledges completion. This post proposes a remediation strategy for both frontend and backend.

Common Causes

Watch events often fire on timers or percentage thresholds. If the client fires the event and then navigates away before the server responds, the request is lost. Using fetch instead of a kept-alive mechanism makes the problem worse on slow networks. Similarly, optimistic updates that rely on localStorage without server confirmation can create false positives that are later overwritten.

Reliable Progress Tracking

Use navigator.sendBeacon() for progress pings so they survive page unload. On the server, accept progress events idempotently and store a timestamped completion record with a unique constraint on user_id plus lesson_id. This prevents duplicate progress entries and makes reconciliation simple. WebSocket updates can provide instant feedback when a user stays on the site, while background sync handles offline cases.

Data Integrity Concerns

Reliability in learning systems intersects with broader AI product concerns discussed in Recently Started Paying for AI, where the author describes data-integrity pitfalls from AI-assisted workflows. The same principle applies: treat user-generated signals as authoritative and reconcile asynchronous state changes deliberately.

Frontend Safeguards

Debounce progress events so that rapid playhead jumps do not flood the server. Show a saved indicator after a successful server response, and queued retries for offline support. For sensitive courses, sign progress payloads so they cannot be forged client-side.

Conclusion

Marking lessons complete is a state synchronization problem. Combine reliable delivery, idempotent server behavior, and visible feedback so users trust that their progress is safe.

Related Posts

These related posts cover AI product reliability, review discipline, and state synchronization patterns.

Likely Causes and Debugging

Course progress tracking typically relies on one of three patterns: localStorage entries, authenticated API calls marking lessons complete, or a mix of both. If the mark-as-complete action fails silently, inspect the Network tab in browser dev tools while watching a lesson. Look for a PATCH or POST request to an endpoint like /lessons/{id}/complete and check its response. A 401 or 403 indicates authentication issues, while a 4xx with a validation message suggests missing CSRF token or an incorrect endpoint.

Also verify that the course platform's frontend is actually attaching the lesson ID or user identifier to the request. In Single Page Apps built with Inertia or Vue, it's easy for a stale closure or incorrect prop to cause the UI to display an old completion state. Clear localStorage for the domain and re-login to force a fresh state load from the server.

Progress Tracking Architecture Patterns

Robust progress tracking usually stores completion records server-side in a pivot or dedicated table, keyed by user and lesson. localStorage is used only as a cache or offline buffer, not the source of truth. Periodic sync via navigator.sendBeacon or background sync ensures offline progress reaches the server. If the backend is Laravel, see How to review AI-generated code for considerations when the course content itself is AI-generated, and Recently Started Paying for AI for thoughts on maintaining data integrity in AI-driven education products.

Learning Analytics and Progress Tracking Pitfalls

Progress tracking systems in online courses must reconcile multiple sources of truth: the video player, the LMS database, and the user's browser. The player reports playback events (play, pause, seek, complete) via events or beacon requests. The LMS stores these in a lessons_user pivot table with completion flags and timestamps. If these systems drift, users see stale progress bars or unmarked lessons despite watching all material.

Causes include cross-origin restrictions blocking beacon requests, third-party cookie blocking preventing session identification, or backend race conditions where concurrent lesson-mark requests overwrite each other. Use database transactions for completion updates, and ensure your player SDK retries failed requests with exponential backoff.

Client-Side Resilience

Offline-first learning apps need robust sync. Queue completion events in IndexedDB and flush when online. Use the Background Sync API for retries on browser restart. Deduplicate events using a hash of (user_id, lesson_id, event_type, timestamp). For real-time progress updates, consider websockets via Laravel Echo; when the user completes a lesson, broadcast an event and update the UI instantly.

Related topics: How to review AI-generated code, Recently Started Paying for AI, and Tracking transferred bytes on the client side?.

Accessibility and Keyboard Navigation in Courser Interfaces

Progress marking should be accessible. Ensure the mark-complete button is keyboard focusable and announces its state via aria-live regions. Screen reader users need confirmation that a lesson was marked complete. If your UI relies solely on color changes, add text or icon indicators. Timing is also important: the confirmation should appear quickly so assistive technology can read it before focus moves.

For video players, provide keyboard shortcuts to play, pause, and mark complete. Captions and transcripts improve comprehension and should be synchronized with progress events. If a lesson has multiple segments, define what "complete" means: every segment watched, or a quiz pass? Make it explicit in the UI.

Session Persistence Across Devices

If users switch between desktop and mobile, progress should merge server-side. Use the user account as the source of truth, not localStorage. Ensure the API returns the authoritative completion status on each load. When marking complete fails offline, retry on the next network window with backoff and deduplication.

See How to review AI-generated code, Recently Started Paying for AI, and Laravel 13 + Sanctum + Fortify: API Routes Redirecting for related topics.

Design Recommendations for Course Platforms

Course platforms should treat progress as a first-class entity. Store completion per user per lesson with timestamps, expose a lightweight API to query and update progress, and require idempotent marking. Cache progress locally for offline resilience and sync with exponential backoff. Test the full flow under flaky network conditions using tools like Chrome DevTools Network throttling. Provide users with a progress refresh button that calls the API directly and reconciles local and server state.

See How to review AI-generated code, Recently Started Paying for AI, and Laravel 13 + Sanctum + Fortify: API Routes Redirecting for related topics.