1. Home
  2. Docs
  3. Developers
  4. Hooks and Filters

Hooks and Filters

We are currently in the process of updating all developer docs. In the interim, we have included a short list of common hooks & filters below.

Below are some actions and filters you can use to integrate LearnDash with your project. These are to be placed in your child theme’s functions.php file.


Actions in WordPress allow you to add or remove functionality that currently exists. An example would be adding a special button when your course is completed, perhaps to upsell the next course. You would use the code below as a starting point to “hook” into LearnDash’s current functionality and create your own function where “//Called when…” is displayed in each example below.

Called when course is completed

add_action("learndash_course_completed", function($data) {
//Called when course is completed
}, 5, 1);

Called when lesson is completed

add_action("learndash_lesson_completed", function($data) {
//Called when lesson is completed
}, 5, 1);

Called when topic is completed

add_action("learndash_topic_completed", function($data) {
//Called when topic is completed
}, 5, 1);

Called when quiz is completed

add_action("learndash_quiz_completed", function($data) {
//Called when quiz is completed
}, 5, 1);

Called when someone resets options to default

add_action( 'sfwd_options_reset', function() {
//Called when someone Resets Options to Default
) );

Redirection Filters

Filters in WordPress allow you to replace specific data that is found in an existing Action. An example would be to change the page that a user is taken to immediately after a course is completed. You can use the code below as a starting point to “hook” into an Action and change (or “filter”) LearnDash’s default behavior.

For course completion redirection:

add_filter("learndash_course_completion_url", function($link, $course_id) {
//You can change the link here
return $link;
}, 5, 2);

For all completion related redirections: i.e. when Mark Complete, or Click Here to Continue buttons are clicked:

add_filter("learndash_completion_redirect", function($link, $post_id) {
//You can change the link here
//$post_id is ID of the lesson/quiz from where the user is being redirected from. $link is the link to which the user is redirected from.
return $link;
}, 5, 2);

When a non-logged in user clicks the Take This Course button (free courses):

add_filter("learndash_course_join_redirect", function($link, $course_id) {
//You can change the link here. $link is the login link here.
return $link;
}, 5, 2);

When a non-logged in user clicks the Take This Course button (paid courses):

