Introducing LearnDash Course Analytics: Course-Level Reporting That Doesn’t Slow Your Site Down

If you run courses on LearnDash, you’ve probably asked some version of this question: “How is this course actually performing?” Not one student’s progress — the whole course. How many people enrolled? How many started? How many finished?

LearnDash gives you plenty of user-level detail, but getting a clean, course-level answer usually means exporting data, cross-referencing spreadsheets, or clicking through reports one course at a time. LearnDash Course Analytics exists to fix that: one dashboard, refreshed automatically, showing exactly where every course stands.

Why We Built This

The original version of this plugin worked the “obvious” way: for every course, loop through every enrolled user and call LearnDash’s own learndash_course_progress() function to check their status.

It worked fine — until a site with a large course catalog and an active user base tried to run it. That loop, combined with a theme’s support-tool plugin hooking into WordPress’s capability checks on every single call, exhausted the server’s memory limit and crashed the request. Not a great way to check on your course completion rates.

That failure taught us the right lesson: course-level reporting should never run expensive per-user logic at request time. So we rebuilt it around a completely different approach — and that rebuild is what shipped as LearnDash Course Analytics.

How It Works

Instead of calculating engagement numbers live, the plugin pre-computes them in the background:

  • Nightly aggregation. Once a day (by default, around 2am), the plugin runs a single grouped SQL query against LearnDash’s own activity data and rebuilds a summary table — one row per course, with enrolled/started/completed/not-started counts already calculated.
  • Batched processing. Rather than trying to process your entire course catalog in one request (which is exactly what caused the original crash), the aggregation runs in small batches via WordPress cron, picking up where it left off each time.
  • A run lock. Only one aggregation run can be in progress at a time, so a slow nightly run and a manual “Refresh Now” click can’t collide and corrupt each other’s data.

The result: opening the dashboard is just a fast read from a small, already-computed table. Nothing expensive happens while you’re looking at it, and nothing expensive happens because a visitor loaded your site.

What You Get

A single dashboard. Every course, with enrolled, started, completed, and not-started counts, plus a computed completion rate — sorted, searchable, and filterable by course category or status (e.g. “has completions,” “no activity yet”).

On-demand refresh. The nightly cron keeps things current automatically, but if you need up-to-the-minute numbers — right after a big course launch, for example — a “Refresh Now” button kicks off an immediate aggregation run.

CSV export. Export the full filtered report, or a single course’s data, whenever you need numbers for a stakeholder update, a board meeting, or your own records.

An activity log. Every aggregation run — nightly or manual — is logged with its trigger, duration, and status. If something ever looks off, you can see exactly when data last refreshed and whether the last run actually succeeded.

Getting Started

  1. Install and activate the plugin like any other WordPress plugin (Plugins → Add New → Upload Plugin).
  2. Activate your license under LearnDash Course Analytics → License, using the key emailed to you at purchase.
  3. That’s it — the first aggregation run kicks off automatically once your license activates, so you’re not stuck waiting until 2am for your first data.

From there, the dashboard lives under its own menu item in your WordPress sidebar, right alongside your other LearnDash tools.

Instead of calculating engagement numbers live, the plugin pre-computes them in the background:

  • Nightly aggregation. Once a day (by default, around 2am), the plugin runs a single grouped SQL query against LearnDash’s own activity data and rebuilds a summary table — one row per course, with enrolled/started/completed/not-started counts already calculated.
  • Batched processing. Rather than trying to process your entire course catalog in one request (which is exactly what caused the original crash), the aggregation runs in small batches via WordPress cron, picking up where it left off each time.
  • A run lock. Only one aggregation run can be in progress at a time, so a slow nightly run and a manual “Refresh Now” click can’t collide and corrupt each other’s data.

The result: opening the dashboard is just a fast read from a small, already-computed table. Nothing expensive happens while you’re looking at it, and nothing expensive happens because a visitor loaded your site.

A Few Things to Know

  • LearnDash LMS is required. This plugin reads LearnDash’s own activity data — it doesn’t work standalone.
  • Data refreshes on a schedule, not in real time. If a student completes a course at 9am, that won’t show up in the dashboard until the next aggregation run (nightly, or whenever you manually refresh). This is a deliberate trade-off: it’s what keeps the dashboard fast and keeps your site’s live traffic completely untouched by reporting overhead.
  • One license per site. Licenses are activation-limited per your purchase tier, so moving to a new domain means deactivating on the old one first (a one-click action from the License page) to free up the slot.

Why This Approach Matters

A lot of reporting tools are built to look impressive in a demo — real-time numbers, live-updating charts — without much thought for what happens when a real customer’s course catalog and user base grow past demo size. We built LearnDash Course Analytics from the opposite direction: start with the failure mode, then design around it.

The nightly-aggregation architecture isn’t a limitation we’re apologizing for — it’s the whole point. It’s the reason this plugin can sit on a large, active LearnDash site and just quietly keep working.