How to Migrate LearnDash to LifterLMS: What Maps and What Does Not

A practical plan to migrate LearnDash to LifterLMS: how courses, topics, quizzes, groups and certificates map, how to carry over enrollments and progress without spamming students, and how to protect URLs and subscriptions.

  • Add as a preferred source on Google
Illustration for “How to Migrate LearnDash to LifterLMS: What Maps and What Does Not”

If you want to migrate LearnDash to LifterLMS, the good news is that both are WordPress plugins. Your users, pages, media and theme stay where they are, and only the learning layer changes. The harder news is that the two products model courses differently, so a migration is a mapping exercise, not a button.

This guide is for site owners and developers planning that move. It shows what maps cleanly, what needs a decision, how to carry enrollments and progress across without triggering a flood of emails, and how to keep your URLs and recurring revenue intact.

For the general process that applies to any platform, such as audits, staging and rollback, read our LifterLMS migration guide first. This article covers the LearnDash specifics.

How LearnDash content maps to LifterLMS

LearnDash stores its content as custom post types: sfwd-courses, sfwd-lessons, sfwd-topic, sfwd-quiz, sfwd-question and sfwd-certificates, plus groups for group management. LifterLMS uses course, section, lesson, llms_quiz, llms_question and llms_certificate. The structures overlap but are not identical.

LearnDashLifterLMSNotes
CourseCourseDirect match. Description, featured image and categories carry over.
Section headingSectionIn LifterLMS every lesson must sit in a section, so sections are required, not optional.
LessonLessonDirect match.
TopicLesson, or a lesson inside a new sectionLifterLMS has no third level. See the next section.
Quiz on a lessonQuiz attached to that lessonA LifterLMS lesson holds one quiz.
Quiz on a topic or the whole courseQuiz on its own lessonCreate a lesson such as "Final assessment" to hold it.
Single and multiple choice questionsMultiple ChoiceCore question type.
Fill in the blank, sorting, essayAdvanced Quizzes add-on typesPaid add-on; otherwise rewrite the question.
AssignmentsAssignments add-onPaid add-on; submissions are usually archived, not migrated.
Groups and group leadersGroups add-onPaid add-on; rebuild groups and re-invite leaders.
CertificatesCertificate templatesRebuild the design in the LifterLMS block-based certificate editor.
Course pointsNo direct equivalentUse achievements, or GamiPress for points.

Decide how to handle topics and multiple quizzes

Topics are the biggest structural decision. You have two clean options.

  1. Flatten topics into lessons. Each LearnDash lesson becomes a LifterLMS section, and its topics become the lessons inside it. This works well when LearnDash lessons were really chapters and topics carried the content.
  2. Keep lessons and add topics after them. The LearnDash lesson stays a lesson, and its topics follow it as further lessons in the same section. This keeps your existing lesson titles but makes sections longer.

Pick one rule and apply it to every course, so students and reports stay consistent. If a LearnDash lesson has content as well as topics, the first option usually means turning that content into an introductory lesson at the top of the new section.

Quizzes need the same thinking. LifterLMS attaches at most one quiz to a lesson, so a course-level final quiz needs a lesson of its own. If you used lesson progression rules that required passing a quiz, recreate them with the Require Passing Grade on Quiz lesson setting and prerequisites. Our guide to drip content and prerequisites in LifterLMS covers those settings.

Migration tools: what exists and where they stop

There is no importer for LearnDash data in LifterLMS core. The core importer, under LifterLMS > Import, reads LifterLMS's own JSON export files. Your realistic options are:

  • A dedicated migration plugin. LifterLMS's own LearnDash migration article recommends Transfer by Honors WP, which it describes as moving student data as well as content. There is also a small plugin on WordPress.org, LD to Lifter, whose listing says it migrates courses, topics (as lessons), quizzes and optional student data, but not groups, assignments, essays or forums. Its install base is very small, so test it thoroughly.
  • Generic import tools. CSV export and import plugins can move course and lesson posts, but they do not understand the relationships between them or student progress. You will relink lessons by hand.
  • A custom migration script. For large sites, unusual structures or sites with paying subscribers, a script written for your data gives you full control and a repeatable dry run.

Whatever you use, run it on a staging copy first and compare counts: courses, lessons, questions, enrolled students and completions, before and after.

Moving enrollments and progress without spamming students

LearnDash keeps course access and progress in user meta and its own activity table. LifterLMS keeps enrollments and completions in its own table, wp_lifterlms_user_postmeta: an _status row of enrolled for each course or membership, and an _is_complete row of yes for each completed lesson, section and course. Our article on how LifterLMS stores its data explains that table in detail.

Three details trip up most first attempts:

  • Enrolling and completing fire engagements. llms_enroll_student() and llms_mark_complete() run the same hooks as a real enrollment or completion. Welcome emails, certificates and achievements will be sent to every migrated student unless you stop them. Switch off enrollment and completion emails under LifterLMS > Settings > Notifications while you import, and suppress engagements in your script.
  • Enrollment dates drive drip content. LifterLMS reads the enrollment date from the updated_date column of the _start_date row. If you enroll everyone today, lessons dripped "days after enrollment" lock again for long-standing students. Write the original date back.
  • Completion cascades. Marking the last lesson complete also completes the section and the course, which can award a certificate. That is usually what you want, as long as the certificate template is ready before you import.