add_filter('learndash_payment_button', function($button, $params) {
//You can change the button html here.
return $button;

When a logged in user clicks the Take This Course button (paid courses):

add_filter("learndash_course_join_redirect", 'learndash_course_join_redirect_fn', 5, 2);
function learndash_course_join_redirect_fn($link, $course_id) {
$user_id = get_current_user_id();
// You can set the link below
$link = "http://google.com/";
return $link;

When a non-logged in user clicks on the course content table located on the course page:

add_filter("learndash_access_redirect", function($link, $post_id) {
//Modify the $link here
return $link;
}, 10, 2);

Other Common Filters

Show course progression next step link

* LearnDash Show Course Progression Next Step Link
* By default LearnDash will hide the next link on Lessons/Topics until they
* are completed by the user. Using this filter you can override this default
* logic.
* @since 2.3
* @param bool $show_next_link true if the next link for lesson/topic is to be shown or false is not.
* @param int $user_id This is the ID of the logged in user to check.
* @param int $post_id This is the ID of the post object to check. This may relate to a course, lesson, topic, quiz
* @return bool true to show the next link, false to not show next link
add_filter('learndash_show_next_link', 'learndash_show_next_link_proc', 10, 3);
function learndash_show_next_link_proc( $show_next_link = false, $user_id = 0, $post_id = 0 ) {

// Example 1) Check if user is admin or group_leader 
if ( ( user_can( $user_id, 'administrator' ) ) || ( user_can( $user_id, 'group_leader' ) ) ) 
$show_next_link = true;

// Example 2) Check post type 
//$post_type = get_post_type( $post_id ); 
//if ( $post_type == 'sfwd-lessons') 
// $show_next_link = true; 
return $show_next_link; 

Modify the link where a user is directed to after a course is completed

add_filter("learndash_course_completion_url", function($link, $course_id) {
if ( $course_id == 123 ) {
$link = "https://www.EXAMPLE.com";
return $link;
}, 5, 2);

Modify the custom post type options $post_options for the $post_type

add_filter( 'sfwd_cpt_options', function($post_options, $post_type) {
//$post_type is "sfwd-courses", "sfwd-lessons", "sfwd-quiz" or "sfwd-certificates"
} , 5, 2 );

Modify array arguments generating the courses, lessons, quiz and certificate options page

add_filter("learndash_post_args", function($post_args) {
}, 5, 1 );

Modify the PayPal button

add_filter('learndash_payment_button', function($paypal_button, $payment_params) {
}, 5, 2 );

Modify the restriction message if user doesn’t have access to current page content

add_filter("learndash_content_access", function($restriction_message, $post) {
//Return null if not restricted. Return the restriction message to show if the current user doesn't have access to see the current page content.
}, 5, 2);

Modify the content of courses, lessons or quizzes

add_filter("learndash_content", function($content, $post) {
}, 5, 2);

Modify the previous post link

add_filter('learndash_previous_post_link', function($link) {
}, 5, 1);

Modify the continue link shown after quiz completion

add_filter('learndash_quiz_continue_link', function($returnLink, $url) {
}, 5, 2);

Modify the available on message text for the drip feeding lessons

add_filter("leardash_lesson_available_from_text", function($content, $post, $lesson_access_from) {
}, 5, 3);

For changing slugs of custom post types

add_filter("learndash_post_args", function($post_args) {
foreach ($post_args as $key => $post_arg) {
if($post_arg["post_type"] == "custom-post-type") {
$post_args[$key]["slug_name"] = "new-slug";
return $post_args;
}, 10, 1);

To enroll user to course

ld_update_course_access($user_id, $course_id, $remove = false);

To unenroll user from course

ld_update_course_access($user_id, $course_id, $remove = true);

To mark lesson or topic complete

learndash_process_mark_complete($user_id, $post_id);

LearnDash filter display user quiz statistics

For more info on this filter, see: show_user_profile_quiz_statistics.php

// @return $show_stats Should be true to display the link or false to not display. add_filter('show_user_profile_quiz_statistics', 'show_user_profile_quiz_statistics_proc', 10, 4);
function show_user_profile_quiz_statistics_proc( $show_stats, $user_id, $quiz_attempt, $context = '' ) {

// Example of checking context match on some custom template
if ( 'test.php' == $context )
$show_stats = true;
$show_stats = false;
return $show_stats;

Show quiz continue button on student fail

* LearnDash override Quiz Continue button on Student fail.
* By default the Quiz continue button is not displayed if the student fails. This filter
* will let you override this logic.
* @since
* @param bool $show_button value will be false to not show the continue button.
* @param int $quiz_id The current quiz displayed to student.
* @return bool true to show button, false to not show button
add_filter( 'show_quiz_continue_buttom_on_fail', 'show_quiz_continue_buttom_on_fail_proc', 10, 2 );
function show_quiz_continue_buttom_on_fail_proc( $show_button = false, $quiz_id = 0 ) {

// Example to show the continue button only on quiz 232
if ( $quiz_id == 232 )
$show_button = true;

return $show_button;

Allow LearnDash custom post types to be shown in search results

* LearnDash Filter Post Args - Enable post types in search
* This can affect any of the CPT used by LearnDash: Course, Lesson, Topic, Quiz etc.
* @args $post_args array a large array of the CPT details as well as many details specific to LearnDash
* The $post_args is an array or array items. The array item key is the post type
* 'sfwd-courses' - Courses
* 'sfwd-lessons' - Lessons
* 'sfwd-topic' - Topics
* 'sfwd-quiz' - Quizzes
* @return $post_args The modified post args array
add_filter( 'learndash_post_args', function( $post_args = array() ) {
// Example 1
// As of LD v2.3 this all custom post types were excluded from search
// We want to include Courses and Lesson in the WP search results.
if ( isset( $post_args['sfwd-courses']['cpt_options']['exclude_from_search'] ) )
$post_args['sfwd-courses']['cpt_options']['exclude_from_search'] = false;

if ( isset( $post_args['sfwd-lessons']['cpt_options']['exclude_from_search'] ) )
$post_args['sfwd-lessons']['cpt_options']['exclude_from_search'] = false;

// always return the $post_args array
return $post_args;
}, 10, 1 );

Redirect to a lesson quiz after completing last lesson topic

* This snippet hooks into the 'learndash_completion_redirect' to allow override of the redirect link
add_filter( 'learndash_completion_redirect', function( $link, $post_id ) { 

	// We only want to do this for Topics. But the below code can be adapted to work for Lessons
	if ( get_post_type( $post_id ) == 'sfwd-topic' ) {
		// First we get the topic progress. This will return all the sibling topics. 
		// More important it will show the next item 
		$progress = learndash_get_course_progress( null, $post_id );

		// Normally when the user completed topic #3 of #5 the 'next' element will point to the #4 topic. 
		// But when the student reaches the end of the topic chain it will be empty. 
		if ( !empty( $progress ) && ( isset( $progress['next'] ) ) && ( empty( $progress['next'] ) ) ) {

			// So this is where we now want to get the parent lesson_id and determine if it has a quiz
			$lesson_id = learndash_get_setting( $post_id, 'lesson' );
			if ( !empty( $lesson_id ) ) {
				$lesson_quizzes = learndash_get_lesson_quiz_list( $lesson_id );
				if ( !empty( $lesson_quizzes ) ) {

					// If we have some lesson quizzes we loop through these to find the first one not completed by the user. 
					// This should be the first one but we don't want to assume. 
					foreach( $lesson_quizzes as $lesson_quiz ) {
						if ( $lesson_quiz['status'] == 'notcompleted' ) {
							// Once we find a non-completed quiz we set the $link to the quiz 
							// permalink then break out of out loop
							$link = $lesson_quiz['permalink'];
	// Always return $link
	return $link;
}, 20, 2);

Was this article helpful to you?

How can we help?