Skip to Content

Inactive Students for LearnDash — Documentation

Inactive Students for LearnDash — Documentation

What this plugin is for

Course completion rates are famously poor, and low completion quietly costs money: it drives refunds, it suppresses renewals, and it means no testimonials. LearnDash reporting will tell you what your completion rate is. It will not tell you where people give up.

This plugin answers that second question. It finds every learner who started a course and then stopped, shows the exact step each of them stopped on, and turns each course into a funnel so you can see which single lesson loses the most people.

It is entirely read-only with respect to LearnDash. It never changes a learner’s progress, enrolment or account.

Requirements

  • WordPress 5.8 or later
  • PHP 7.4 or later
  • LearnDash LMS (tested against 4.10)

Action Scheduler is used for background work when it is available — WooCommerce and many other plugins bundle it. If it is not present the plugin falls back to WP-Cron. There is nothing extra to install either way.

Installation

  1. Upload the plugin folder to /wp-content/plugins/, or install the zip through Plugins → Add New → Upload Plugin.
  2. Activate it.
  3. Go to LearnDash LMS → Inactive Students.
  4. Click Recalculate now to build the first report.
  5. Open the Settings tab and set the inactivity threshold to something that suits your courses.

If LearnDash is not active the plugin does nothing at all and says so in a notice, rather than causing errors.

The first scan

No report exists until a scan has run. Activation deliberately does not start one, because on a large site that would make activation hang. Instead the plugin schedules a nightly scan and waits.

To get results immediately, press Recalculate now. While you stay on the page the scan is driven forward from your browser, one chunk at a time, and the progress percentage updates as it goes. When it finishes the page reloads with the new figures. If you navigate away, the background queue carries on without you.

Report one — Stalled Learners

The Stalled Learners report, sorted by days inactive.
The Stalled Learners report, sorted by days inactive.

This is the “who has gone quiet” screen. Every row is one learner in one course.

ColumnWhat it means
StudentDisplay name and email address. The name links to their user profile.
CourseThe course they are stuck in. Flagged access expired if their access has lapsed and you have chosen to include those learners.
ProgressPercentage complete, plus the raw steps-completed-of-total. A step is a lesson, topic or quiz.
Stopped atThe first step in the course they have not completed — the thing sitting in their way. This is the column the plugin exists for.
Last activityThe last time they actually engaged with course content.
Days inactiveDays since that activity. The table sorts by this descending by default.
ActionView step opens the step they are stuck on. Email opens your mail client.

Above the table is a one-line summary — “38 of 210 students who started are inactive (18%)” — and, when you filter to a single course, the step most of them stopped at.

Use the Course filter to narrow to one course, and the search box to find a learner by name, username or email. Every column header except Stopped at and Action is sortable.

Report two — Course Drop-off

The Course Drop-off funnel, with the worst step highlighted.
The Course Drop-off funnel, with the worst step highlighted.

This is the “where does this course lose people” screen. Choose a course and you get its whole structure as a funnel, in reading order: a lesson, then its topics and quizzes, then the next lesson.

ColumnWhat it means
ReachedHow many learners got as far as this step — that is, everyone who passed the step before it. For the first step it is everyone who started the course.
PassedHow many of them completed it.
LostReached minus Passed.
Drop-offLost as a percentage of Reached. Shown in red from 20% upwards.

The worst step is highlighted and named in the summary line above the table. That single row is the point of the whole plugin: it tells you which lesson to rewrite first.

A note on non-linear courses

If your course does not enforce linear progression, a learner can complete step 5 without completing step 4. That would make a naive funnel report a negative drop-off. To avoid nonsense, Reached is floored at Passed for the same step, so drop-off never goes below zero. On a strictly linear course this makes no difference at all.

How “inactive” is defined

A learner appears in the Stalled Learners report when all of the following are true:

  1. They started. They have completed at least one step, or they have a recorded activity against the course. Merely being enrolled does not count — someone who bought a course and never opened it never started, and is a different problem needing a different fix.
  2. They have not finished. Learners who completed the course never appear.
  3. They have been quiet for at least N days, where N is your threshold (14 by default).

Two further rules keep the list honest:

  • Expired access. By default learners whose course access has expired are left out entirely — they did not quit, they lost access. You can switch to including them, flagged as such.
  • Unmeasurable learners. If a learner has progress but no activity record at all, their inactivity genuinely cannot be measured. Rather than guess, the plugin leaves them out and reports the count in the course summary.

Unpublished courses are skipped, and learners whose accounts have since been deleted are skipped cleanly rather than appearing as nameless quitters.

Where “last activity” comes from

The LearnDash user activity table, which records when a learner actually engaged with a lesson, topic, quiz or exam. Enrolment records are deliberately excluded, because enrolling is not starting.

Settings