Here is the core of a WP-CLI script that enrolls students from a CSV exported from LearnDash (email, LifterLMS course ID, original enrollment date) and keeps the original date. Run it with wp eval-file llmsx-import-enrollments.php enrollments.csv, then run wp cache flush.

<?php
// Stop engagements (emails, certificates, achievements) during the import.
add_filter( 'lifterlms_get_engagements', '__return_empty_array' );

global $wpdb;

$handle = fopen( $args[0], 'r' );
fgetcsv( $handle ); // Skip the header row.

while ( false !== ( $row = fgetcsv( $handle ) ) ) {
	list( $email, $course_id, $enrolled_at ) = $row;

	$user = get_user_by( 'email', $email );
	if ( ! $user ) {
		WP_CLI::warning( "No user found for {$email}" );
		continue;
	}

	$course_id = absint( $course_id );
	if ( ! llms_is_user_enrolled( $user->ID, $course_id ) ) {
		llms_enroll_student( $user->ID, $course_id, 'llmsx_learndash_import' );
	}

	// Restore the original enrollment date so drip schedules stay correct.
	$wpdb->query(
		$wpdb->prepare(
			"UPDATE {$wpdb->prefix}lifterlms_user_postmeta
			 SET updated_date = %s
			 WHERE user_id = %d AND post_id = %d
			 AND meta_key IN ( '_start_date', '_status', '_enrollment_trigger' )",
			$enrolled_at,
			$user->ID,
			$course_id
		)
	);
}

fclose( $handle );
WP_CLI::success( 'Enrollments imported.' );

Progress follows the same pattern with llms_mark_complete( $user_id, $lesson_id, 'lesson', 'llmsx_learndash_import' ) for each completed lesson or topic, using your topic mapping to find the right LifterLMS lesson ID. Detailed quiz attempt histories rarely justify the effort; most sites keep the final grade in a note or export and let students start fresh on quizzes.

Payments, subscriptions and WooCommerce

How you sold courses on LearnDash decides the work here.

  • One-time purchases. Past payments do not need to move. Students keep access through the enrollments you import, and you keep the payment records in Stripe or PayPal.
  • LearnDash recurring payments. Existing subscriptions keep billing in your gateway account, but LifterLMS knows nothing about them. Either let them run and manage access manually until each subscriber renews on a new LifterLMS access plan, or have a developer create matching LifterLMS orders linked to the existing gateway subscriptions. The second option is custom work and must be tested with real gateway events.
  • WooCommerce or a membership plugin. If WooCommerce sold access to LearnDash courses, you can keep it and switch to the paid LifterLMS WooCommerce integration add-on, which our article on LifterLMS with WooCommerce covers. Products then grant LifterLMS enrollments instead of LearnDash access.

Never run both LMS plugins' recurring billing at the same time on a cloned site. A staging copy with live gateway keys can charge real customers.

Keeping URLs and search rankings

LifterLMS uses /course/ for single courses, /courses/ for the course archive, and /lesson/ and /quiz/ for lessons and quizzes. You can change these bases in Settings > Permalinks, in the LifterLMS Permalinks section. Check your LearnDash permalink settings, including whether nested URLs were on, and list every public course and lesson URL before you start.

Then either match the old structure where it is simple, or add 301 redirects from each old URL to its new equivalent. Course sales pages matter most for search traffic. Lessons are mostly behind a login, but students bookmark them, so redirect those as well.

A cut-over plan that avoids downtime

  1. Clone the live site to staging and disable outgoing email and live payment keys there.
  2. Install LifterLMS alongside LearnDash, migrate content, and fix structure, quizzes and certificates course by course.
  3. Run the student migration on staging and compare counts and a sample of individual students.
  4. Rebuild checkout, access plans, memberships and integrations such as your CRM or email tool.
  5. Freeze course edits on live, re-run the student import against a fresh copy of the data, and switch.
  6. Add redirects, deactivate LearnDash, and keep its data in the database for a few weeks in case you need to check anything.
  7. Email students a short note on what changed and how to log in, and watch support requests closely for the first week.

Frequently asked questions

Will students lose their progress?

Not if you migrate it. Lesson and course completions can be recreated in LifterLMS. Detailed quiz attempt histories are usually not migrated, so keep an export of them.

Do students need new passwords?

No. Both plugins use standard WordPress user accounts, so logins are unchanged.

Can I run LearnDash and LifterLMS side by side?

Yes, during the migration. Keep LearnDash active until the move is verified, but make sure only one plugin controls access and billing on the live site at any time.

How long does a LearnDash migration take?

A handful of simple courses can move in days. Sites with many topics, advanced quiz types, groups or active subscriptions take longer, mostly because of testing.

Next steps

Start with an inventory: courses, topics, quiz types, groups, certificates, active subscriptions and URLs. That list tells you whether a plugin can do the job or whether you need a scripted migration.

If the site has paying subscribers, groups or a large student base, our LifterLMS migration service plans and runs the move, including dry runs, redirects and subscription handling. Send us your inventory and we will tell you what a safe migration involves.

Add LifterLMS Expert to your preferred sources

Add lifterlmsexpert as a preferred source on Google, or open this article in your AI assistant to use it as a source.

  • Add as a preferred source on Google
VishavjeetChoubeyLifterLMS Expert
Free consultation

Prefer expert help over DIY?

Skip the trial and error. Get specialist LifterLMS help and ship faster.

Talk to a LifterLMS Expert Explore our services

Replies within one business day