Hooks and Filters
This page documents the most important action hooks and filters provided by Dashboard for LearnDash for custom development.
Action Hooks
ld_dashboard_before_dashboard
Fires immediately before the dashboard wrapper <div> is rendered. Use it to inject content or markup above the entire dashboard.
add_action( 'ld_dashboard_before_dashboard', function( $user_id ) {
echo '<div class="my-banner">Welcome back!</div>';
} );
Parameters: $user_id (int) — ID of the user viewing the dashboard.
ld_dashboard_after_dashboard
Fires immediately after the dashboard wrapper closes. Use it to inject content or scripts below the dashboard.
add_action( 'ld_dashboard_after_dashboard', function( $user_id ) {
echo '<script>console.log("Dashboard loaded for user ' . $user_id . '")</script>';
} );
Parameters: $user_id (int)
Filter Hooks
ld_dashboard_prepare_acf_fields
Filters the array of ACF fields before they are rendered in a front-end edit form. Use this to show or hide specific fields based on user role, post ID, or any condition.
add_filter( 'ld_dashboard_prepare_acf_fields', function( $fields, $post_id, $user_id ) {
// Hide a field from non-admins
if ( ! current_user_can( 'manage_options' ) ) {
unset( $fields['field_ldd_course_internal_notes_1'] );
}
return $fields;
}, 10, 3 );
Parameters:
$fields (array) — associative array of field key → field config
$post_id (int) — ID of the post being edited
$user_id (int) — ID of the current user
Returns: array of fields to render.
ld_dashboard_tabs
Filters the array of registered tabs before the sidebar is rendered. Use it to add, remove, or reorder tabs programmatically.
add_filter( 'ld_dashboard_tabs', function( $tabs ) {
// Remove the messages tab for all users
unset( $tabs['messages'] );
return $tabs;
} );
Parameters: $tabs (array) — associative array of tab slug → tab object.
Returns: array
ld_dashboard_modules
Filters the array of registered modules. Use it to add a custom module or disable an existing one.
add_filter( 'ld_dashboard_modules', function( $modules ) {
// Register a custom module
$modules['my-module'] = new My_Custom_Module();
return $modules;
} );
Parameters: $modules (array) — associative array of module ID → module object.
Returns: array
JavaScript
Localized JS Objects
Two JS objects are available globally after the dashboard scripts load:
ld_dashboard_public_js (legacy, frontend):
ld_dashboard_public_js.ajax_url // WordPress AJAX URL
ld_dashboard_public_js.nonce // Frontend nonce for AJAX requests
ld_dashboard_js_object (modular scripts, frontend):
ld_dashboard_js_object.ajax_url
ld_dashboard_js_object.ajax_nonce // = wp_create_nonce('ajax-nonce')
Admin scripts:
ld_dashboard_obj.ajax_nonce // Admin nonce
ld_dashboard_obj.ajax_url
Using the Nonce in Custom AJAX
When making custom AJAX calls to plugin handlers, include the correct nonce:
jQuery.post( ld_dashboard_js_object.ajax_url, {
action: 'my_custom_action',
nonce: ld_dashboard_js_object.ajax_nonce,
data: myData
} );
On the PHP side, verify with:
check_ajax_referer( 'ajax-nonce', 'nonce' );
AJAX Best Practice
All admin-side AJAX handlers should wrap output with ob_start() / ob_end_clean() before calling wp_send_json() to prevent PHP warnings from corrupting the JSON response:
add_action( 'wp_ajax_my_custom_action', function() {
check_ajax_referer( 'ajax-nonce', 'nonce' );
ob_start();
// ... your logic ...
ob_end_clean();
wp_send_json_success( $data );
} );
Profile Hooks
ld_dashboard_user_profile_fields
Filters the array of fields rendered in the front-end profile edit form. Use it to add, remove, or reorder profile fields.
add_filter( 'ld_dashboard_user_profile_fields', function( $fields ) {
$fields['linkedin_url'] = [
'title' => 'LinkedIn URL',
'tag' => 'input',
'type' => 'url',
'name' => 'linkedin_url',
'value' => get_user_meta( get_current_user_id(), 'linkedin_url', true ),
'section' => 'contact',
];
return $fields;
} );
Parameters: $fields (array) — associative array of field key → field config.
Returns: array
ld_dashboard_save_user_profile_fields
Fires after the profile form is submitted and validated. Use it to save custom field values.
add_action( 'ld_dashboard_save_user_profile_fields', function( $user_id, $data ) {
if ( isset( $data['linkedin_url'] ) ) {
update_user_meta( $user_id, 'linkedin_url', sanitize_url( $data['linkedin_url'] ) );
}
}, 10, 2 );
Parameters:
$user_id (int) — ID of the user whose profile is being saved
$data (array) — raw POST data from the form submission
ld_dashboard_before_profile_setting_form
Fires immediately before the <form> tag in the profile edit template.
add_action( 'ld_dashboard_before_profile_setting_form', function( $user_id ) {
echo '<div class="my-profile-banner">Update your profile below.</div>';
} );
ld_dashboard_before_profile_setting_fields
Fires after the <form> tag opens, before the first field group.
ld_dashboard_after_profile_setting_fields
Fires after the last field group, before the submit button.
ld_dashboard_after_profile_setting_form
Fires immediately after the </form> tag closes.
Email Hooks
ld_dashboard_email_subject
Filters the email subject line before the email is sent.
add_filter( 'ld_dashboard_email_subject', function( $subject, $template, $data ) {
if ( $template === 'course_completion' ) {
$subject = '🎉 ' . $subject;
}
return $subject;
}, 10, 3 );
Parameters:
$subject (string) — the subject line
$template (string) — template ID (e.g., course_completion, new_message, new_announcement)
$data (array) — merge tag data for this email
ld_dashboard_email_body
Filters the email body HTML before the email is sent.
add_filter( 'ld_dashboard_email_body', function( $body, $template, $data ) {
return $body . '<p style="color:#999;">Sent by Your Academy</p>';
}, 10, 3 );
ld_dashboard_email_recipients
Filters the array of recipient email addresses before the email is sent.
add_filter( 'ld_dashboard_email_recipients', function( $recipients, $template, $data ) {
if ( $template === 'course_completion' ) {
$recipients[] = 'completions@yoursite.com';
}
return $recipients;
}, 10, 3 );
ld_dashboard_email_templates
Filters the registered email template definitions. Use it to add a new template or modify an existing one.
add_filter( 'ld_dashboard_email_templates', function( $templates ) {
$templates['my_custom_event'] = [
'label' => 'Custom Event Notification',
'subject' => 'Something happened in {course_name}',
'body' => '<p>Hi {student_name},</p><p>A custom event occurred.</p>',
];
return $templates;
} );
ld_dashboard_before_send_email
Fires immediately before wp_mail() is called.
add_action( 'ld_dashboard_before_send_email', function( $template, $recipient, $data ) {
// Log outgoing email
error_log( "LDD: sending $template to $recipient" );
}, 10, 3 );
ld_dashboard_after_send_email
Fires immediately after wp_mail() returns.
add_action( 'ld_dashboard_after_send_email', function( $template, $recipient, $result ) {
if ( ! $result ) {
error_log( "LDD: email $template to $recipient failed" );
}
}, 10, 3 );
Email From Address
// Override the From address for all dashboard notification emails
add_filter( 'ld_dashboard_email_from', function( $from ) {
return 'courses@yoursite.com';
} );
add_filter( 'ld_dashboard_email_from_name', function( $name ) {
return 'Your Course Platform';
} );