The Settings tab.
The Settings tab.
SettingWhat it does
Inactive afterDays without activity before a learner counts as inactive. Default 14. Course length varies enormously — a two-week bootcamp and a twelve-month certification need very different thresholds. Takes effect on the next scan.
Expired accessLeave expired learners out (default), or include them flagged as access expired.
Staff accountsLeave administrators and group leaders out of the report. On by default.
Skip these coursesCourses never scanned. Useful for evergreen or reference material nobody is expected to finish, which would otherwise dominate the report.
RecalculateHow often the scan runs by itself: daily (recommended), twice daily, hourly, or only when you press the button. Scheduled scans start around 3am site time.
Learners per chunkHow many learners each background chunk processes. Lower it if your host times out during a scan; raise it to finish sooner on a capable server. Default 200.

How the background scan works

This is the heaviest query in any LearnDash reporting tool — every learner, against every course, against every step. On a site with thousands of students it cannot run on page load, so it never does.

Instead, the scan runs in the background in chunks and writes its results to three of its own database tables. The admin screens only ever read those cached rows. That is why they open instantly regardless of how many students you have, and why the header always tells you when the figures were last calculated.

Some specifics worth knowing:

  • Results are versioned. Every row is written with the ID of the scan that produced it. A finished scan is promoted by pointing a “live” marker at it and deleting older rows. A scan that dies half way through therefore cannot corrupt what you are looking at — you keep seeing the last good results.
  • Only one worker at a time. Action Scheduler, WP-Cron and your browser can all try to advance the same scan. A database-level lock ensures exactly one of them processes any given batch, so nothing is ever counted twice.
  • Loopbacks are not assumed to work. On many hosts — and on most local development environments — WP-Cron and Action Scheduler never fire because the site cannot make an HTTP request to itself. If that is your situation the nightly scan would silently never run. While you are on the report page the browser drives the scan instead, so Recalculate now always works. If your scheduled scans never seem to happen, that is the cause, and a real system cron is the fix.

Exporting and re-engaging

Both reports export to CSV. The export honours whatever filters are on screen and matches the visible data exactly, so what you download is what you were looking at.

The Copy … email addresses button puts every address in the current filtered list on your clipboard, de-duplicated and comma-separated, ready to paste into whatever you already send email with.

Why it will not email students for you

Deliberate. Sending email brings deliverability, consent and unsubscribe obligations that you do not want bolted onto a reporting plugin — and your existing mail tool already handles all three properly, with your existing unsubscribe link and your existing suppression list. This plugin hands you the list and gets out of the way.

For developers

Filters:

FilterPurpose
rau_isl_threshold_daysOverride the inactivity threshold in days.
rau_isl_chunk_sizeOverride how many learners each background chunk processes.
rau_isl_excluded_coursesOverride the array of excluded course IDs.

Action:

ActionFires
rau_isl_scan_completeAfter a scan completes and its results go live. Receives the scan ID.

Every LearnDash function call is wrapped in function_exists(), so a LearnDash release that moves or removes a function degrades to a skipped feature rather than a fatal error.

Troubleshooting

The report is empty

Check that a scan has run — the header says when it last did. If it says No results yet, press Recalculate now. If it has run and the list is genuinely empty, then nobody meets the criteria: everyone who started is either still active or has finished.

Everyone is stopped at step 1

That is usually correct and usually bad news: it means learners are enrolling, opening the course and not completing the very first step. Check whether that step is published, whether drip-feed is hiding it, and whether a prerequisite is blocking access.

A student I expected is missing

Work through the definition above. The most common reasons are that they finished the course, their access expired and you are excluding those learners, or their last activity is more recent than your threshold.

Scheduled scans never run

Almost always blocked loopback requests, which stop WP-Cron and Action Scheduler from firing at all. Confirm by pressing Recalculate now: if that works while the schedule does not, loopbacks are the cause. Setting up a real system cron for wp-cron.php fixes it site-wide.

The scan times out

Lower Learners per chunk in Settings. Each chunk is a separate request, so smaller chunks mean more, shorter requests.

Uninstalling

Deactivating stops all scheduled work but leaves the cached results in place, so reactivating does not lose your report. Deleting the plugin removes its three tables, its settings and its scheduled jobs, and touches nothing belonging to LearnDash or WordPress.

Frequently asked questions

Will this change anything in LearnDash?

No. It reads, counts and reports. It never writes to learner progress, enrolment or accounts.

How many days should I use?

Start at 14 and adjust once you have seen a report. A good threshold is comfortably longer than the gap a committed learner would normally leave between sessions on that course.

Does it work with groups?

Group members appear like any other learner. Filtering and reporting by group is not in this version.

Will it slow my site down?

No. Nothing is computed on page load. Scans run in the background in chunks, and the chunk size is adjustable if your host is constrained.

Does it work with ProPanel or other reporting plugins?

Yes. It reads LearnDash data and adds its own screens; it does not modify LearnDash behaviour, so it sits alongside other add-ons without conflict.