Skip to content
Learnomy
Get Learnomy Pro

Hooks Reference

Every action and filter Learnomy fires, grouped by the part of the plugin that fires it. Use it to find the hook for a job; the feature pages explain the common ones in context.

599 hooks: 374 filters and 225 actions. This page is generated from the code by bin/gen-hooks-reference.php; do not edit it by hand.

Arguments are shown as the call passes them, after the hook name. For a filter the first argument is the value you return. "Fired in" is the first place the hook is called; a number in brackets means it is called from that many places.

Adapters#

Hook Type Arguments What it is for Fired in
learnomy_checkout_purchase_types filter array() The checkout purchase types that extensions register, keyed by type. includes/adapters/class-purchase-types.php:61
learnomy_default_gateway_order filter array( 'woocommerce', 'stripe', 'paypal', 'test' ) Preference order for surfaces that show one Pay button rather than a. includes/adapters/class-adapter-registry.php:98
learnomy_membership_invoice_paid action (int) $sub->id, $provider_sub_id Fires after a renewal invoice for a Stripe membership subscription has been recorded. includes/adapters/class-stripe-adapter.php:1852
learnomy_natively_provisioned_purchase_types filter array_merge( \Learnomy\Models\Transaction::course_sale_types(), array( 'membership', 'm... Filter the purchase types adapters provision themselves. includes/adapters/class-adapter-registry.php:564
learnomy_payment_failed action (string) ( $event->data->object->id ?? '' ), 'stripe', 'async_payment_failed' Fires when a Stripe Checkout session completes without payment being collected, so no. includes/adapters/class-stripe-adapter.php:1131 (2)
learnomy_paypal_manage_url filter 'https://www.paypal.com/myaccount/autopay/', $sub The URL where a PayPal subscriber manages their subscription. includes/adapters/class-pay-pal-adapter.php:206
learnomy_paypal_subscription_updated action (int) $sub->id, $resource->status ?? '', $resource Fires when PayPal reports a subscription update that Free does not act on, such as a plan. includes/adapters/class-pay-pal-adapter.php:1554
learnomy_purchase_billing_interval filter $raw, $type, $item_id Schedule for a purchase type this adapter does not know natively. includes/adapters/class-woo-commerce-adapter.php:2157
learnomy_register_payment_adapters action Fires after the built-in gateways are registered. includes/adapters/class-adapter-registry.php:526
learnomy_stripe_invoice_orphan action $provider_sub_id, $invoice Fires when a paid Stripe invoice arrives for a subscription Learnomy has no record of. includes/adapters/class-stripe-adapter.php:1751 (2)
learnomy_stripe_subscription_updated action $subscription, $membership Stripe customer.subscription.updated event. Fires for every. includes/adapters/class-stripe-adapter.php:2185
learnomy_stripe_webhook_event action (string) $event->type, $event Fires for every verified Stripe webhook event, after the core. includes/adapters/class-stripe-adapter.php:1201
learnomy_subscription_ action . $hook . '_raw', (string) $wc_sub->get_id(), $payload, 'woocommerce' Fires for a WooCommerce subscription lifecycle event. The dynamic portion of the hook name,. includes/adapters/class-woo-commerce-adapter.php:1692
learnomy_subscription_cancelled_raw action $provider_sub_id, $resource, 'paypal' Generic cancellation - see the note in handle_subscription_renewed(). includes/adapters/class-pay-pal-adapter.php:1369 (2)
learnomy_subscription_payment_failed_raw action $provider_sub_id, $resource, 'paypal', $event_ts Generic payment failure - see the note in handle_subscription_renewed(). includes/adapters/class-pay-pal-adapter.php:1399 (2)
learnomy_subscription_renewed_raw action $provider_sub_id, $sale, 'paypal' Generic subscription lifecycle event, fired for EVERY recurring. includes/adapters/class-pay-pal-adapter.php:1450 (2)

Admin#

Hook Type Arguments What it is for Fired in
learnomy_admin_commerce_menu_icon filter 'dashicons-cart' The icon of the Commerce top-level admin menu. includes/admin/class-admin.php:466
learnomy_admin_commerce_menu_items action Fires after Learnomy's own Commerce submenus are registered, so extensions can add theirs. includes/admin/class-admin.php:549
learnomy_admin_commerce_menu_label filter __( 'LMS Commerce', 'learnomy' ) The label of the Commerce top-level admin menu. includes/admin/class-admin.php:460
learnomy_admin_course_detail_actions action (int) $course->id Pro extension point for per-course actions in the overview header. includes/admin/views/course-detail.php:100
learnomy_admin_course_detail_panels action (int) $course->id Fires at the bottom of the admin course detail screen, so extensions can add panels. includes/admin/views/course-detail.php:594
learnomy_admin_dashboard_after_stats action $stats Fires below the stat cards on the admin dashboard. Only fired for site owners, not. includes/admin/views/dashboard.php:147
learnomy_admin_filter_options_cap filter 200 includes/admin/class-admin.php:3276 (9)
learnomy_admin_hidden_submenu_targets filter $targets Allow Pro / third-party code to hide additional submenu pages. includes/admin/class-admin.php:1502
learnomy_admin_init action $this Fires at the end of the admin controller's init, after Learnomy's own admin hooks are. includes/admin/class-admin.php:112
learnomy_admin_instructor_detail_actions action (int) $instructor_id Pro extension point for per-instructor actions, rendered in the. includes/admin/views/instructor-detail.php:115
learnomy_admin_menu_icon filter \Learnomy\logo_menu_icon() The icon of the top-level Learnomy admin menu. includes/admin/class-admin.php:129
learnomy_admin_menu_items action Fires after Learnomy's own admin submenus are registered, so extensions can add theirs. includes/admin/class-admin.php:381
learnomy_admin_menu_label filter __( 'Learnomy', 'learnomy' ) The label of the top-level Learnomy admin menu. includes/admin/class-admin.php:123
learnomy_admin_menu_section_map filter $groups, $parent Filter the slug -> section-key map for a menu. $parent says which menu. includes/admin/class-admin.php:1283
learnomy_admin_menu_sections filter $group_order, $parent Filter the ordered section-key -> label list for a menu. Controls both. includes/admin/class-admin.php:1292
learnomy_admin_pro_features_after_categories action Fires after the feature categories on the Pro Features admin page. includes/admin/views/pro-features.php:307
learnomy_admin_pro_features_before_categories action Fires before the catalog grid on the Pro Features page. includes/admin/views/pro-features.php:160
learnomy_admin_settings_menu_icon filter 'dashicons-admin-settings' The icon of the Settings top-level admin menu. includes/admin/class-admin.php:580
learnomy_admin_settings_menu_items action Pro / third-party config pages can register under the Settings menu. includes/admin/class-admin.php:715
learnomy_admin_settings_menu_label filter __( 'Learnomy Settings', 'learnomy' ) The label of the Settings top-level admin menu. includes/admin/class-admin.php:574
learnomy_admin_settings_nav action Fires after the built-in navigation items of the Settings screen, so extensions can add nav. includes/admin/views/settings.php:395
learnomy_admin_settings_nav_groups filter $nav_groups Register a settings tab into one of the groups above. includes/admin/views/settings.php:195
learnomy_admin_settings_sections action Fires after the built-in Settings sections, so extensions can render additional sections. includes/admin/views/settings.php:3215
learnomy_admin_status_labels filter $labels Filter the admin status slug → translated label map. includes/admin/class-ux.php:159
learnomy_admin_status_variants filter $map Filter the admin status → badge-variant map. includes/admin/class-ux.php:93
learnomy_admin_student_detail_actions action (int) $user->ID Pro extension point for per-student actions (e.g. "Add to Space". includes/admin/views/student-detail.php:76
learnomy_admin_subscription_detail_actions action $sub_id Pro extension point for per-subscription actions in the header. includes/admin/views/subscription-detail.php:73
learnomy_admin_subscription_detail_panels action $sub_id, (int) ( $subscription->user_id ?? 0 ) Pro extension point for extra CONTENT panels below the payments table. includes/admin/views/subscription-detail.php:334
learnomy_admin_transaction_detail_actions action $txn_id Pro extension point for per-transaction actions in the header. includes/admin/views/transaction-detail.php:76
learnomy_certificate_instructor_choice_limit filter 500 The maximum number of instructors listed in the certificate rule's Specific instructors. includes/admin/class-admin.php:5049
learnomy_commerce_card_descriptions filter array( 'learnomy-memberships' => __( 'Plans, pricing, and access tiers.', 'learnomy' ),... The one-line descriptions shown on the Commerce overview cards. includes/admin/views/commerce-overview.php:47
learnomy_commerce_card_icons filter array( 'learnomy-memberships' => 'badge-check', 'learnomy-subscriptions' => 'repeat', '... The Lucide icon for each Commerce overview card. includes/admin/views/commerce-overview.php:29
learnomy_course_editor_fields action $course ?? null Renders extra course-editor fields in the sidebar so integrations. includes/admin/views/course-form.php:626
learnomy_course_form_show_pricing filter $kernel->is_enabled( 'payments' ) || $kernel->is_enabled( 'membership' ), $course ?? null Whether the course editor shows the pricing panel. includes/admin/views/course-form.php:257
learnomy_demo_seed_pro action $manifest['course_ids'] ?? array() Fires during demo seeding so Pro extensions can seed their own demo fixtures. includes/admin/ajax/class-demo-seeder.php:222
learnomy_demo_seeder_cascade_cleanup action $user_ids, $course_ids Fires after the core cascade sweep so add-ons can purge their own. includes/admin/ajax/class-demo-seeder.php:638
learnomy_editorjs_tools filter array() Open extension seam - it is the owner's site, so we never gate what an. includes/admin/class-admin.php:6250
learnomy_email_merge_tags filter $lrn_email_tags, (string) $type_key includes/admin/views/settings.php:2575
learnomy_force_commerce_menu filter false Allow Pro / third-party code to force the Commerce menu visible. includes/admin/class-admin.php:444 (2)
learnomy_grading_row_actions filter $lrn_grade_row_actions, $lrn_row includes/admin/views/quiz-grading.php:237
learnomy_integrations_cards action includes/admin/views/settings.php:3201
learnomy_is_pro filter defined( 'LEARNOMY_PRO_VERSION' ) Whether Learnomy Pro counts as active on the Earnings screen, which gates its Pro-only. includes/admin/views/earnings.php:241 (4)
learnomy_keep_admin_notice filter $keep, $callback, $hook Keep a notice callback on Learnomy screens. includes/admin/class-notice-scope.php:99
learnomy_learning_standards filter array( 'xapi' => array( 'name' => __( 'xAPI', 'learnomy' ), 'icon' => 'activity', 'summ... The canonical learning-standards catalogue. Each entry is one standard the. includes/admin/views/partials/integrations-hub.php:31
learnomy_lesson_content_editor action $current_content_type, $is_edit && $lesson ? (int) $lesson->id : 0 Render seam for a Pro-registered content-type's editor panel. includes/admin/views/lesson-editor.php:571
learnomy_lesson_editor_fields action $is_edit && $lesson ? $lesson : null Renders extra lesson-editor fields (and sub-lesson, same editor) so. includes/admin/views/lesson-editor.php:731
learnomy_lesson_editor_routes filter array( 'course-editor' ) Front-end routes that host a client-rendered lesson editor. includes/admin/class-lesson-attachments-panel.php:123
learnomy_lesson_has_release_schedule filter false, (int) $lesson->id Does this lesson also carry a Pro release schedule?. includes/admin/views/lesson-editor.php:817
learnomy_lesson_release_settings action $is_edit && $lesson ? (int) $lesson->id : 0 Release / drip scheduling panel injection point. includes/admin/views/lesson-editor.php:893
learnomy_membership_plan_after_form action $lrn_plan_id ?? 0 Render extra panels below the membership-plan editor form (e.g. an. includes/admin/views/membership-edit.php:530
learnomy_membership_plan_space_options filter array() Space scope. Free owns this column and Pro decides what can go in it,. includes/admin/views/membership-edit.php:450
learnomy_module_gate_enabled filter $enabled, $gate_key Final say on whether a gated admin page's owner is active. includes/admin/class-admin.php:864
learnomy_module_gate_label filter $module_label, $module Plain-English name for the thing that gates the page. Free resolves. includes/admin/class-admin.php:1026
learnomy_module_gated_admin_slugs filter $map Admin pages that disappear when their gating module is switched off. includes/admin/class-admin.php:842
learnomy_module_gated_page_labels filter $slug_labels Plain-English names for gated pages, so the recovery notice says what. includes/admin/class-admin.php:1015
learnomy_nav_menu_pages filter $pages Filter the list of Learnomy pages exposed in the nav-menus metabox. includes/admin/class-nav-menu-metabox.php:151
learnomy_notice_resurface_days filter $days, $key Filter the re-surface window for one notice. includes/admin/class-notice-dismissal.php:179
learnomy_onboarding_steps filter $steps The steps of the onboarding checklist. includes/admin/class-onboarding-state.php:178
learnomy_pro_course_builder_ai_slot action (int) $course->id AI authoring slot - the Pro ai-authoring extension renders its. includes/admin/views/course-builder.php:48
learnomy_pro_course_create_ai_slot action Fires on the new-course admin screen, where Pro renders its AI course creation entry point. includes/admin/views/course-form.php:103
learnomy_pro_docs_slugs filter self::DOCS_SLUGS Filter the catalog-slug => docs-slug map, so a site (or a future. includes/admin/class-pro-links.php:137
learnomy_pro_link_utm filter $args, $url, $campaign, $content Filter the tracking parameters added to a Learnomy marketing link. includes/admin/class-pro-links.php:97
learnomy_pro_quiz_editor_ai_slot action (int) $quiz->id, (string) ( $quiz->title ?? '' ) AI authoring slot - the Pro ai-authoring extension renders its. includes/admin/views/quiz-editor.php:222
learnomy_pro_tools_card_groups filter array( 'teaching' => __( 'Teaching', 'learnomy' ), 'progress' => __( 'Skills & progress... Section headings for the hub, in render order. includes/admin/views/pro-tools-hub.php:70
learnomy_pro_tools_cards filter array() The cards on the Pro Tools hub. Used here to work out which extension pages belong under the. includes/admin/class-admin.php:1642 (2)
learnomy_quiz_editor_advanced_panel action (int) $quiz->id Pro seam - advanced authoring for a saved quiz. includes/admin/views/quiz-editor.php:907
learnomy_quiz_editor_fields action $quiz ?? null Renders extra quiz-editor fields so an integration can add its own. includes/admin/views/quiz-editor.php:918
learnomy_quiz_grading_response_controls action $lrn_row['response'], $attempt, $lrn_row['question'] Fires after the manual grading controls of a response on the quiz grading detail screen. The. includes/admin/views/quiz-grading-detail.php:234 (2)
learnomy_sanitize_settings filter $clean, $raw The sanitized Learnomy settings, filtered before they are saved. includes/admin/class-admin.php:2510
learnomy_settings_pages_registry filter $frontend_pages Allow Pro extensions to register additional public pages in the Pages. includes/admin/views/settings.php:333
learnomy_settings_schema filter $schema Filter the settings schema. includes/admin/class-admin.php:2044
learnomy_unknown_instructor_label filter get_bloginfo( 'name' ), $course The label shown in the admin courses list for a course whose instructor no longer exists. includes/admin/views/courses.php:392
learnomy_warn_on_empty_publish filter true, $course_id Filter whether to warn about publishing an empty course. includes/admin/class-empty-curriculum-notice.php:69
learnomy_webhook_row_actions action $hook Fires after the row actions of a webhook in the admin webhooks list, so extensions can echo. includes/admin/views/webhooks.php:512
learnomy_webhook_row_actions_list filter $row_actions, $hook Filter the row actions for a webhook list row. includes/admin/views/webhooks.php:502

Api#

Hook Type Arguments What it is for Fired in
learnomy_account_fields_save action $user_id, $request Persist custom account fields captured at REGISTRATION. Same action the. includes/api/class-auth-controller.php:992 (3)
learnomy_account_fields_validate filter true, $request, 'instructor' === $role ? 'registration_instructor' : 'registration_stud... Reject a registration or account save before anything is written. includes/api/class-auth-controller.php:898 (3)
learnomy_admin_reset_course_progress action $user_id, $course_id Fires after an admin resets a student's progress, quiz attempts and enrollment summary for a. includes/api/class-admin-controller.php:1611
learnomy_api_controllers filter $classes The REST controllers Learnomy registers, so an extension can add, replace or remove one. includes/api/class-api.php:400
learnomy_app_config_branding filter $defaults Filter the app branding block. The Pro white-label extension maps. includes/api/class-app-config-controller.php:235
learnomy_app_config_features filter $features Filter the app feature flags. Learnomy Pro injects one flag per. includes/api/class-app-config-controller.php:302
learnomy_app_config_legal filter $legal Filter the app legal block (per-site URLs, owner-configurable). includes/api/class-app-config-controller.php:330
learnomy_app_enabled filter false Filter whether the mobile app may connect to this site. includes/api/class-app-config-controller.php:178
learnomy_app_min_version filter '1.0.0' Filter the minimum app version this site supports. The app. includes/api/class-app-config-controller.php:84
learnomy_before_student_self_delete action $user_id, $user->user_email Fires immediately before the WordPress user row is removed during. includes/api/class-auth-controller.php:1435
learnomy_broadcast_max_audience filter 10000 Hard ceiling for a broadcast audience. Requests that resolve more. includes/api/class-broadcasts-controller.php:529 (2)
learnomy_broadcast_send_email filter true, $audience, $actor_id Filter whether this broadcast may also go out by email. includes/api/class-broadcasts-controller.php:449
learnomy_bulk_enroll_max filter 500 The maximum number of email addresses one bulk enrollment request processes. Extra addresses. includes/api/class-admin-controller.php:1839
learnomy_cancel_reasons filter $default The reasons a member can pick when cancelling a subscription. includes/api/class-membership-controller.php:902
learnomy_cancel_retention_offers filter array(), $sub, $user_id The retention offers shown to a member before they cancel a subscription. includes/api/class-membership-controller.php:855
learnomy_cancellable_subscription_statuses filter array( 'active', 'past_due', 'trialing', 'paused' ), $sub The subscription statuses a member may cancel from. includes/api/class-membership-controller.php:772
learnomy_checkout_extra filter $lrn_extra, $lrn_purchase_type, $request Metadata to carry with an extension purchase. includes/api/class-checkout-controller.php:985
learnomy_checkout_thank_you_url filter $url, $gateway_id, $context Filters the buyer's post-purchase return URL. includes/api/class-checkout-controller.php:1435
learnomy_course_rest_args filter $args The argument schema of the course create and update REST routes. includes/api/class-courses-controller.php:2573
learnomy_course_rest_fields filter $data, $request The fields of a course in a REST response. includes/api/class-courses-controller.php:2232
learnomy_course_reviews_per_page filter 10, $course_id The number of reviews one page of a course's review list returns. Clamped to 1-50. includes/api/class-reviews-controller.php:304 (2)
learnomy_course_saved action $course_id, $request Fires after a course is created or updated via REST, carrying the. includes/api/class-courses-controller.php:708 (2)
learnomy_course_settings_rest filter $out, $raw The course settings accepted from a REST request. Lets extensions accept extra keys they. includes/api/class-courses-controller.php:2391
learnomy_course_students_rest_items filter $items, $course_id, get_current_user_id() Filter the REST course-students rows before the response. Lets an. includes/api/class-enrollments-controller.php:747
learnomy_email_log_resent action $id, $user_id, $sent, $reason Fires after an admin manually resends a logged notification email. includes/api/class-email-log-controller.php:184
learnomy_guest_account_created action $new_guest_account_id, \Learnomy\Models\Transaction::find( (int) $txn_id ) Fires after a guest checkout created a new user account and its transaction was recorded. includes/api/class-checkout-controller.php:1292 (2)
learnomy_incoming_purchase_sources filter [] Inbound purchase sources, asked in order. The generic signed-JSON source. includes/api/class-webhooks-controller.php:612
learnomy_incoming_webhook_payload filter $result, $request The normalised incoming operation, before it is carried out. includes/api/class-webhooks-controller.php:573
learnomy_lesson_attachments_reordered action $lesson_id, $ids Fires after a lesson's attachments are reordered. includes/api/class-lesson-attachments-controller.php:243
learnomy_lesson_comment_posted action $comment_id, $lesson_id, $user_id Fires after a new lesson comment is posted and is live. Comments held for moderation fire. includes/api/class-comments-controller.php:462 (2)
learnomy_lesson_comment_replied action $comment_id, $parent_id, $lesson_id, $user_id Fires after a reply to a lesson comment is posted and is live. includes/api/class-comments-controller.php:565 (2)
learnomy_lesson_created action $lesson_id, $course_id, $data Fires after a lesson is created through the REST API. includes/api/class-lessons-controller.php:1005 (2)
learnomy_lesson_editor_panels filter [], $lesson_id, $lesson Per-lesson panels for a client-rendered lesson editor. includes/api/class-lessons-controller.php:1633
learnomy_lesson_numeric_ref_types filter array( 'mediashield' ) The lesson content types whose video field stores a numeric reference ID rather than a URL. includes/api/class-lessons-controller.php:1973
learnomy_lesson_resources action $lesson_id, $items Fire once per list fetch so later surfaces (student Resources section,. includes/api/class-lesson-attachments-controller.php:143
learnomy_lesson_saved action $lesson_id, $request Documented in create_lesson_in_section(). includes/api/class-lessons-controller.php:1007 (3)
learnomy_lesson_updated action (int) $lesson->id, $data Fires after a lesson is updated through the REST API. includes/api/class-lessons-controller.php:1124
learnomy_lesson_video_progress action $user_id, (int) $lesson->id, $watch_pct includes/api/class-lessons-controller.php:1698
learnomy_lessons_reassigned action $updated_ids Fires after lessons are moved between sections. includes/api/class-sections-controller.php:460
learnomy_lessons_reordered action $section_id, $order Fires after the lessons of a section are reordered. includes/api/class-lessons-controller.php:1227
learnomy_login_credential_error_codes filter array( 'empty_username', 'empty_password', 'invalid_username', 'invalid_email', 'incorr... Error codes meaning "these credentials are wrong" and nothing more. includes/api/class-auth-controller.php:531
learnomy_membership_plan_archived action $plan_id Fires after a membership plan that still has dependants is set to inactive instead of being. includes/api/class-membership-controller.php:1168
learnomy_membership_plan_deleted action $plan_id Fires after a membership plan with no dependants is hard-deleted along with its course links. includes/api/class-membership-controller.php:1184
learnomy_membership_plan_has_dependants filter $has_subs, $plan_id Does anything else still depend on this plan?. includes/api/class-membership-controller.php:1158
learnomy_membership_plan_saved action $plan_id, true Fires after a membership plan is created. includes/api/class-membership-controller.php:1089 (2)
learnomy_membership_resume_paused filter false, $subscription_id, $sub Resumes a paused subscription. Free cannot, so Pro handles it and returns the result. includes/api/class-membership-controller.php:1030 (2)
learnomy_module_route_map filter [ // questionandquiz bare, so every hyphenated child is covered // by the rule ra... Route pattern => module slug, for the modules a site owner can switch. includes/api/class-api.php:174
learnomy_module_toggled action $slug, $enabled Fires after an admin enables or disables a Learnomy module. includes/api/class-admin-controller.php:2268
learnomy_my_courses_per_page filter 40 The number of courses one page of the My Courses list returns. Clamped to 1-100 afterwards. includes/api/class-enrollments-controller.php:236 (2)
learnomy_pro_can_broadcast_to_space filter user_can( $user_id, 'manage_options' ), $space_id, $user_id Whether a user may send a broadcast to a space audience. Free has no Spaces model, so Pro. includes/api/class-broadcasts-controller.php:340
learnomy_pro_quiz_filter_marks filter $marks_by_qid, $questions, (int) $quiz->id Filter what each question on THIS paper is worth: question id => marks. includes/api/class-quizzes-controller.php:1368
learnomy_pro_quiz_filter_questions filter $questions, (int) $quiz->id, [] Filter the question objects a quiz attempt presents. Receives the. includes/api/class-quizzes-controller.php:1334
learnomy_pro_space_member_user_ids filter array(), $space_id The user IDs of a space's members, resolved by Pro when a broadcast targets a space. includes/api/class-broadcasts-controller.php:587
learnomy_pro_space_title filter __( 'Learning Space', 'learnomy' ), $space_id The display title of a space audience, shown for a broadcast sent to a space. includes/api/class-broadcasts-controller.php:594
learnomy_quiz_attempts_granted action $user_id, $quiz_id, $granted, $attempts Fires after an admin changes a student's extra-attempt balance on a quiz. includes/api/class-admin-controller.php:1674
learnomy_quiz_created action $quiz_id, $data Fires after a quiz is created through the REST API. includes/api/class-quizzes-controller.php:1013
learnomy_quiz_player_context filter $player_context, (int) $quiz->id, (int) $attempt->id Filter the quiz player context payload sent to the client on quiz start. includes/api/class-quizzes-controller.php:1699
learnomy_quiz_saved action $quiz_id, $request Fires after a quiz is created or updated via REST, carrying the request,. includes/api/class-quizzes-controller.php:1022 (2)
learnomy_quiz_slots_reordered action $quiz_id, $clean_order Fires after the question slots of a quiz are reordered. includes/api/class-quizzes-controller.php:736
learnomy_quiz_submit_grace_seconds filter 60, $attempt The grace period, in seconds, after a timed attempt's deadline before a submission is. includes/api/class-quizzes-controller.php:1889
learnomy_quiz_timer_resume_policy filter 'wall_clock', $quiz, $attempt How a timed quiz attempt's clock behaves when the student resumes it. includes/api/class-quizzes-controller.php:1592
learnomy_quiz_updated action (int) $quiz->id, $data Fires after a quiz is updated through the REST API. includes/api/class-quizzes-controller.php:1077
learnomy_registration_challenge_verify filter true, $request This filter is documented in includes/api/class-auth-controller.php. includes/api/class-checkout-controller.php:250 (2)
learnomy_report_resolved action $report_id, $status, get_current_user_id() Fires after a moderator resolves a report. includes/api/class-reports-controller.php:246
learnomy_report_submitted action $report_id, $object_type, $object_id, $user_id, $reason Fires after a member files a moderation report. includes/api/class-reports-controller.php:206
learnomy_rest_lesson_payload filter $filtered, $lesson, $request Filter the single-lesson REST payload. includes/api/class-lessons-controller.php:940
learnomy_section_created action $section_id, $course_id Fires after a course section is created through the REST API. includes/api/class-sections-controller.php:317
learnomy_section_items_reordered action $section_id, $items Fires after the mixed lessons and quizzes inside a section are reordered. includes/api/class-sections-controller.php:491
learnomy_section_updated action (int) $section->id, $data Fires after a course section is updated through the REST API. includes/api/class-sections-controller.php:378
learnomy_sections_reordered action $course_id, $order Fires after a course's sections are reordered. includes/api/class-sections-controller.php:530
learnomy_student_account_deleted action $user->user_email Fires after the student user row is successfully removed. includes/api/class-auth-controller.php:1459
learnomy_subscription_extended action $sub_id, (int) $sub->user_id, (int) $sub->plan_id Fires after an admin extends a subscription's period. includes/api/class-membership-controller.php:1524
learnomy_user_blocked action $me, $target Fires after one member blocks another. includes/api/class-blocks-controller.php:149
learnomy_user_registered action $user_id, $role Fires after a new user registers through the Learnomy frontend. includes/api/class-auth-controller.php:978
learnomy_user_unblocked action $me, $target Fires after one member unblocks another. includes/api/class-blocks-controller.php:169
learnomy_validate_plan_space_id filter is_numeric( $v ) && (int) $v >= 0, $v Whether a space ID is acceptable on a membership plan. Pro tightens this to require that the. includes/api/class-membership-controller.php:564
learnomy_withdrawal_approved action (int) $withdrawal->instructor_id, $withdrawal Fires after an admin approves an instructor withdrawal and it is marked processed. includes/api/class-admin-controller.php:971
learnomy_withdrawal_rejected action $withdrawal_id, (int) $withdrawal->instructor_id, $reason Fires after an admin rejects a withdrawal and its commissions are returned to pending. includes/api/class-admin-controller.php:1012

Auth#

Hook Type Arguments What it is for Fired in
learnomy_app_connect_bridge filter $info Filter the resolved app-connect bridge for this site. includes/auth/class-app-connect.php:155
learnomy_app_connect_schemes filter array( App_Authorize_Access::app_scheme() ) Filter the custom URL schemes the Learnomy app-connect flow may. includes/auth/class-app-connect.php:113
learnomy_app_credential_issued action $user->ID, $app_id, $app_name Fires after a member exchanges their password for an app credential. includes/auth/class-app-credentials.php:193
learnomy_app_password_login_enabled filter $on Filter whether members may exchange a WordPress password for an. includes/auth/class-app-credentials.php:89
learnomy_app_scheme filter self::DEFAULT_APP_SCHEME Filter the mobile app's deep-link scheme. includes/auth/class-app-authorize-access.php:109
learnomy_email_verified_redirect filter \Learnomy\route_url( 'student-dashboard' ), $user_id Where a user is sent after their email address is verified and they are signed in. includes/auth/class-email-verification.php:257
learnomy_generic_login_errors filter true Whether to answer every failed sign-in identically. includes/auth/class-login-flow.php:252
learnomy_login_redirect filter $destination, $user, $redirect_to Filter where a member lands after signing in. includes/auth/class-login-flow.php:158

Blocks#

Hook Type Arguments What it is for Fired in
learnomy_my_progress_max filter 20 The maximum number of in-progress courses the My Progress block lists. 0 lists them all. blocks/my-progress/render.php:66

Cli#

Hook Type Arguments What it is for Fired in
learnomy_cli_commands action Fires after built-in CLI commands are registered. includes/cli/class-cli.php:93
learnomy_repair_data_integrity_tasks filter array(), $dry_run Filters the extension-contributed data-integrity tasks. includes/cli/class-repair.php:458

Content#

Hook Type Arguments What it is for Fired in
learnomy_content_allowed_html filter $allowed, $context Filter the content allow-list (save gate + render floor). includes/content/class-content-html.php:544
learnomy_content_migratable_fields filter $fields Filter the content fields a migration converts. includes/content/class-content-migrator.php:132
learnomy_content_premigration_backup_written action $file, $rows Fires after the pre-migration content backup is written, before content is converted to. includes/content/class-content-migrator.php:294
learnomy_content_snapshot_fields filter $fields Filter the content fields that get snapshotted before a migration. includes/content/class-content-migrator.php:69
learnomy_embed_blocked_hosts filter array(), $url Filter the embed host deny-list (lowercase hosts). includes/content/class-embed.php:354
learnomy_embed_fediverse_enabled filter $enabled, $url Filter whether guarded Fediverse/oEmbed discovery runs. includes/content/class-embed.php:332
learnomy_embed_html filter $html, $url, $opts Filter the final embed HTML (after wrap + caption). includes/content/class-embed.php:81
learnomy_embed_oembed_args filter array( 'maxwidth' => 1280, 'discover' => false, ), $url Filter the args passed to wp_oembed_get for the FIRST pass (core providers). includes/content/class-embed.php:188
learnomy_embed_platform_adapters filter array( array( __CLASS__, 'peertube_adapter' ) ) Filter the federated-platform embed adapters. Each is. includes/content/class-embed.php:271
learnomy_store_content_as_html filter true Whether new lesson content is stored as HTML rather than Editor.js JSON. False opts the site. includes/content/class-content-html.php:600

Core#

Hook Type Arguments What it is for Fired in
learnomy_account_nav_items filter $items, $current Filter the account navigation items. Pro adds its account surfaces here. includes/functions.php:3963
learnomy_account_nav_section_map filter $section_by_key Filter the account-nav item -> section map, so a developer can move an. includes/functions.php:4006
learnomy_account_routes filter array( 'student-dashboard', 'account-courses', 'account-quiz-results', 'account-billing... The routes that make up the My Account area and share its vertical nav. includes/functions.php:3764
learnomy_app_user_agent_token filter 'LearnomyApp' Token the native app appends to its WebView User-Agent. White-label apps. includes/functions.php:2246
learnomy_asset_filemtime filter $on Whether Learnomy asset URLs use the file's modified time as their version, so a changed file. includes/functions.php:5248
learnomy_become_instructor_slug filter 'become-instructor' The URL slug of the instructor application page. includes/functions.php:537
learnomy_billing_slug filter account_slug() . '/billing' The URL path of the account billing page. includes/functions.php:507 (2)
learnomy_block_allowed_html filter $allowed, $name Filter the allowed-HTML set used to sanitise Learnomy block output. includes/class-blocks.php:474
learnomy_block_category_label filter __( 'Learnomy', 'learnomy' ) Label for the Learnomy block-inserter category. includes/class-blocks.php:563
learnomy_block_output filter $html, $attributes, $name The rendered markup of a Learnomy block, filtered before it is sanitised and echoed. includes/class-blocks.php:513
learnomy_breadcrumb_root filter $item Filter the shared breadcrumb root. 10k sites, more than one mind: a. includes/functions.php:2131
learnomy_cancelled_slug filter enroll_slug() . '/cancelled' The URL path of the checkout cancelled page. includes/functions.php:525
learnomy_certificate_expired action (int) $row->id, (int) $row->user_id, (int) $row->course_id Fires after the daily sweep marks a certificate as expired. includes/class-cron.php:993
learnomy_checkout_default_country filter 'US' The billing country the checkout Address Element starts with. includes/class-template-loader.php:3366
learnomy_container_width filter $container_width, $route Filters the content container width for one Learnomy page. includes/class-template-loader.php:243
learnomy_content_can_access filter $user_id > 0, $user_id Filter whether a viewer may read course content while the academy is private. includes/functions.php:746
learnomy_content_route_names filter array( 'catalog', 'category', 'course', 'lesson', 'quiz', 'standalone-quiz', 'instructo... The course content routes gated by the require-login setting. includes/functions.php:829
learnomy_countries filter $wc This filter is documented below. includes/functions.php:5428 (2)
learnomy_course_approved action $course_id Fires after a course is approved and published through the approve-course ability. includes/class-abilities.php:2639
learnomy_course_rejected action $course_id, $reason Fires after a course is rejected through the reject-course ability and set back to draft. includes/class-abilities.php:2677
learnomy_course_taxonomies filter $default The tag taxonomies offered for courses. includes/functions.php:5033
learnomy_cron_jobs filter $events The recurring cron events Learnomy schedules, so extensions can register theirs. includes/class-cron.php:181
learnomy_currency_names filter array( 'AED' => __( 'United Arab Emirates dirham', 'learnomy' ), 'AFN' => __( 'Afghan a... Filter the human names shown in a currency picker. includes/functions.php:2925
learnomy_currency_options filter $options, $args Filter the options shown in a currency picker. includes/functions.php:2907
learnomy_currency_symbol_position filter $position, $currency, $locale Filter the currency symbol position. includes/functions.php:3395
learnomy_currency_symbols filter array( 'AED' => 'د.إ', 'AFN' => '؋', 'ALL' => 'L', 'AMD' => 'AMD', 'ANG' => 'ƒ', 'A... Map of ISO 4217 currency code to display symbol. includes/functions.php:3121
learnomy_display_timezone filter wp_timezone(), $user_id > 0 ? $user_id : get_current_user_id() The timezone times are shown in. Return a member's own timezone to show. includes/functions.php:4271
learnomy_distraction_free_route filter $distraction_free, $route Whether a route renders without the theme header and footer. includes/class-template-loader.php:549
learnomy_docs_url filter 'https://learnomy.app/docs/' Filter the documentation base URL. includes/functions.php:5307
learnomy_edd_item_id filter 1662698 The EDD product id used to register the plugin for license updates. learnomy.php:107
learnomy_email_log_retention_days filter $retention_days Filter the email-log retention window in days. includes/class-cron.php:962
learnomy_enable_pwa filter false Whether the Learnomy PWA (service worker, offline banner and manifest) is enabled. This call. includes/functions.php:897 (3)
learnomy_enrollment_expired action (int) $row->id, (int) $row->user_id, (int) $row->course_id, $access->access_remains( (i... Fires after the expiry sweep ends an enrollment's term. Kept for. includes/class-cron.php:483
learnomy_entity_labels filter $defaults Filters the set of renamable nouns. includes/functions.php:1518
learnomy_erase_app_data action $user_id Fires during a member data-erase so Pro extensions can wipe their own. includes/class-privacy.php:628
learnomy_erase_authored_course action $course_id, $user_id Fires before an erased author's course is removed. includes/class-privacy.php:452
learnomy_extension_enabled filter false, $slug Filter whether a Pro extension is enabled on this site. includes/functions.php:596
learnomy_for_sale_models filter array( Models\MembershipPlan::class ) The model classes whose rows are for sale. Each has. includes/class-learnomy.php:1557
learnomy_hide_admin_bar_for_students filter true Filter whether the WP admin bar is hidden for pure students. includes/class-learnomy.php:142
learnomy_init action $this Fires after Learnomy has fully initialized all dependencies. includes/class-learnomy.php:845
learnomy_instructor_application_approved action $application_id, (int) ( $application->user_id ?? 0 ) Fires when an instructor application is approved. includes/class-abilities.php:2566 (2)
learnomy_instructor_application_rejected action $application_id, (int) ( $application->user_id ?? 0 ), $reason Fires when an instructor application is rejected. Same action and. includes/class-abilities.php:2603 (2)
learnomy_instructor_application_submitted action (int) $application_id, $user_id Fires when a student submits an instructor application. Notifier. includes/class-router.php:896 (3)
learnomy_instructor_approved action $application_id Legacy alias, kept firing. includes/class-abilities.php:2578
learnomy_instructor_course_edit_url filter $backend, $course_id The frontend URL of the course editor shown in the instructor's in-content bar. Returning. includes/class-admin-bar.php:114 (4)
learnomy_instructor_lesson_edit_url filter $backend, $course_id, $lesson_id The frontend URL of the lesson editor shown in the instructor's in-content bar. Returning. includes/class-admin-bar.php:135
learnomy_instructor_nav_items filter $items, $current includes/functions.php:4106
learnomy_instructor_profile_url filter $url, $instructor Filter the instructor profile URL used across course and lesson surfaces. includes/functions.php:2066
learnomy_instructor_quiz_edit_url filter $backend, $quiz_id, $course_id The frontend URL of the quiz editor shown in the instructor's in-content bar. Returning the. includes/class-admin-bar.php:158
learnomy_instructor_registration_enabled filter ! solo_mode() Whether visitors may apply to become instructors. includes/functions.php:610
learnomy_instructor_rejected action $application_id, $reason Legacy alias, kept firing. includes/class-abilities.php:2613
learnomy_instructor_routes filter // 'instructor-reports' is NOT here, and its absence is the point. That // route is reg... The instructor routes that use the shared teaching layout and its stylesheets. includes/functions.php:3797
learnomy_instructor_shell_routes filter array( 'instructor-dashboard', 'instructor-reports', 'instructor-courses', 'instructor-... The instructor routes that render through the shared teaching shell and so load the. includes/class-template-loader.php:1583
learnomy_is_editor_preview filter defined( 'REST_REQUEST' ) && REST_REQUEST && current_user_can( 'edit_posts' ) Filters whether a block is being drawn as an editor preview. includes/functions.php:3631
learnomy_layouts filter $surfaces Filters the layout registry. Pro / third-party code adds variants to a. includes/functions.php:1230
learnomy_lesson_html_allowed_html filter $allowed, $raw Filter the allowed-HTML set used to sanitise raw lesson bodies (legacy. includes/functions.php:4583
learnomy_lesson_require_watch_percent filter 0, $lesson, $course The video watch percentage a lesson requires before it can be marked complete, as enforced. includes/class-template-loader.php:3651 (4)
learnomy_lesson_taxonomies filter $default The tag taxonomies offered for lessons. includes/functions.php:5068
learnomy_live_session_duration filter 60, $lesson Filter the default length of a live session, in minutes. includes/functions.php:2498
learnomy_member_payment_provider_label filter $label, $slug Filter the buyer-facing name of a payment provider. includes/functions.php:3573
learnomy_membership_faq_items filter $faq Filter the membership FAQ rows. Each row: { q, a }. includes/functions.php:4216
learnomy_membership_on_offer filter module_enabled( 'membership' ) Filter whether membership sign-up CTAs may render. includes/functions.php:2292
learnomy_money_display_params filter $params, (string) $resolved Filter how money is SHOWN, never what is charged. includes/functions.php:3450
learnomy_multi_instructor_enabled filter $on Whether co-instructors and revenue sharing are offered. includes/functions.php:686
learnomy_notice_help_ids filter $ids Filter the notice ids documented on troubleshooting/admin-notices. includes/functions.php:5365
learnomy_offline_slug filter 'learnomy-offline' The URL slug of the offline page served by the PWA shell. includes/functions.php:870
learnomy_payout_method_aliases filter array( 'bank' => 'bank_transfer', 'banktransfer' => 'bank_transfer', 'bank-transfer' =>... The alternate spellings of payout methods that are normalised to a canonical method. includes/functions.php:1768
learnomy_payout_methods filter $methods Filter the payout rails. includes/functions.php:1750
learnomy_privacy_authored_batch filter self::AUTHORED_BATCH The number of rows processed per batch when erasing a user's authored content. includes/class-privacy.php:415
learnomy_privacy_authored_content_erasure filter 'delete' What happens to content the data subject authored. includes/class-privacy.php:577
learnomy_privacy_authored_time_budget filter self::AUTHORED_TIME_BUDGET Seconds one authored-content pass may run before stopping and. includes/class-privacy.php:425
learnomy_privacy_certificate_erasure filter 'delete' How a certificate is erased for a GDPR request. includes/class-privacy.php:2069
learnomy_privacy_content_reassign_to filter $default User ID that authored content is reassigned to during a GDPR erase. includes/class-privacy.php:386
learnomy_pro_active filter defined( 'LEARNOMY_PRO_VERSION' ) Whether Learnomy Pro counts as active. A test can force this to fake Pro. includes/functions.php:1895 (2)
learnomy_protected_routes filter $protected_routes includes/class-template-loader.php:310
learnomy_provider_cancel_sweep_limit filter 25 The number of provider-side subscription cancellations reconciled in one hourly run. includes/class-cron.php:1025
learnomy_purchase_descriptor filter $descriptor, $type, $item_id Describe a purchase type for display on a gateway's order record. includes/functions.php:5763
learnomy_purge_page_cache action $url Fires when a Learnomy URL's cached copy is stale. Hook a CDN or any page. includes/functions.php:5859
learnomy_pwa_app_name filter get_bloginfo( 'name' ) The app name in the PWA web manifest. includes/class-router.php:947
learnomy_pwa_app_short_name filter 'Learnomy' The app name in the PWA web manifest. includes/class-router.php:953
learnomy_pwa_icon filter $icon The app name in the PWA web manifest. includes/class-router.php:974
learnomy_pwa_manifest filter $manifest Filter the whole PWA manifest before it is served. includes/class-router.php:987
learnomy_pwa_theme_color filter '#2383e2' The app name in the PWA web manifest. includes/class-router.php:964
learnomy_query_vars filter $vars The public query variables Learnomy registers with WordPress. includes/class-router.php:369
learnomy_question_taxonomies filter $default The tag taxonomies offered for quiz questions. includes/functions.php:5099
learnomy_question_types filter $types Filters the registered question types. includes/class-question-types.php:67
learnomy_quiz_display_templates filter $templates Filter the quiz display templates. includes/functions.php:1948
learnomy_quiz_start_style filter $style Filter the quiz start-screen layout. includes/functions.php:1994
learnomy_quiz_taxonomies filter $default The tag taxonomies offered for quizzes. includes/functions.php:5126
learnomy_reengagement_enabled filter true Whether the inactivity re-engagement email runs at all. includes/class-cron.php:569
learnomy_reengagement_max_per_run filter 500 The maximum number of re-engagement emails queued in one run. includes/class-cron.php:586
learnomy_register_abilities action Fires inside wp_abilities_api_init after Learnomy's own abilities are registered, so. includes/class-abilities.php:135
learnomy_register_instructor_slug filter 'register/instructor' The URL slug of the instructor registration page. includes/functions.php:858
learnomy_register_student_slug filter 'register/student' The URL slug of the student registration page. includes/functions.php:846
learnomy_registered_tag_types filter $types Extend the allow-list for vocabularies not surfaced by the three core. includes/functions.php:5152
learnomy_reminder_cadences filter array( '7d', '3d', '1d' ) The cadences at which expiry reminders are sent before an enrollment's access ends. includes/class-cron.php:641 (2)
learnomy_require_login_for_content filter $on Whether course content routes redirect logged-out visitors to the login page. includes/functions.php:717
learnomy_reserved_slugs filter array( // WP pagination segment. 'page', // /instructor/ children (Pro frontend builder... The URL segments reserved by Learnomy, which a course or other slug may not use. includes/functions.php:410
learnomy_route_access_gates filter array( 'instructor-courses' => 'partials/instructor-access-gate.php', 'instructor-stude... Filter the routes that render an access gate instead of a 404. includes/class-template-loader.php:706
learnomy_route_capabilities filter self::$capability_routes Capability gate. Being logged in is not the same as being allowed:. includes/class-template-loader.php:353
learnomy_route_enabled filter true, $route Per-route enable gate. A route whose feature/module is turned off. includes/class-template-loader.php:398
learnomy_route_http_status filter (int) ( $view_data['http_status'] ?? 200 ), $route, $data, $view_data The HTTP status a route renders with, such as 403 or 410. Decided before headers are sent. includes/class-template-loader.php:607
learnomy_route_no_cache_for_user filter true, $route Whether a logged-in user's Learnomy page is sent with private, no-cache headers so a page. includes/class-template-loader.php:419
learnomy_route_not_found filter ! empty( $view_data['not_found'] ), $route, $data, $view_data Whether the request is a 404. Lets a route without its own view-data resolver declare that. includes/class-template-loader.php:584
learnomy_route_slug filter $value, $option_key Uniform slug filter - THE single seam the route registry promised, so a. includes/functions.php:374
learnomy_route_title filter '', $route, $data Filter the for a route with no built-in title - the.</td> <td><code>includes/class-template-loader.php:3927</code></td> </tr> <tr> <td><code>learnomy_routes</code></td> <td>filter</td> <td><code>$defs</code></td> <td>Filter the route table. Pro + third-party code add/modify routes here.</td> <td><code>includes/class-routes.php:338</code></td> </tr> <tr> <td><code>learnomy_send_access_expiring_reminders</code></td> <td>filter</td> <td><code>true</code></td> <td></td> <td><code>includes/class-cron.php:510</code> (2)</td> </tr> <tr> <td><code>learnomy_send_renewal_reminders</code></td> <td>filter</td> <td><code>true</code></td> <td></td> <td><code>includes/class-cron.php:511</code> (2)</td> </tr> <tr> <td><code>learnomy_solo_mode</code></td> <td>filter</td> <td><code>$on</code></td> <td>Whether the site runs in solo mode: one instructor, no commissions, no co-instructors and no.</td> <td><code>includes/functions.php:560</code></td> </tr> <tr> <td><code>learnomy_standalone_dark_mode</code></td> <td>filter</td> <td><code>false</code></td> <td>Filter whether Learnomy shows its own dark-mode toggle and applies its own.</td> <td><code>includes/functions.php:2614</code></td> </tr> <tr> <td><code>learnomy_student_registration_enabled</code></td> <td>filter</td> <td><code>$on</code></td> <td>Whether visitors may register as students.</td> <td><code>includes/functions.php:638</code></td> </tr> <tr> <td><code>learnomy_student_registration_url</code></td> <td>filter</td> <td><code>wp_login_url( $redirect ), $redirect</code></td> <td>Replacement destination for signup CTAs when student registration is.</td> <td><code>includes/functions.php:669</code></td> </tr> <tr> <td><code>learnomy_subscription_auto_expired</code></td> <td>action</td> <td><code>(int) $row->id, (int) $row->user_id, (int) $row->plan_id</code></td> <td>Fires when the sweep expires a subscription whose period ended more than the grace period.</td> <td><code>includes/class-cron.php:1122</code></td> </tr> <tr> <td><code>learnomy_subscription_grace_days</code></td> <td>filter</td> <td><code>$days</code></td> <td>Filter the past-due grace window (days).</td> <td><code>includes/functions.php:2367</code></td> </tr> <tr> <td><code>learnomy_subscription_trial_ending</code></td> <td>action</td> <td><code>(int) $row->id, (int) $row->user_id, (int) $row->plan_id, (string) $row->trial_ends_at</code></td> <td>Fires once for each trialing subscription whose trial ends within the next 72 hours.</td> <td><code>includes/class-cron.php:1160</code></td> </tr> <tr> <td><code>learnomy_suppress_webhooks</code></td> <td>filter</td> <td><code>false, $event, $payload</code></td> <td>Short-circuit outbound webhook delivery.</td> <td><code>includes/functions.php:1637</code></td> </tr> <tr> <td><code>learnomy_template_map</code></td> <td>filter</td> <td><code>self::$default_template_map</code></td> <td>The template file used for each route.</td> <td><code>includes/class-template-loader.php:926</code></td> </tr> <tr> <td><code>learnomy_text_response_types</code></td> <td>filter</td> <td><code>[ 'essay', 'short_answer', 'fill_blank' ]</code></td> <td>Filters the types whose response is free text rather than option ids.</td> <td><code>includes/class-question-types.php:125</code></td> </tr> <tr> <td><code>learnomy_thank_you_slug</code></td> <td>filter</td> <td><code>enroll_slug() . '/thank-you'</code></td> <td>The URL path of the checkout thank-you page.</td> <td><code>includes/functions.php:516</code></td> </tr> <tr> <td><code>learnomy_three_decimal_currencies</code></td> <td>filter</td> <td><code>array( 'BHD', 'IQD', 'JOD', 'KWD', 'LYD', 'OMR', 'TND' )</code></td> <td>Currencies whose smallest unit is a THOUSANDTH, not a hundredth.</td> <td><code>includes/functions.php:2788</code></td> </tr> <tr> <td><code>learnomy_trusted_proxies</code></td> <td>filter</td> <td><code>array()</code></td> <td>Addresses or CIDR ranges of reverse proxies / CDNs in front of this site,.</td> <td><code>includes/functions.php:143</code></td> </tr> <tr> <td><code>learnomy_user_reference_tables</code></td> <td>filter</td> <td><code>$refs</code></td> <td>Filter the user-reference map.</td> <td><code>includes/functions.php:1874</code></td> </tr> <tr> <td><code>learnomy_view_data_resolvers</code></td> <td>filter</td> <td><code>self::$view_data_resolvers</code></td> <td>The classes that resolve view data for each route.</td> <td><code>includes/class-template-loader.php:905</code></td> </tr> <tr> <td><code>learnomy_virtual_query_corrected</code></td> <td>action</td> <td><code>$query, (string) $route</code></td> <td>Fires once the main query has been told it is on a Learnomy route.</td> <td><code>includes/class-router.php:151</code></td> </tr> <tr> <td><code>learnomy_wishlist_url</code></td> <td>filter</td> <td><code>add_query_arg( 'tab', 'wishlist', route_url( 'account-courses' ) )</code></td> <td>The Wishlist address. Filter it to send members somewhere else.</td> <td><code>includes/functions.php:2705</code></td> </tr> <tr> <td><code>learnomy_zero_decimal_currencies</code></td> <td>filter</td> <td><code>array( 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VN...</code></td> <td>The currency codes that have no minor unit, so their amounts are not multiplied by 100.</td> <td><code>includes/functions.php:2802</code></td> </tr> </tbody></table></div> <h2 id="cron">Cron<a class="heading-anchor" href="#cron" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_lesson_unlock_is_valid</code></td> <td>filter</td> <td><code>$valid, $user_id, $lesson_id, $course_id</code></td> <td>Filter whether a relative-drip unlock row is still valid to fire.</td> <td><code>includes/cron/class-drip-cron.php:245</code></td> </tr> <tr> <td><code>learnomy_lesson_unlocked</code></td> <td>action</td> <td><code>$lesson_id, $user_id, $course_id</code></td> <td>Fires once when a previously-locked lesson becomes available.</td> <td><code>includes/cron/class-drip-cron.php:151</code> (2)</td> </tr> </tbody></table></div> <h2 id="db">Db<a class="heading-anchor" href="#db" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_relation_models</code></td> <td>filter</td> <td><code>array()</code></td> <td>Filters the model classes asked to declare their relations.</td> <td><code>includes/db/class-relations.php:204</code></td> </tr> <tr> <td><code>learnomy_relation_parents</code></td> <td>filter</td> <td><code>$parents</code></td> <td>Filters the entity => parent table map.</td> <td><code>includes/db/class-relations.php:142</code></td> </tr> <tr> <td><code>learnomy_relations_cascaded</code></td> <td>action</td> <td><code>$entity, $id, $removed, $cleared</code></td> <td>Fires after an entity's declared relations have been cleaned.</td> <td><code>includes/db/class-relations.php:309</code></td> </tr> <tr> <td><code>learnomy_schema_strip_fulltext</code></td> <td>filter</td> <td><code>$is_temp</code></td> <td>Force the FULLTEXT strip on or off.</td> <td><code>includes/db/class-schema.php:58</code></td> </tr> </tbody></table></div> <h2 id="integrations">Integrations<a class="heading-anchor" href="#integrations" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_companion_package_hosts</code></td> <td>filter</td> <td><code>array( $store_host )</code></td> <td>Hosts allowed to serve a companion plugin zip.</td> <td><code>includes/integrations/class-companion-installer.php:245</code></td> </tr> <tr> <td><code>learnomy_companions</code></td> <td>filter</td> <td><code>array( 'mediashield' => array( 'label' => __( 'MediaShield', 'learnomy' ), 'why' => __(...</code></td> <td>Filter the Academy Stack companion catalog. Pro + third-party plugins.</td> <td><code>includes/integrations/class-companion-registry.php:46</code></td> </tr> <tr> <td><code>learnomy_theme_token_maps</code></td> <td>filter</td> <td><code>$maps</code></td> <td>Filter the theme token maps. Themes/add-ons register a mapping here so.</td> <td><code>includes/integrations/class-theme-bridge.php:155</code></td> </tr> </tbody></table></div> <h2 id="migration">Migration<a class="heading-anchor" href="#migration" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_migration_not_migrated</code></td> <td>filter</td> <td><code>$items, $source_slug</code></td> <td>Filter the "not migrated" list, per source. Shown on BOTH the dry-run.</td> <td><code>includes/migration/class-import-service.php:286</code></td> </tr> <tr> <td><code>learnomy_migration_question_type_fallbacks</code></td> <td>filter</td> <td><code>array( 'image_matching' => 'matching', 'image_answering' => 'short_answer', 'h5p' => 's...</code></td> <td>The fallback Learnomy question type for each source question type with no exact equivalent.</td> <td><code>includes/migration/class-import-service.php:309</code></td> </tr> <tr> <td><code>learnomy_migration_sources</code></td> <td>filter</td> <td><code>$defaults</code></td> <td>Filter the migration sources. Pro and third parties append modules.</td> <td><code>includes/migration/class-source-registry.php:49</code></td> </tr> </tbody></table></div> <h2 id="models">Models<a class="heading-anchor" href="#models" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_access_grant_reference_label</code></td> <td>filter</td> <td><code>$label, $source, $external_ref</code></td> <td>How the admin screens name a grant's reference.</td> <td><code>includes/models/class-access-grant.php:196</code></td> </tr> <tr> <td><code>learnomy_catalog_where_clauses</code></td> <td>filter</td> <td><code>array( $where_sql, $where_values ), $args</code></td> <td>Final hook for extensions to contribute WHERE clauses + values to.</td> <td><code>includes/models/class-course.php:670</code></td> </tr> <tr> <td><code>learnomy_category_includes_descendants</code></td> <td>filter</td> <td><code>true, $category_id</code></td> <td>Whether a category listing rolls up the courses filed under its.</td> <td><code>includes/models/class-category.php:191</code></td> </tr> <tr> <td><code>learnomy_cert_verify_throttle_seconds</code></td> <td>filter</td> <td><code>5 * MINUTE_IN_SECONDS</code></td> <td>The minimum seconds between verification-count increments for one certificate.</td> <td><code>includes/models/class-certificate.php:452</code></td> </tr> <tr> <td><code>learnomy_certificate_template_usage</code></td> <td>filter</td> <td><code>$reasons, $template_id</code></td> <td>Filter what else depends on a certificate template.</td> <td><code>includes/models/class-certificate-template.php:170</code></td> </tr> <tr> <td><code>learnomy_commission_void_payout_statuses</code></td> <td>filter</td> <td><code>array( 'reversed', 'refunded' )</code></td> <td>Filters the payout statuses that exclude a commission from earnings.</td> <td><code>includes/models/class-commission.php:78</code></td> </tr> <tr> <td><code>learnomy_coupon_exhausted</code></td> <td>action</td> <td><code>$id</code></td> <td>Fires when a coupon is retired for running out of redemptions.</td> <td><code>includes/models/class-coupon.php:206</code></td> </tr> <tr> <td><code>learnomy_course_complete_continue_url</code></td> <td>filter</td> <td><code>self::completed_destination( $course, $user_id ), $course, $user_id</code></td> <td>Filter the "Continue Learning" destination for a course the viewer.</td> <td><code>includes/models/class-course.php:3962</code></td> </tr> <tr> <td><code>learnomy_course_complete_url</code></td> <td>filter</td> <td><code>\Learnomy\route_url( 'course-complete', array( 'slug' => (string) $course->slug ) ), $c...</code></td> <td>Where a learner lands when a course completes.</td> <td><code>includes/models/class-course.php:3844</code></td> </tr> <tr> <td><code>learnomy_course_enroll_gate</code></td> <td>filter</td> <td><code>'', $course, $user_id</code></td> <td>Lets an extension take over the enrol call-to-action for a course.</td> <td><code>includes/models/class-course.php:4067</code> (2)</td> </tr> <tr> <td><code>learnomy_course_is_purchasable</code></td> <td>filter</td> <td><code>true, $course, $user_id</code></td> <td>Whether a course may be bought right now.</td> <td><code>includes/models/class-course.php:3810</code></td> </tr> <tr> <td><code>learnomy_course_sale_transaction_types</code></td> <td>filter</td> <td><code>array( 'course', 'subscription_course', 'subscription_course_renewal' )</code></td> <td>Filter the transaction types treated as the sale of one course.</td> <td><code>includes/models/class-transaction.php:100</code></td> </tr> <tr> <td><code>learnomy_courses_primed</code></td> <td>action</td> <td><code>$lrn_primed</code></td> <td></td> <td><code>includes/models/class-course.php:968</code></td> </tr> <tr> <td><code>learnomy_enrollment_current_statuses</code></td> <td>filter</td> <td><code>[ 'active', 'completed' ]</code></td> <td>Statuses treated as a live enrolment by rosters, counts and averages.</td> <td><code>includes/models/class-enrollment.php:1274</code></td> </tr> <tr> <td><code>learnomy_enrollment_source_is_paid</code></td> <td>filter</td> <td><code>in_array( $source, array( 'purchase', 'paid', 'subscription', 'membership' ), true ), $...</code></td> <td>Whether an enrollment source counts as money changing hands.</td> <td><code>includes/models/class-enrollment.php:1160</code></td> </tr> <tr> <td><code>learnomy_enrollment_source_is_self_serve</code></td> <td>filter</td> <td><code>'free' === $source, $source</code></td> <td>Whether an enrollment source is self-serve.</td> <td><code>includes/models/class-enrollment.php:1150</code></td> </tr> <tr> <td><code>learnomy_enrollment_source_label</code></td> <td>filter</td> <td><code>$labels[ $source ] ?? ucfirst( str_replace( '_', ' ', $source ) ), $source</code></td> <td>Filters the human label for an enrollment source, so an integration.</td> <td><code>includes/models/class-enrollment.php:1121</code></td> </tr> <tr> <td><code>learnomy_instructor_resumed</code></td> <td>action</td> <td><code>$user_id</code></td> <td>An instructor was resumed and takes new business again.</td> <td><code>includes/models/class-instructor.php:251</code></td> </tr> <tr> <td><code>learnomy_instructor_suspended</code></td> <td>action</td> <td><code>$user_id</code></td> <td>An instructor was paused: hidden from the public directory, no new.</td> <td><code>includes/models/class-instructor.php:244</code></td> </tr> <tr> <td><code>learnomy_lesson_attachment_added</code></td> <td>action</td> <td><code>$lesson_id, $attachment_id, $media_id</code></td> <td>Fires after a file is attached to a lesson.</td> <td><code>includes/models/class-lesson.php:1365</code></td> </tr> <tr> <td><code>learnomy_lesson_attachment_removed</code></td> <td>action</td> <td><code>(int) $row->lesson_id, $attachment_id</code></td> <td>Fires after a lesson attachment is detached.</td> <td><code>includes/models/class-lesson.php:1386</code></td> </tr> <tr> <td><code>learnomy_lesson_content_type_descriptors</code></td> <td>filter</td> <td><code>$descriptors</code></td> <td>Filter the described lesson content types.</td> <td><code>includes/models/class-lesson.php:162</code></td> </tr> <tr> <td><code>learnomy_lesson_content_type_label</code></td> <td>filter</td> <td><code>$label, $type</code></td> <td>Filter the human-readable label for a lesson content-type, so a Pro.</td> <td><code>includes/models/class-lesson.php:262</code></td> </tr> <tr> <td><code>learnomy_lesson_content_types</code></td> <td>filter</td> <td><code>self::CONTENT_TYPES</code></td> <td>Filter the selectable lesson content-types.</td> <td><code>includes/models/class-lesson.php:86</code></td> </tr> <tr> <td><code>learnomy_max_webhooks</code></td> <td>filter</td> <td><code>self::DEFAULT_MAX</code></td> <td>Filter the maximum number of active outbound webhooks.</td> <td><code>includes/models/class-webhook.php:44</code></td> </tr> <tr> <td><code>learnomy_membership_free_plan_limit</code></td> <td>filter</td> <td><code>self::FREE_PLAN_LIMIT</code></td> <td>Filter the free-plan cap. Pro sets this to PHP_INT_MAX.</td> <td><code>includes/models/class-membership-plan.php:145</code></td> </tr> <tr> <td><code>learnomy_model_where_default_limit</code></td> <td>filter</td> <td><code>5000, static::table_name()</code></td> <td>The row ceiling applied to a model query that passes no limit.</td> <td><code>includes/models/class-model.php:695</code></td> </tr> <tr> <td><code>learnomy_notification_type_label</code></td> <td>filter</td> <td><code>$label, $type</code></td> <td>Filter the human label for a notification type slug.</td> <td><code>includes/models/class-notification.php:80</code></td> </tr> <tr> <td><code>learnomy_progress_activity_announcement</code></td> <td>filter</td> <td><code>$map, $status</code></td> <td>Verb and icon used to announce a progress row in an activity feed.</td> <td><code>includes/models/class-progress.php:612</code></td> </tr> <tr> <td><code>learnomy_provider_cancel_max_attempts</code></td> <td>filter</td> <td><code>10</code></td> <td>How many times a cancellation is retried at the payment provider before giving up.</td> <td><code>includes/models/class-subscription.php:718</code></td> </tr> <tr> <td><code>learnomy_quiz_max_attempts</code></td> <td>filter</td> <td><code>$limit, $quiz, $user_id</code></td> <td>Filter the number of attempts a student may take on a quiz.</td> <td><code>includes/models/class-quiz.php:578</code></td> </tr> <tr> <td><code>learnomy_quiz_question_count</code></td> <td>filter</td> <td><code>$slots, $quiz_id</code></td> <td>Filter how many questions a sitting of a quiz holds.</td> <td><code>includes/models/class-quiz.php:664</code></td> </tr> <tr> <td><code>learnomy_renewal_transaction_types</code></td> <td>filter</td> <td><code>array( 'membership_renewal', 'subscription_course_renewal' )</code></td> <td>Filter the transaction types treated as a renewal.</td> <td><code>includes/models/class-transaction.php:121</code></td> </tr> <tr> <td><code>learnomy_store_managed_label</code></td> <td>filter</td> <td><code>$labels[ $source ] ?? ucwords( str_replace( array( '-', '_' ), ' ', $source ) ), $source</code></td> <td>The store's display name for a store-managed membership source.</td> <td><code>includes/models/class-subscription.php:162</code></td> </tr> <tr> <td><code>learnomy_subscription_deleted</code></td> <td>action</td> <td><code>$id</code></td> <td>Fires after a subscription is deleted so extensions can clean up.</td> <td><code>includes/models/class-subscription.php:228</code></td> </tr> <tr> <td><code>learnomy_technical_content_types</code></td> <td>filter</td> <td><code>self::TECHNICAL_CONTENT_TYPES</code></td> <td>The lesson content types whose technical name is hidden from learners.</td> <td><code>includes/models/class-lesson.php:291</code></td> </tr> <tr> <td><code>learnomy_webhook_deleted</code></td> <td>action</td> <td><code>$id</code></td> <td>Fires after a webhook is deleted so extensions can clean up rows.</td> <td><code>includes/models/class-webhook.php:108</code></td> </tr> </tbody></table></div> <h2 id="modules">Modules<a class="heading-anchor" href="#modules" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_after_module_disabled</code></td> <td>action</td> <td><code>$slug</code></td> <td>Fires after a module is disabled. A module that wrote rows into a.</td> <td><code>includes/modules/class-module-kernel.php:246</code></td> </tr> <tr> <td><code>learnomy_after_module_enabled</code></td> <td>action</td> <td><code>$slug</code></td> <td>Fires after a module is enabled. Lets the owning extension (Free or.</td> <td><code>includes/modules/class-module-kernel.php:204</code></td> </tr> <tr> <td><code>learnomy_module_disable_impact</code></td> <td>filter</td> <td><code>$impact, $slug</code></td> <td>Declare what ELSE a site loses by switching this module off.</td> <td><code>includes/modules/class-module-kernel.php:353</code></td> </tr> <tr> <td><code>learnomy_module_enabled</code></td> <td>filter</td> <td><code>$result, $slug</code></td> <td>Final say on whether an OPTIONAL module is active. Lets a site-wide.</td> <td><code>includes/modules/class-module-kernel.php:102</code></td> </tr> <tr> <td><code>learnomy_module_preset_applied</code></td> <td>action</td> <td><code>$preset_slug, $modules</code></td> <td>Fires after a wizard preset has been applied. Listeners can seed.</td> <td><code>includes/modules/class-module-kernel.php:896</code></td> </tr> <tr> <td><code>learnomy_module_presets</code></td> <td>filter</td> <td><code>$presets</code></td> <td>Filter the wizard presets. Custom builds can rename, replace, or.</td> <td><code>includes/modules/class-module-kernel.php:841</code></td> </tr> <tr> <td><code>learnomy_module_user_commitment</code></td> <td>filter</td> <td><code>$held, $slug, $user_id</code></td> <td>Whether this user still holds something the module sold them, and so.</td> <td><code>includes/modules/class-module-kernel.php:389</code></td> </tr> <tr> <td><code>learnomy_modules_catalog</code></td> <td>filter</td> <td><code>$base</code></td> <td>Filter the module catalog so Pro extensions and third parties.</td> <td><code>includes/modules/class-module-kernel.php:751</code></td> </tr> <tr> <td><code>learnomy_pro_enabled_extensions</code></td> <td>filter</td> <td><code>(array) get_option( 'learnomy_pro_extensions', array() )</code></td> <td></td> <td><code>includes/modules/class-module-kernel.php:125</code></td> </tr> <tr> <td><code>learnomy_site_sells_something</code></td> <td>filter</td> <td><code>$sells</code></td> <td>Filter whether this site counts as selling something.</td> <td><code>includes/modules/class-module-kernel.php:542</code></td> </tr> </tbody></table></div> <h2 id="notifications">Notifications<a class="heading-anchor" href="#notifications" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_community_notification_removed</code></td> <td>action</td> <td><code>'course', $course_id</code></td> <td>Fires when an object that community notifications point at is deleted.</td> <td><code>includes/notifications/class-community-notification-contract.php:46</code> (2)</td> </tr> </tbody></table></div> <h2 id="permissions">Permissions<a class="heading-anchor" href="#permissions" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_can_access_course</code></td> <td>filter</td> <td><code>$result, $user_id, $context_id</code></td> <td>Whether a user may access a course.</td> <td><code>includes/permissions/class-permission-engine.php:121</code></td> </tr> <tr> <td><code>learnomy_co_instructor_can_manage</code></td> <td>filter</td> <td><code>false, $user_id, (int) $course->id</code></td> <td>Allow an assigned co-instructor to co-manage a course (content,.</td> <td><code>includes/permissions/class-permission-engine.php:386</code></td> </tr> <tr> <td><code>learnomy_credential_max_failures</code></td> <td>filter</td> <td><code>self::CREDENTIAL_MAX_FAILURES</code></td> <td>The failed credential attempts allowed in a bucket before it is locked out.</td> <td><code>includes/permissions/class-rate-limiter.php:115</code></td> </tr> <tr> <td><code>learnomy_credential_window</code></td> <td>filter</td> <td><code>self::CREDENTIAL_WINDOW</code></td> <td>How long, in seconds, failed credential attempts in a bucket are counted.</td> <td><code>includes/permissions/class-rate-limiter.php:142</code></td> </tr> <tr> <td><code>learnomy_guest_checkout_rate_limit</code></td> <td>filter</td> <td><code>self::GUEST_CHECKOUTS_PER_HOUR</code></td> <td>The number of guest checkouts allowed per IP address per hour.</td> <td><code>includes/permissions/class-rate-limiter.php:64</code></td> </tr> <tr> <td><code>learnomy_is_course_learner</code></td> <td>filter</td> <td><code>$result, $user_id, $course_id</code></td> <td>Final say on whether a user counts as a learner on this course.</td> <td><code>includes/permissions/class-permission-engine.php:274</code></td> </tr> <tr> <td><code>learnomy_permission_check</code></td> <td>filter</td> <td><code>false, $user_id, $action, $context_id</code></td> <td>The verdict for a permission action when the user lacks the WordPress capability behind it.</td> <td><code>includes/permissions/class-permission-engine.php:87</code> (2)</td> </tr> <tr> <td><code>learnomy_permission_context_check</code></td> <td>filter</td> <td><code>true, $user_id, $action, $context_id</code></td> <td>The verdict for an action that has no context-specific rule, once the capability check has passed.</td> <td><code>includes/permissions/class-permission-engine.php:196</code></td> </tr> <tr> <td><code>learnomy_visibility_grants</code></td> <td>filter</td> <td><code>$grants, $viewer_id, $purpose</code></td> <td>Filters the rectangles a viewer may read.</td> <td><code>includes/permissions/class-permission-engine.php:531</code></td> </tr> </tbody></table></div> <h2 id="security">Security<a class="heading-anchor" href="#security" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_scope_media_to_author</code></td> <td>filter</td> <td><code>$scope, get_current_user_id()</code></td> <td>Filter whether the Media Library is limited to the user's own uploads.</td> <td><code>includes/security/class-media-library-scope.php:60</code></td> </tr> <tr> <td><code>learnomy_webhook_allowed_schemes</code></td> <td>filter</td> <td><code>array( 'https', 'http' )</code></td> <td>Allowed URL schemes for outbound webhooks. Defaults to https only.</td> <td><code>includes/security/class-webhook-url-validator.php:124</code></td> </tr> </tbody></table></div> <h2 id="seo">Seo<a class="heading-anchor" href="#seo" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_meta_description</code></td> <td>filter</td> <td><code>$description, (string) get_query_var( 'learnomy_route' )</code></td> <td>Filter the meta description for a Learnomy route.</td> <td><code>includes/seo/class-schema-markup.php:537</code></td> </tr> <tr> <td><code>learnomy_meta_description_max_length</code></td> <td>filter</td> <td><code>155</code></td> <td>Max meta-description length before truncation.</td> <td><code>includes/seo/class-schema-markup.php:581</code></td> </tr> <tr> <td><code>learnomy_seo_plugin_head_filters</code></td> <td>filter</td> <td><code>self::SEO_PLUGIN_HEAD_FILTERS</code></td> <td>Filters the SEO plugin filters Learnomy empties on its own routes, so.</td> <td><code>includes/seo/class-schema-markup.php:155</code></td> </tr> <tr> <td><code>learnomy_seo_yield_to_plugin</code></td> <td>filter</td> <td><code>$seo_plugin_active</code></td> <td>Whether Learnomy yields its schema markup to an active SEO plugin.</td> <td><code>includes/seo/class-schema-markup.php:454</code></td> </tr> <tr> <td><code>learnomy_sitemap_courses_per_page</code></td> <td>filter</td> <td><code>100</code></td> <td>The number of courses listed on each sitemap page.</td> <td><code>includes/seo/class-course-sitemap-provider.php:74</code></td> </tr> <tr> <td><code>learnomy_sitemap_instructors_per_page</code></td> <td>filter</td> <td><code>100</code></td> <td>The number of instructors listed on each sitemap page.</td> <td><code>includes/seo/class-instructor-sitemap-provider.php:103</code></td> </tr> </tbody></table></div> <h2 id="services">Services<a class="heading-anchor" href="#services" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_access_email_covers</code></td> <td>filter</td> <td><code>array( 'enrollment', 'membership_created', 'new_user_account', 'space_c1' )</code></td> <td></td> <td><code>includes/services/class-access-grant-service.php:199</code></td> </tr> <tr> <td><code>learnomy_access_grant_created</code></td> <td>action</td> <td><code>$grant_id, (int) $row->user_id, (string) $row->item_type, (int) $row->item_id, (string)...</code></td> <td>An Access Grant came into force (ledger level). Fires once per ledger.</td> <td><code>includes/services/class-access-grant-service.php:916</code></td> </tr> <tr> <td><code>learnomy_access_grant_revoked</code></td> <td>action</td> <td><code>(int) $row->id, (int) $row->user_id, (string) $row->item_type, (int) $row->item_id, (st...</code></td> <td>An Access Grant ended (ledger level).</td> <td><code>includes/services/class-access-grant-service.php:949</code></td> </tr> <tr> <td><code>learnomy_access_grant_types</code></td> <td>filter</td> <td><code>$types</code></td> <td>The item types an Access Grant can give. Pro adds learning_path,.</td> <td><code>includes/services/class-access-grant-service.php:102</code></td> </tr> <tr> <td><code>learnomy_access_granted</code></td> <td>action</td> <td><code>$enrollment_id, $user_id, $course_id, $source</code></td> <td>Fires once per person when a student gains a course they did not have:.</td> <td><code>includes/services/class-enrollment-service.php:663</code></td> </tr> <tr> <td><code>learnomy_access_granted_email</code></td> <td>filter</td> <td><code>( new Notification_Service() )->is_email_enabled_for_type( 'access_granted' ), $source</code></td> <td>Send the one "Your access is ready" email for grants from this source.</td> <td><code>includes/services/class-access-grant-service.php:185</code></td> </tr> <tr> <td><code>learnomy_access_revoked</code></td> <td>action</td> <td><code>$enrollment_id, (int) $enrollment->user_id, (int) $enrollment->course_id, (string) $enr...</code></td> <td>Fires once per person when a student loses a course: the last.</td> <td><code>includes/services/class-enrollment-service.php:624</code></td> </tr> <tr> <td><code>learnomy_account_billing_view_data</code></td> <td>filter</td> <td><code>$view_data, $user_id</code></td> <td>Filter the resolved view-data array. Pro extensions can decorate.</td> <td><code>includes/services/view-data/class-account-billing-view-data.php:120</code></td> </tr> <tr> <td><code>learnomy_account_field_multi_types</code></td> <td>filter</td> <td><code>self::MULTI_TYPES</code></td> <td>Filter which account-field types hold multiple values. A custom type.</td> <td><code>includes/services/class-custom-fields.php:86</code></td> </tr> <tr> <td><code>learnomy_account_field_option_types</code></td> <td>filter</td> <td><code>self::OPTION_TYPES</code></td> <td>Filter which account-field types carry an option list.</td> <td><code>includes/services/class-custom-fields.php:102</code></td> </tr> <tr> <td><code>learnomy_account_field_render</code></td> <td>filter</td> <td><code>false, $field, $value</code></td> <td>Render an account field yourself. Echo the markup and return true to.</td> <td><code>includes/services/class-custom-fields.php:279</code></td> </tr> <tr> <td><code>learnomy_account_field_sanitize</code></td> <td>filter</td> <td><code>null, $field, $raw</code></td> <td>Sanitize an account field yourself. Return anything other than null.</td> <td><code>includes/services/class-custom-fields.php:510</code></td> </tr> <tr> <td><code>learnomy_account_field_types</code></td> <td>filter</td> <td><code>self::TYPES</code></td> <td>Filter the account-field types a site accepts.</td> <td><code>includes/services/class-custom-fields.php:67</code></td> </tr> <tr> <td><code>learnomy_after_email_send</code></td> <td>action</td> <td><code>$to, $subject, $template, $user_id, $sent</code></td> <td>Fires immediately after an email send attempt.</td> <td><code>includes/services/class-notification-service.php:597</code></td> </tr> <tr> <td><code>learnomy_allow_guest_checkout</code></td> <td>filter</td> <td><code>$on, $course</code></td> <td>Filters whether guest checkout is allowed for a given course.</td> <td><code>includes/services/class-payment-settings.php:280</code></td> </tr> <tr> <td><code>learnomy_allow_multiple_plan_subscriptions</code></td> <td>filter</td> <td><code>false</code></td> <td>Allow multiple concurrent plan subscriptions per user. Default false:.</td> <td><code>includes/services/class-subscription-service.php:424</code></td> </tr> <tr> <td><code>learnomy_avatar_updated</code></td> <td>action</td> <td><code>$user_id, (int) $attachment_id</code></td> <td>Fires after a member's avatar changes. Lets caches (CDN, object.</td> <td><code>includes/services/class-avatar-service.php:179</code> (2)</td> </tr> <tr> <td><code>learnomy_before_email_send</code></td> <td>action</td> <td><code>$to, $subject, $template, $user_id</code></td> <td>Fires immediately before an email is sent.</td> <td><code>includes/services/class-notification-service.php:584</code></td> </tr> <tr> <td><code>learnomy_can_access_lesson</code></td> <td>filter</td> <td><code>$available, $user_id, $lesson_id, $lesson</code></td> <td>Gate a lesson's availability. Pro's content-drip extension hooks this.</td> <td><code>includes/services/class-lesson-service.php:233</code></td> </tr> <tr> <td><code>learnomy_certificate_asserted_facts</code></td> <td>filter</td> <td><code>$facts, $certificate</code></td> <td>Filter the facts a certificate asserts, as read back for display.</td> <td><code>includes/services/class-certificate-service.php:317</code></td> </tr> <tr> <td><code>learnomy_certificate_designs</code></td> <td>filter</td> <td><code>[]</code></td> <td>The curated certificate designs.</td> <td><code>includes/services/class-certificate-library.php:72</code></td> </tr> <tr> <td><code>learnomy_certificate_issue_snapshot</code></td> <td>filter</td> <td><code>$snapshot, $user_id, $course_id, $context</code></td> <td>Filter the facts recorded on a certificate at issue time.</td> <td><code>includes/services/class-certificate-service.php:199</code></td> </tr> <tr> <td><code>learnomy_certificate_issued</code></td> <td>action</td> <td><code>$certificate_id, $user_id, $course_id</code></td> <td>Fires after a certificate is issued.</td> <td><code>includes/services/class-certificate-service.php:146</code></td> </tr> <tr> <td><code>learnomy_certificate_merge_tags</code></td> <td>filter</td> <td><code>array()</code></td> <td>Add merge tags to the certificate designer and renderer.</td> <td><code>includes/services/class-certificate-renderer.php:393</code></td> </tr> <tr> <td><code>learnomy_certificate_revoked</code></td> <td>action</td> <td><code>$certificate_id, $certificate</code></td> <td>Fires after a certificate is revoked.</td> <td><code>includes/services/class-certificate-service.php:501</code></td> </tr> <tr> <td><code>learnomy_certificate_verified</code></td> <td>action</td> <td><code>$certificate->id, $uuid</code></td> <td>Fires when a certificate is verified by its public UUID.</td> <td><code>includes/services/class-certificate-service.php:408</code></td> </tr> <tr> <td><code>learnomy_checkout_cancelled_view_data</code></td> <td>filter</td> <td><code>$view_data, $course_id, $plan_id</code></td> <td>Filter the cancelled-flow view data before it reaches the template.</td> <td><code>includes/services/view-data/class-checkout-cancelled-view-data.php:83</code></td> </tr> <tr> <td><code>learnomy_checkout_thank_you_view_data</code></td> <td>filter</td> <td><code>$view_data, $transaction, $user_id</code></td> <td>Filter the thank-you view data before it reaches the template.</td> <td><code>includes/services/view-data/class-checkout-thank-you-view-data.php:528</code></td> </tr> <tr> <td><code>learnomy_commission_calculated</code></td> <td>action</td> <td><code>$transaction_id</code></td> <td>Fires after the commission rows for a sale are written.</td> <td><code>includes/services/class-commission-service.php:378</code> (2)</td> </tr> <tr> <td><code>learnomy_commission_eligible</code></td> <td>filter</td> <td><code>$eligible, $transaction</code></td> <td>Filters whether a payment earns commission.</td> <td><code>includes/services/class-commission-service.php:239</code></td> </tr> <tr> <td><code>learnomy_commission_instructor_allocations</code></td> <td>filter</td> <td><code>array( array( 'recipient_id' => $main_author_id, 'amount' => $instructor_pool, 'rate_ap...</code></td> <td>How a sale's instructor pool is split between instructors.</td> <td><code>includes/services/class-commission-service.php:341</code></td> </tr> <tr> <td><code>learnomy_commission_overpaid</code></td> <td>action</td> <td><code>$overpaid, (int) $original->id, $provider</code></td> <td>Commissions already paid out that a refund has now made excessive.</td> <td><code>includes/services/class-refund-service.php:219</code></td> </tr> <tr> <td><code>learnomy_completion_enforcement</code></td> <td>filter</td> <td><code>$mode, $user_id, $lesson</code></td> <td>Layer 5: filter. Last word on the resolved enforcement mode. Return.</td> <td><code>includes/services/class-progress-service.php:602</code></td> </tr> <tr> <td><code>learnomy_consent_documents</code></td> <td>filter</td> <td><code>$docs</code></td> <td>Filters the legal documents a new member must agree to.</td> <td><code>includes/services/class-consent-service.php:99</code></td> </tr> <tr> <td><code>learnomy_consent_required</code></td> <td>filter</td> <td><code>! empty( self::documents() ), self::documents()</code></td> <td>Filters whether terms acceptance is enforced at registration.</td> <td><code>includes/services/class-consent-service.php:118</code></td> </tr> <tr> <td><code>learnomy_course_access_requirements</code></td> <td>filter</td> <td><code>array(), $course, $user_id</code></td> <td>Course-level requirements gate EVERY lesson in the course.</td> <td><code>includes/services/view-data/class-single-lesson-view-data.php:129</code></td> </tr> <tr> <td><code>learnomy_course_completed</code></td> <td>action</td> <td><code>$enrollment_id, (int) $enrollment->user_id, (int) $enrollment->course_id</code></td> <td>Fires after an enrollment is marked completed.</td> <td><code>includes/services/class-enrollment-service.php:887</code></td> </tr> <tr> <td><code>learnomy_course_completion_type_changed</code></td> <td>action</td> <td><code>$id, $new_type, $was_type</code></td> <td>A course's completion type changed, so the number of steps it.</td> <td><code>includes/services/class-course-service.php:149</code></td> </tr> <tr> <td><code>learnomy_course_create_data</code></td> <td>filter</td> <td><code>$data, $author_id</code></td> <td>The data a new course is created with.</td> <td><code>includes/services/class-course-service.php:46</code></td> </tr> <tr> <td><code>learnomy_course_created</code></td> <td>action</td> <td><code>$course_id, $data</code></td> <td>Fires after a course is created.</td> <td><code>includes/services/class-course-service.php:62</code></td> </tr> <tr> <td><code>learnomy_course_deleted</code></td> <td>action</td> <td><code>$id</code></td> <td>Fires after a course is deleted.</td> <td><code>includes/services/class-course-service.php:376</code></td> </tr> <tr> <td><code>learnomy_course_duplicated</code></td> <td>action</td> <td><code>$new_course_id, $id</code></td> <td>Fires after a course is duplicated.</td> <td><code>includes/services/class-course-service.php:523</code></td> </tr> <tr> <td><code>learnomy_course_pending_review</code></td> <td>action</td> <td><code>$id</code></td> <td>This action is documented in includes/services/class-course-service.php.</td> <td><code>includes/services/class-course-service.php:158</code> (2)</td> </tr> <tr> <td><code>learnomy_course_published</code></td> <td>action</td> <td><code>$course_id</code></td> <td>Fires when a course is published, including when it is created already published.</td> <td><code>includes/services/class-course-service.php:73</code> (3)</td> </tr> <tr> <td><code>learnomy_course_restarted</code></td> <td>action</td> <td><code>$user_id, $course_id</code></td> <td>Fires after a learner restarts a course and their certificates for it are revoked.</td> <td><code>includes/services/class-progress-service.php:662</code></td> </tr> <tr> <td><code>learnomy_course_retaken</code></td> <td>action</td> <td><code>$user_id, $course_id, $reset_progress</code></td> <td>Fires after a student has successfully re-entered a course.</td> <td><code>includes/services/class-enrollment-service.php:961</code></td> </tr> <tr> <td><code>learnomy_course_update_data</code></td> <td>filter</td> <td><code>$data, $id</code></td> <td>The data a course is updated with.</td> <td><code>includes/services/class-course-service.php:88</code></td> </tr> <tr> <td><code>learnomy_course_updated</code></td> <td>action</td> <td><code>$id, $data</code></td> <td>Fires after a course is updated.</td> <td><code>includes/services/class-course-service.php:131</code></td> </tr> <tr> <td><code>learnomy_courses_per_page</code></td> <td>filter</td> <td><code>$per_page</code></td> <td>Filter the catalog page size.</td> <td><code>includes/services/view-data/class-catalog-view-data.php:62</code> (2)</td> </tr> <tr> <td><code>learnomy_dashboard_widgets</code></td> <td>filter</td> <td><code>array(), $surface, $context</code></td> <td>The dashboard widgets contributed for a surface.</td> <td><code>includes/services/class-dashboard-widget-registry.php:64</code></td> </tr> <tr> <td><code>learnomy_demo_data_cleaned</code></td> <td>action</td> <td><code>$manifest, $reassign_to</code></td> <td>Fires after demo data is removed.</td> <td><code>includes/services/class-setup-service.php:217</code> (2)</td> </tr> <tr> <td><code>learnomy_demo_data_seeded</code></td> <td>action</td> <td><code>$manifest, $admin_id</code></td> <td>Fires after demo data is created.</td> <td><code>includes/services/class-setup-service.php:182</code></td> </tr> <tr> <td><code>learnomy_email_body</code></td> <td>filter</td> <td><code>$body, $template, $user_id, $data</code></td> <td>The HTML body of a notification email.</td> <td><code>includes/services/class-notification-service.php:566</code></td> </tr> <tr> <td><code>learnomy_email_headers</code></td> <td>filter</td> <td><code>$headers, $template, $user_id</code></td> <td>The headers of a notification email.</td> <td><code>includes/services/class-notification-service.php:574</code></td> </tr> <tr> <td><code>learnomy_email_subject</code></td> <td>filter</td> <td><code>$subject, $template, $user_id, $data</code></td> <td>The subject of a notification email.</td> <td><code>includes/services/class-notification-service.php:557</code></td> </tr> <tr> <td><code>learnomy_email_template_groups</code></td> <td>filter</td> <td><code>$map</code></td> <td>Filter the email toggle groups.</td> <td><code>includes/services/class-notification-service.php:709</code></td> </tr> <tr> <td><code>learnomy_email_template_types</code></td> <td>filter</td> <td><code>array( 'enrollment' => __( 'Enrollment Welcome', 'learnomy' ), // One email per store g...</code></td> <td>The notification email templates a site owner can customise.</td> <td><code>includes/services/class-notification-service.php:749</code></td> </tr> <tr> <td><code>learnomy_email_to</code></td> <td>filter</td> <td><code>$user->user_email, $template, $user_id, $data</code></td> <td>The recipient address of a notification email.</td> <td><code>includes/services/class-notification-service.php:548</code></td> </tr> <tr> <td><code>learnomy_expo_push_message</code></td> <td>filter</td> <td><code>array( 'to' => $token, 'title' => $title, 'body' => $body, 'sound' => 'default', 'data'...</code></td> <td>Filter one Expo push message before it is sent.</td> <td><code>includes/services/class-expo-push-transport.php:84</code></td> </tr> <tr> <td><code>learnomy_external_enrollment_requested</code></td> <td>action</td> <td><code>$user_id, $course_id, $this->request</code></td> <td>Fires after an incoming webhook has given a buyer access, for add-ons such as xAPI.</td> <td><code>includes/services/class-incoming-purchase-service.php:287</code></td> </tr> <tr> <td><code>learnomy_external_purchase_completed</code></td> <td>action</td> <td><code>$txn_id, $user_id, $type, $ext, $gateway</code></td> <td>Legacy hook that fires after a purchase that is neither a course nor a membership completes.</td> <td><code>includes/services/class-purchase-recorder.php:320</code></td> </tr> <tr> <td><code>learnomy_grading_queue_sources</code></td> <td>filter</td> <td><code>array(), $course_ids, $status, $fetch</code></td> <td>Extra sources of items for the grading queue.</td> <td><code>includes/services/class-grading-service.php:167</code> (2)</td> </tr> <tr> <td><code>learnomy_instructor_courses_reassigned</code></td> <td>action</td> <td><code>$user_id, $target, $count</code></td> <td>Fires after a deleted instructor's courses are reassigned.</td> <td><code>includes/services/class-user-cleanup-service.php:175</code></td> </tr> <tr> <td><code>learnomy_instructor_create_course_url</code></td> <td>filter</td> <td><code>admin_url( 'admin.php?page=learnomy-new-course' )</code></td> <td>The URL of the instructor dashboard create-course link.</td> <td><code>includes/services/view-data/class-instructor-dashboard-view-data.php:185</code> (3)</td> </tr> <tr> <td><code>learnomy_instructor_student_detail</code></td> <td>filter</td> <td><code>$student, $is_admin</code></td> <td>Filter one student's instructor-facing detail record. Companion to.</td> <td><code>includes/services/view-data/class-instructor-students-view-data.php:244</code></td> </tr> <tr> <td><code>learnomy_instructor_students_list</code></td> <td>filter</td> <td><code>$students, $scope_course_ids, null === $scope_course_ids</code></td> <td>Filter the instructor roster rows before render. An extension can.</td> <td><code>includes/services/view-data/class-instructor-students-view-data.php:149</code></td> </tr> <tr> <td><code>learnomy_instructor_suspension_blocks_sources</code></td> <td>filter</td> <td><code>array( 'free' ), $course_id, $user_id</code></td> <td>Enrollment sources a suspended instructor still blocks.</td> <td><code>includes/services/class-enrollment-service.php:224</code></td> </tr> <tr> <td><code>learnomy_lesson_access_requirements</code></td> <td>filter</td> <td><code>array(), $lesson, $course, $user_id</code></td> <td>Filter extra lesson-access requirements layered on top of enrollment.</td> <td><code>includes/services/view-data/class-single-lesson-view-data.php:117</code></td> </tr> <tr> <td><code>learnomy_lesson_attachment_downloaded</code></td> <td>action</td> <td><code>$attachment_id, (int) $row->lesson_id, get_current_user_id()</code></td> <td>Fires immediately before a handout's bytes go out, after the.</td> <td><code>includes/services/class-attachment-download.php:91</code></td> </tr> <tr> <td><code>learnomy_lesson_body_fields</code></td> <td>filter</td> <td><code>array( 'content', 'content_html', 'content_plain', 'video_url', 'media_url' )</code></td> <td>Fields that count as a lesson's renderable body.</td> <td><code>includes/services/class-lesson-service.php:507</code></td> </tr> <tr> <td><code>learnomy_lesson_comments_enabled</code></td> <td>filter</td> <td><code>$global_lesson_comments, $lesson, $course</code></td> <td>Whether comments are enabled on a lesson in the lesson player.</td> <td><code>includes/services/view-data/class-single-lesson-view-data.php:413</code></td> </tr> <tr> <td><code>learnomy_lesson_completed</code></td> <td>action</td> <td><code>$user_id, $lesson_id, $course_id</code></td> <td></td> <td><code>includes/services/class-progress-service.php:143</code></td> </tr> <tr> <td><code>learnomy_lesson_completion_rules</code></td> <td>filter</td> <td><code>$status, $user_id, $lesson</code></td> <td>A lesson's completion status and requirements for a learner.</td> <td><code>includes/services/class-progress-service.php:542</code></td> </tr> <tr> <td><code>learnomy_lesson_copied</code></td> <td>action</td> <td><code>$new_id, $lesson_id, $course_id</code></td> <td>Fires after a lesson is copied.</td> <td><code>includes/services/class-lesson-service.php:648</code></td> </tr> <tr> <td><code>learnomy_lesson_deleted</code></td> <td>action</td> <td><code>$lesson_id, $course_id</code></td> <td>Fires after a lesson is deleted.</td> <td><code>includes/services/class-lesson-service.php:573</code></td> </tr> <tr> <td><code>learnomy_lesson_locked_reason</code></td> <td>filter</td> <td><code>'', (int) $lesson->id, (int) $user_id, $course</code></td> <td>One sentence telling the viewer how a dateless locked lesson opens.</td> <td><code>includes/services/view-data/class-single-lesson-view-data.php:321</code> (3)</td> </tr> <tr> <td><code>learnomy_lesson_media_served</code></td> <td>action</td> <td><code>$lesson_id, $media_id, get_current_user_id()</code></td> <td>Fires after a lesson's primary media passes its permission check.</td> <td><code>includes/services/class-lesson-media-download.php:65</code></td> </tr> <tr> <td><code>learnomy_lesson_standard_completion</code></td> <td>filter</td> <td><code>null, $user_id, $lesson</code></td> <td>Whether a learner has met the completion rule of a SCORM, cmi5 or LTI lesson.</td> <td><code>includes/services/class-progress-service.php:454</code></td> </tr> <tr> <td><code>learnomy_lesson_unlock_date</code></td> <td>filter</td> <td><code>$unlocks_at, (int) $lesson->id, (int) $user_id, $course</code></td> <td>The date a locked, dripped lesson unlocks for the viewer.</td> <td><code>includes/services/view-data/class-single-lesson-view-data.php:304</code> (2)</td> </tr> <tr> <td><code>learnomy_manual_graded_types</code></td> <td>filter</td> <td><code>array( 'essay' )</code></td> <td>The question types that need manual grading.</td> <td><code>includes/services/class-quiz-service.php:701</code></td> </tr> <tr> <td><code>learnomy_media_protected</code></td> <td>action</td> <td><code>$media_id, $relative</code></td> <td>Fires after a media item's bytes have moved into the protected store.</td> <td><code>includes/services/class-protected-uploads.php:595</code></td> </tr> <tr> <td><code>learnomy_membership_cancelled</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id</code></td> <td>This action is documented in cancel() above.</td> <td><code>includes/services/class-subscription-service.php:828</code> (2)</td> </tr> <tr> <td><code>learnomy_membership_change_plan_in_place</code></td> <td>filter</td> <td><code>false, $sub</code></td> <td>Whether this membership can be switched to another plan in place.</td> <td><code>includes/services/class-subscription-service.php:211</code></td> </tr> <tr> <td><code>learnomy_membership_created</code></td> <td>action</td> <td><code>$subscription_id, $user_id, $plan_id</code></td> <td>Plan-context subscription created.</td> <td><code>includes/services/class-subscription-service.php:403</code></td> </tr> <tr> <td><code>learnomy_membership_expired</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id</code></td> <td>Plan-context subscription expired.</td> <td><code>includes/services/class-subscription-service.php:1806</code></td> </tr> <tr> <td><code>learnomy_membership_has_access</code></td> <td>filter</td> <td><code>$access, $user_id, $course_id, $active_subs</code></td> <td>Let Pro (Spaces, entitlement caps, geographic restrictions) enhance.</td> <td><code>includes/services/class-subscription-service.php:1834</code> (2)</td> </tr> <tr> <td><code>learnomy_membership_manage_actions</code></td> <td>filter</td> <td><code>$actions, $sub</code></td> <td>Filter the action buttons shown on the manage page. Pro adds.</td> <td><code>includes/services/view-data/class-membership-manage-view-data.php:253</code></td> </tr> <tr> <td><code>learnomy_membership_renewed</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id</code></td> <td></td> <td><code>includes/services/class-subscription-service.php:1589</code></td> </tr> <tr> <td><code>learnomy_notification_pref_buckets</code></td> <td>filter</td> <td><code>$map</code></td> <td>Map notification types to learner email-preference buckets. Extensions.</td> <td><code>includes/services/class-notification-service.php:1128</code></td> </tr> <tr> <td><code>learnomy_notifications_always_send</code></td> <td>filter</td> <td><code>self::ALWAYS_SEND, $type</code></td> <td>This filter is documented in module_allows() below.</td> <td><code>includes/services/class-notification-service.php:70</code></td> </tr> <tr> <td><code>learnomy_notifications_async</code></td> <td>filter</td> <td><code>true</code></td> <td>Whether notification delivery is queued through Action Scheduler instead of running inline.</td> <td><code>includes/services/class-notification-service.php:450</code></td> </tr> <tr> <td><code>learnomy_object_integrations</code></td> <td>filter</td> <td><code>array(), $type, $id</code></td> <td>Register a product that can give this object a community or discussion.</td> <td><code>includes/services/class-object-integration-registry.php:93</code></td> </tr> <tr> <td><code>learnomy_payment_completed</code></td> <td>action</td> <td><code>$txn_id, $user_id, $gateway</code></td> <td>Fires after a purchase of any type completes.</td> <td><code>includes/services/class-purchase-recorder.php:330</code></td> </tr> <tr> <td><code>learnomy_payment_refunded</code></td> <td>action</td> <td><code>(int) $original->id, $amount, $provider, $is_full_refund</code></td> <td>Fires after a refund is recorded against a sale.</td> <td><code>includes/services/class-refund-service.php:230</code></td> </tr> <tr> <td><code>learnomy_pre_enroll</code></td> <td>filter</td> <td><code>true, $user_id, $course_id, $source</code></td> <td></td> <td><code>includes/services/class-enrollment-service.php:257</code></td> </tr> <tr> <td><code>learnomy_provision_enrollments</code></td> <td>filter</td> <td><code>array(), $user_id, $context</code></td> <td>Course IDs to auto-enroll a provisioned user into (empty = none).</td> <td><code>includes/services/class-provisioning-service.php:200</code></td> </tr> <tr> <td><code>learnomy_provision_role</code></td> <td>filter</td> <td><code>'lrn_student', $user_id, $context</code></td> <td>The role a newly provisioned user receives. Return '' to skip.</td> <td><code>includes/services/class-provisioning-service.php:179</code></td> </tr> <tr> <td><code>learnomy_purchase_completed</code></td> <td>action</td> <td><code>$txn_id, $user_id, $type, $item_id, $ext, $gateway</code></td> <td>A purchase completed and was recorded. THE canonical fulfilment event.</td> <td><code>includes/services/class-purchase-recorder.php:305</code></td> </tr> <tr> <td><code>learnomy_purchase_enrollment_failed</code></td> <td>action</td> <td><code>$user_id, $course_id, $result, $provider, $context</code></td> <td>Fires when a completed payment did not result in a course enrollment.</td> <td><code>includes/services/class-enrollment-service.php:472</code></td> </tr> <tr> <td><code>learnomy_push_message</code></td> <td>filter</td> <td><code>array( 'token' => $device_token, 'notification' => array( 'title' => $title, 'body' => ...</code></td> <td>Filter the FCM message before it is sent.</td> <td><code>includes/services/class-push-service.php:146</code></td> </tr> <tr> <td><code>learnomy_push_sent</code></td> <td>action</td> <td><code>$token, $title</code></td> <td>Fires after a push notification is delivered to a device.</td> <td><code>includes/services/class-expo-push-transport.php:134</code> (2)</td> </tr> <tr> <td><code>learnomy_quiz_auto_grade_result</code></td> <td>filter</td> <td><code>$result, $attempt_id</code></td> <td>The automatic grading result of a quiz attempt.</td> <td><code>includes/services/class-quiz-service.php:807</code></td> </tr> <tr> <td><code>learnomy_quiz_deleted</code></td> <td>action</td> <td><code>$quiz_id, $course_id</code></td> <td>Fires after a quiz and its attempts, responses and slots are gone.</td> <td><code>includes/services/class-quiz-service.php:526</code></td> </tr> <tr> <td><code>learnomy_quiz_deleting</code></td> <td>action</td> <td><code>$quiz_id, $course_id</code></td> <td>Fires BEFORE a quiz's cascade runs, while its slots, attempts and.</td> <td><code>includes/services/class-quiz-service.php:494</code></td> </tr> <tr> <td><code>learnomy_quiz_failed</code></td> <td>action</td> <td><code>$attempt_id, $user_id, $quiz_id, $score</code></td> <td>Fires when a quiz attempt is finally graded as failed.</td> <td><code>includes/services/class-quiz-service.php:1057</code></td> </tr> <tr> <td><code>learnomy_quiz_graded</code></td> <td>action</td> <td><code>$attempt_id, (int) $attempt->user_id, (int) $attempt->quiz_id</code></td> <td>Fires after the last manual grade is saved and the attempt is finalised as graded.</td> <td><code>includes/services/class-quiz-service.php:1392</code></td> </tr> <tr> <td><code>learnomy_quiz_inherits_lesson_lock</code></td> <td>filter</td> <td><code>true, $quiz, $user_id</code></td> <td>Whether a quiz inherits the lock state of the lesson it is bound to.</td> <td><code>includes/services/class-quiz-service.php:1550</code></td> </tr> <tr> <td><code>learnomy_quiz_pass_score</code></td> <td>filter</td> <td><code>$pass_score, $attempt_id, (int) $attempt->quiz_id</code></td> <td>The pass mark a quiz is graded against, in percent.</td> <td><code>includes/services/class-quiz-service.php:338</code> (3)</td> </tr> <tr> <td><code>learnomy_quiz_passed</code></td> <td>action</td> <td><code>$attempt_id, $user_id, $quiz_id, $score</code></td> <td>Fires when a quiz attempt is finally graded as passed.</td> <td><code>includes/services/class-quiz-service.php:1047</code></td> </tr> <tr> <td><code>learnomy_quiz_question_answered</code></td> <td>action</td> <td><code>$question_id, $response, $is_correct, $attempt_id</code></td> <td>Fires once per answered question, immediately after the response row is.</td> <td><code>includes/services/class-quiz-service.php:295</code></td> </tr> <tr> <td><code>learnomy_quiz_started</code></td> <td>action</td> <td><code>$attempt_id, $user_id, $quiz_id</code></td> <td>Fires after a quiz attempt is started.</td> <td><code>includes/services/class-quiz-service.php:234</code></td> </tr> <tr> <td><code>learnomy_quiz_submitted</code></td> <td>action</td> <td><code>$attempt_id, (int) $attempt->user_id, (int) $attempt->quiz_id</code></td> <td>Fires after a quiz attempt is submitted.</td> <td><code>includes/services/class-quiz-service.php:391</code></td> </tr> <tr> <td><code>learnomy_refund_partial_revocation</code></td> <td>action</td> <td><code>$notice, $original, (int) $refund_id</code></td> <td>A full refund could not fully revoke what was sold.</td> <td><code>includes/services/class-refund-service.php:170</code></td> </tr> <tr> <td><code>learnomy_registration_captcha_enabled</code></td> <td>filter</td> <td><code>$on</code></td> <td>Filter whether the built-in signup captcha runs.</td> <td><code>includes/services/class-registration-captcha.php:83</code></td> </tr> <tr> <td><code>learnomy_review_submitted</code></td> <td>action</td> <td><code>$review_id, $user_id, $course_id</code></td> <td>Fires after a course review is saved.</td> <td><code>includes/services/class-review-service.php:78</code></td> </tr> <tr> <td><code>learnomy_route_conflict_force_ownership</code></td> <td>filter</td> <td><code>false</code></td> <td>Whether Learnomy's rewrite rules should outrank every other plugin's.</td> <td><code>includes/services/class-route-conflicts.php:288</code></td> </tr> <tr> <td><code>learnomy_section_deleted</code></td> <td>action</td> <td><code>$section_id, $course_id</code></td> <td>Fires after a section and everything it owned have been removed.</td> <td><code>includes/services/class-course-service.php:426</code></td> </tr> <tr> <td><code>learnomy_send_notification</code></td> <td>action</td> <td><code>$user_id, $type, $data, \Learnomy\Notifications\Community_Notification_Contract::build(...</code></td> <td>Fires after a notification is created (in-app row + optional email).</td> <td><code>includes/services/class-notification-service.php:312</code></td> </tr> <tr> <td><code>learnomy_sender_email</code></td> <td>filter</td> <td><code>''</code></td> <td>Filter the resolved sender address before WordPress's default is kept.</td> <td><code>includes/services/class-notification-service.php:993</code></td> </tr> <tr> <td><code>learnomy_sender_name</code></td> <td>filter</td> <td><code>''</code></td> <td>Filter the resolved sender name before WordPress's default is kept.</td> <td><code>includes/services/class-notification-service.php:949</code></td> </tr> <tr> <td><code>learnomy_setup_completed</code></td> <td>action</td> <td><code>array( 'base_slug' => (string) ( $stored['base_slug'] ?? 'courses' ), 'currency' => (st...</code></td> <td>Fires when the setup wizard is completed.</td> <td><code>includes/services/class-setup-service.php:75</code></td> </tr> <tr> <td><code>learnomy_should_stop_provider_billing</code></td> <td>filter</td> <td><code>true, $sub</code></td> <td>Whether to tell the gateway to stop billing this subscription.</td> <td><code>includes/services/class-subscription-service.php:990</code></td> </tr> <tr> <td><code>learnomy_store_manage_url</code></td> <td>filter</td> <td><code>(string) $url, $source, $sub</code></td> <td>The store page where a member manages a membership the store bills.</td> <td><code>includes/services/class-subscription-service.php:860</code></td> </tr> <tr> <td><code>learnomy_student_access_restored</code></td> <td>action</td> <td><code>$enrollment_id, (int) $enrollment->user_id, (int) $enrollment->course_id</code></td> <td>Fires when a previously revoked enrolment is given access back.</td> <td><code>includes/services/class-enrollment-service.php:748</code></td> </tr> <tr> <td><code>learnomy_student_enrolled</code></td> <td>action</td> <td><code>(int) $existing->id, $user_id, $course_id, $source, true</code></td> <td></td> <td><code>includes/services/class-enrollment-service.php:391</code> (2)</td> </tr> <tr> <td><code>learnomy_student_unenrolled</code></td> <td>action</td> <td><code>$enrollment_id, (int) $enrollment->user_id, (int) $enrollment->course_id, $access_remains</code></td> <td>Fires after an enrollment row is ended, once per row.</td> <td><code>includes/services/class-enrollment-service.php:606</code></td> </tr> <tr> <td><code>learnomy_subscription_approved</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id, 'plan'</code></td> <td>Fires after an admin approves a pending subscription.</td> <td><code>includes/services/class-subscription-service.php:682</code></td> </tr> <tr> <td><code>learnomy_subscription_cancelled</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id, true, 'plan'</code></td> <td>This action is documented in cancel() above.</td> <td><code>includes/services/class-subscription-service.php:826</code> (2)</td> </tr> <tr> <td><code>learnomy_subscription_created</code></td> <td>action</td> <td><code>$subscription_id, $user_id, $plan_id, 'plan'</code></td> <td>Fires after a plan subscription is created and active.</td> <td><code>includes/services/class-subscription-service.php:390</code> (2)</td> </tr> <tr> <td><code>learnomy_subscription_declined</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id, 'plan'</code></td> <td>Fires after an admin declines a pending subscription.</td> <td><code>includes/services/class-subscription-service.php:933</code></td> </tr> <tr> <td><code>learnomy_subscription_expired</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, $target_id, $context_type</code></td> <td>Fires after a subscription expires and its access is revoked.</td> <td><code>includes/services/class-subscription-service.php:1792</code></td> </tr> <tr> <td><code>learnomy_subscription_past_due</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, $target_id, $failure_reason, $context_type</code></td> <td>Fires after a subscription renewal payment fails and it becomes past due.</td> <td><code>includes/services/class-subscription-service.php:1717</code></td> </tr> <tr> <td><code>learnomy_subscription_paused</code></td> <td>action</td> <td><code>$subscription_id, (int) ( $sub->user_id ?? 0 ), $is_course_sub ? (int) $sub->course_id ...</code></td> <td></td> <td><code>includes/services/class-subscription-service.php:1418</code></td> </tr> <tr> <td><code>learnomy_subscription_pending</code></td> <td>action</td> <td><code>$subscription_id, $user_id, $plan_id, 'plan'</code></td> <td>Fires when a subscription is created and is waiting for admin approval.</td> <td><code>includes/services/class-subscription-service.php:347</code></td> </tr> <tr> <td><code>learnomy_subscription_plan_changed</code></td> <td>action</td> <td><code>$subscription_id, $old_price_id, $new_price_id, $context</code></td> <td>Fires after a subscription's billed price changes. Pro extensions.</td> <td><code>includes/services/class-subscription-service.php:1511</code></td> </tr> <tr> <td><code>learnomy_subscription_renewal_after_end</code></td> <td>action</td> <td><code>(int) $sub->id, (int) $sub->user_id, (string) $sub->status</code></td> <td>Fires when a gateway renewal arrives for a cancelled or expired.</td> <td><code>includes/services/class-subscription-service.php:1654</code></td> </tr> <tr> <td><code>learnomy_subscription_renewed</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, $target_id, $context_type</code></td> <td>Fires after a subscription renews.</td> <td><code>includes/services/class-subscription-service.php:1575</code></td> </tr> <tr> <td><code>learnomy_subscription_resumed</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, $target_id, $context_type</code></td> <td>Fires after a subscription is resumed.</td> <td><code>includes/services/class-subscription-service.php:1316</code></td> </tr> <tr> <td><code>learnomy_subscription_status_labels</code></td> <td>filter</td> <td><code>[ 'pending' => __( 'Awaiting approval', 'learnomy' ), 'trialing' => __( 'In trial', 'le...</code></td> <td>Filter the subscription status → UI label map.</td> <td><code>includes/services/class-subscription-service.php:2353</code></td> </tr> <tr> <td><code>learnomy_subscription_trial_ended</code></td> <td>action</td> <td><code>$subscription_id, (int) $sub->user_id, (int) $sub->plan_id, 'plan'</code></td> <td>Fires after a subscription trial ends and the subscription becomes active.</td> <td><code>includes/services/class-subscription-service.php:612</code></td> </tr> <tr> <td><code>learnomy_suppress_notifications</code></td> <td>filter</td> <td><code>false, 'new_user_account', (int) $user_id, array()</code></td> <td>This filter is documented in includes/services/class-notification-service.php.</td> <td><code>includes/services/class-provisioning-service.php:108</code> (2)</td> </tr> <tr> <td><code>learnomy_tab_switch_auto_submit_limit</code></td> <td>filter</td> <td><code>$limit, $quiz</code></td> <td>Filter the tab-switch auto-submit limit (0 = off), e.g. to vary it.</td> <td><code>includes/services/class-quiz-defaults.php:134</code></td> </tr> <tr> <td><code>learnomy_tab_switch_flag_threshold</code></td> <td>filter</td> <td><code>3, $attempt, $quiz</code></td> <td>The number of tab switches at which a quiz attempt is flagged.</td> <td><code>includes/services/class-grading-service.php:422</code></td> </tr> <tr> <td><code>learnomy_thank_you_polling_limit_seconds</code></td> <td>filter</td> <td><code>90</code></td> <td>Seconds the thank-you page keeps checking before it tells the buyer the payment is not confirmed.</td> <td><code>includes/services/view-data/class-checkout-thank-you-view-data.php:566</code></td> </tr> <tr> <td><code>learnomy_thank_you_polling_seconds</code></td> <td>filter</td> <td><code>3</code></td> <td>Seconds between status checks on the thank-you page while a payment is still pending.</td> <td><code>includes/services/view-data/class-checkout-thank-you-view-data.php:541</code></td> </tr> <tr> <td><code>learnomy_update_payment_hint</code></td> <td>filter</td> <td><code>$link['hint'], $sub</code></td> <td>The URL where a member updates the payment method of a subscription.</td> <td><code>includes/services/view-data/class-membership-manage-view-data.php:164</code></td> </tr> <tr> <td><code>learnomy_update_payment_url</code></td> <td>filter</td> <td><code>$link['url'], $sub</code></td> <td>The URL where a member updates the payment method of a subscription.</td> <td><code>includes/services/view-data/class-membership-manage-view-data.php:157</code></td> </tr> <tr> <td><code>learnomy_user_data_purged</code></td> <td>action</td> <td><code>$user_id, $summary</code></td> <td>Fires after a user's Learnomy data is purged.</td> <td><code>includes/services/class-user-cleanup-service.php:379</code></td> </tr> <tr> <td><code>learnomy_user_provisioned</code></td> <td>action</td> <td><code>(int) $user_id, array_merge( array( 'source' => 'ensure_user_by_email' ), $args )</code></td> <td>Fires after an account is created for a buyer who had none, so role and enrollment listeners can run.</td> <td><code>includes/services/class-provisioning-service.php:119</code> (2)</td> </tr> <tr> <td><code>learnomy_validate_enrollment_source</code></td> <td>filter</td> <td><code>$unclaimed, $source, $user_id, $course_id, $access_type</code></td> <td>Lets an extension validate an enrollment source Learnomy does not recognise.</td> <td><code>includes/services/class-enrollment-service.php:1200</code></td> </tr> <tr> <td><code>learnomy_video_max_playback_rate</code></td> <td>filter</td> <td><code>2.0, $lesson</code></td> <td>Fastest playback rate a student could plausibly have used. The bundled.</td> <td><code>includes/services/class-progress-service.php:886</code></td> </tr> <tr> <td><code>learnomy_video_watch_ceiling_pct</code></td> <td>filter</td> <td><code>$ceiling, $lesson, $progress_row</code></td> <td>Last word on the watch ceiling. The escape hatch for a site whose.</td> <td><code>includes/services/class-progress-service.php:902</code></td> </tr> <tr> <td><code>learnomy_webhook_event_map</code></td> <td>filter</td> <td><code>$map</code></td> <td>Filter the outbound webhook event catalogue.</td> <td><code>includes/services/class-webhook-events.php:163</code></td> </tr> <tr> <td><code>learnomy_webhooks_core_dispatch_enabled</code></td> <td>filter</td> <td><code>true</code></td> <td>Whether the core (Free) webhook dispatcher should wire itself to.</td> <td><code>includes/services/class-webhook-events.php:246</code></td> </tr> <tr> <td><code>learnomy_withdrawal_requested</code></td> <td>action</td> <td><code>$withdrawal_id, $instructor_id, $settled</code></td> <td>Fires after an instructor withdrawal is requested.</td> <td><code>includes/services/class-commission-service.php:972</code></td> </tr> </tbody></table></div> <h2 id="templates">Templates<a class="heading-anchor" href="#templates" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_account_billing_rendered</code></td> <td>action</td> <td><code>get_current_user_id()</code></td> <td>Fires after the billing page renders. Pro extensions hook here for.</td> <td><code>templates/account-billing.php:368</code></td> </tr> <tr> <td><code>learnomy_account_fields</code></td> <td>action</td> <td><code>0, 'registration_instructor'</code></td> <td>Fires in the instructor registration form to render extra fields.</td> <td><code>templates/register-instructor.php:229</code> (4)</td> </tr> <tr> <td><code>learnomy_account_nav_sections</code></td> <td>filter</td> <td><code>array( 'learning' => __( 'Learning', 'learnomy' ), 'account' => __( 'Account', 'learnom...</code></td> <td>Filter the account-nav sections - ordered section-key => label. Drives both.</td> <td><code>templates/partials/account-nav.php:59</code></td> </tr> <tr> <td><code>learnomy_cancelled_rendered</code></td> <td>action</td> <td><code>$course_id, $plan_id</code></td> <td>Fires after the cancelled page has rendered. Pro extensions can hook.</td> <td><code>templates/checkout-cancelled.php:91</code></td> </tr> <tr> <td><code>learnomy_catalog_access_notices</code></td> <td>filter</td> <td><code>array( 'not_your_course' => sprintf( /* translators: 1: singular Course label, 2: singu...</code></td> <td>The notices the catalog shows for each access reason.</td> <td><code>templates/catalog/partials/access-notice.php:28</code></td> </tr> <tr> <td><code>learnomy_catalog_filter_facets</code></td> <td>action</td> <td><code>$current_cat</code></td> <td>Hookable facet region in the catalog sidebar. Extensions (or Pro).</td> <td><code>templates/catalog/sidebar.php:140</code></td> </tr> <tr> <td><code>learnomy_certificate_verify_after</code></td> <td>action</td> <td><code>$certificate</code></td> <td>Fires after the verified certificate result block. Extensions use.</td> <td><code>templates/certificate-verify.php:246</code></td> </tr> <tr> <td><code>learnomy_certificate_verify_head</code></td> <td>action</td> <td><code>$certificate</code></td> <td>Fires in the verify page head region for a valid certificate.</td> <td><code>templates/certificate-verify.php:51</code></td> </tr> <tr> <td><code>learnomy_certificate_verify_revoked</code></td> <td>action</td> <td><code>$certificate</code></td> <td>Fires inside the revoked certificate result block. Extensions use.</td> <td><code>templates/certificate-verify.php:291</code></td> </tr> <tr> <td><code>learnomy_closed_cta</code></td> <td>filter</td> <td><code>$lrn_closed_html, $course, get_current_user_id()</code></td> <td>Override the closed-course CTA HTML.</td> <td><code>templates/course/partials/enroll-card.php:292</code></td> </tr> <tr> <td><code>learnomy_course_after_content</code></td> <td>action</td> <td><code>$course</code></td> <td>Placement region below the course body.</td> <td><code>templates/course/hero.php:191</code> (4)</td> </tr> <tr> <td><code>learnomy_course_before_content</code></td> <td>action</td> <td><code>$course</code></td> <td>Placement region above the course body (sponsor / CTA / related).</td> <td><code>templates/course/hero.php:165</code> (4)</td> </tr> <tr> <td><code>learnomy_course_card_badges</code></td> <td>action</td> <td><code>$course</code></td> <td>Fires inside the course card badge row so Surface A (sales.</td> <td><code>templates/partials/course-card.php:239</code></td> </tr> <tr> <td><code>learnomy_course_card_meta</code></td> <td>action</td> <td><code>$course</code></td> <td>Per-card taxonomy / meta slot. Catalog Facets framework subscribers.</td> <td><code>templates/partials/course-card.php:253</code></td> </tr> <tr> <td><code>learnomy_course_comments_enabled</code></td> <td>filter</td> <td><code>$course_comments_on && $site_comments_on, $course</code></td> <td>Whether the course comments section is shown.</td> <td><code>templates/course/partials/body.php:241</code></td> </tr> <tr> <td><code>learnomy_course_enrolled_after_title</code></td> <td>action</td> <td><code>$course</code></td> <td>Under the title of the enrolled course page, so an addition opens the page.</td> <td><code>templates/course/partials/body.php:102</code></td> </tr> <tr> <td><code>learnomy_course_qa_section</code></td> <td>action</td> <td><code>$course</code></td> <td>Fires inside the course sales page Q&A section when.</td> <td><code>templates/course/partials/body.php:449</code></td> </tr> <tr> <td><code>learnomy_course_sidebar_bottom</code></td> <td>action</td> <td><code>$course</code></td> <td>Bottom of the course sidebar.</td> <td><code>templates/course/classic.php:119</code> (2)</td> </tr> <tr> <td><code>learnomy_course_sidebar_card_footer</code></td> <td>action</td> <td><code>$course</code></td> <td>Fires at the bottom of the single-course sidebar card, after the enrol/manage.</td> <td><code>templates/course/partials/enroll-card.php:682</code></td> </tr> <tr> <td><code>learnomy_course_sidebar_top</code></td> <td>action</td> <td><code>$course</code></td> <td>Top of the course sidebar (sponsor / CTA / related). Fires on every.</td> <td><code>templates/course/classic.php:106</code> (2)</td> </tr> <tr> <td><code>learnomy_dashboard_tab_buttons</code></td> <td>action</td> <td></td> <td>Legacy extension point - kept for modules that registered tabs.</td> <td><code>templates/dashboard-widgets/student/enrollments.php:97</code></td> </tr> <tr> <td><code>learnomy_dashboard_tab_panels</code></td> <td>action</td> <td></td> <td>Legacy panel extension point for modules registered against.</td> <td><code>templates/dashboard-widgets/student/enrollments.php:224</code></td> </tr> <tr> <td><code>learnomy_instructor_manage_courses_url</code></td> <td>filter</td> <td><code>admin_url( 'admin.php?page=learnomy-courses' )</code></td> <td>The URL of the manage-all link in the My Courses widget.</td> <td><code>templates/dashboard-widgets/instructor/my-courses.php:78</code></td> </tr> <tr> <td><code>learnomy_instructor_payout_setup</code></td> <td>action</td> <td><code>get_current_user_id()</code></td> <td>Payout-account setup slot. A payout integration (Pro Stripe Connect) renders.</td> <td><code>templates/dashboard-widgets/instructor/earnings.php:61</code></td> </tr> <tr> <td><code>learnomy_instructor_sections</code></td> <td>filter</td> <td><code>$lrn_sections</code></td> <td>Filter the instructor rail sections so a Pro extension can register its own.</td> <td><code>templates/instructor-section.php:68</code></td> </tr> <tr> <td><code>learnomy_instructor_withdraw_block_reason</code></td> <td>filter</td> <td><code>'', get_current_user_id()</code></td> <td>A reason that blocks the instructor from requesting a withdrawal.</td> <td><code>templates/dashboard-widgets/instructor/earnings.php:24</code></td> </tr> <tr> <td><code>learnomy_invoice_pdf_url</code></td> <td>filter</td> <td><code>$default_pdf_url, $invoice</code></td> <td></td> <td><code>templates/partials/membership-invoice-row.php:60</code></td> </tr> <tr> <td><code>learnomy_lesson_access_gate</code></td> <td>filter</td> <td><code>$lrn_gate, $lesson, $course, get_current_user_id()</code></td> <td>Filter the lesson access-gate copy (title / message / cta_label / cta_url).</td> <td><code>templates/lesson/focus.php:85</code> (2)</td> </tr> <tr> <td><code>learnomy_lesson_after_content</code></td> <td>action</td> <td><code>$lesson, $course</code></td> <td>Fires after the embedded lesson layout is rendered.</td> <td><code>templates/lesson/embedded.php:241</code> (2)</td> </tr> <tr> <td><code>learnomy_lesson_before_content</code></td> <td>action</td> <td><code>$lesson, $course</code></td> <td>Placement region above the lesson content (admin edit bar, sponsor, etc.).</td> <td><code>templates/lesson/focus.php:213</code> (2)</td> </tr> <tr> <td><code>learnomy_lesson_live_post_actions</code></td> <td>action</td> <td><code>$lesson, $course</code></td> <td>Fires in the notice shown for a finished live session, to add a recording or contact link.</td> <td><code>templates/lesson/partials/media.php:376</code></td> </tr> <tr> <td><code>learnomy_lesson_pause</code></td> <td>action</td> <td><code>$lesson</code></td> <td>Surface C - pause overlay. Always rendered, but hidden; the JS.</td> <td><code>templates/lesson/embedded.php:271</code></td> </tr> <tr> <td><code>learnomy_lesson_player_aside</code></td> <td>action</td> <td><code>$lesson, $is_enrolled</code></td> <td>Allow Pro modules to render auxiliary tools alongside the lesson.</td> <td><code>templates/lesson/embedded.php:365</code> (2)</td> </tr> <tr> <td><code>learnomy_lesson_render_content</code></td> <td>action</td> <td><code>$content_type, $lesson, $media_url</code></td> <td>Fires to render the player of a lesson content type registered by an extension.</td> <td><code>templates/lesson/partials/media.php:408</code></td> </tr> <tr> <td><code>learnomy_lesson_sidebar_bottom</code></td> <td>action</td> <td><code>$lesson, $course</code></td> <td>Bottom of the lesson curriculum sidebar.</td> <td><code>templates/lesson/embedded.php:625</code> (2)</td> </tr> <tr> <td><code>learnomy_lesson_sidebar_top</code></td> <td>action</td> <td><code>$lesson, $course</code></td> <td>Top of the lesson curriculum sidebar (e.g. resume CTA).</td> <td><code>templates/lesson/embedded.php:499</code> (2)</td> </tr> <tr> <td><code>learnomy_membership_manage_extra_sections</code></td> <td>action</td> <td><code>$sub</code></td> <td>Fires after the primary action row but before the invoices.</td> <td><code>templates/membership-manage.php:477</code></td> </tr> <tr> <td><code>learnomy_pricing_before_faq</code></td> <td>action</td> <td></td> <td>Fires after the plan grid + social proof but BEFORE the FAQ. Pro.</td> <td><code>templates/membership-pricing.php:119</code></td> </tr> <tr> <td><code>learnomy_pricing_page_footer</code></td> <td>action</td> <td></td> <td>Fires below the FAQ block. Pro uses it to inject a money-back.</td> <td><code>templates/membership-pricing.php:157</code></td> </tr> <tr> <td><code>learnomy_pricing_page_header</code></td> <td>action</td> <td></td> <td>Fires above the plan grid. Pro uses it to inject a trust-badges.</td> <td><code>templates/membership-pricing.php:90</code></td> </tr> <tr> <td><code>learnomy_pricing_plan_extras</code></td> <td>action</td> <td><code>$plan</code></td> <td>Hook inside each pricing card so Pro can inject entitlement badges.</td> <td><code>templates/partials/membership-plan-card.php:324</code></td> </tr> <tr> <td><code>learnomy_pricing_social_proof</code></td> <td>action</td> <td></td> <td></td> <td><code>templates/membership-pricing.php:105</code></td> </tr> <tr> <td><code>learnomy_quiz_before_content</code></td> <td>action</td> <td><code>$quiz</code></td> <td>In-content edit affordance, mirroring the course/lesson before-content hooks.</td> <td><code>templates/single-quiz.php:182</code></td> </tr> <tr> <td><code>learnomy_quiz_templates</code></td> <td>filter</td> <td><code>[ 'focused', 'classic', 'conversational', 'sectioned', 'review-board', ]</code></td> <td>The quiz display templates a quiz may use.</td> <td><code>templates/single-quiz.php:149</code></td> </tr> <tr> <td><code>learnomy_registration_challenge</code></td> <td>action</td> <td><code>'registration_instructor'</code></td> <td>Render an owner-supplied signup challenge (CAPTCHA widget,.</td> <td><code>templates/register-instructor.php:245</code> (2)</td> </tr> <tr> <td><code>learnomy_render_course_comments</code></td> <td>action</td> <td><code>(int) $course->id, $course</code></td> <td>Fires on the course page where the comments section is rendered.</td> <td><code>templates/course/partials/body.php:261</code></td> </tr> <tr> <td><code>learnomy_show_instructor_earnings</code></td> <td>filter</td> <td><code>\Learnomy\Services\Commission_Service::instructor_participates_in_revenue( get_current_...</code></td> <td>Whether the instructor dashboard shows the revenue stat for this instructor.</td> <td><code>templates/instructor-dashboard.php:160</code> (2)</td> </tr> <tr> <td><code>learnomy_thank_you_rendered</code></td> <td>action</td> <td><code>$transaction, get_current_user_id()</code></td> <td>Fires after the thank-you page has rendered. Pro analytics modules.</td> <td><code>templates/checkout-thank-you.php:355</code></td> </tr> </tbody></table></div> <h2 id="widgets">Widgets<a class="heading-anchor" href="#widgets" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <div class="docs-table-scroll" role="region" aria-label="Scrollable table" tabindex="0" style="overflow-x:auto;max-width:100%"><table> <thead> <tr> <th>Hook</th> <th>Type</th> <th>Arguments</th> <th>What it is for</th> <th>Fired in</th> </tr> </thead> <tbody><tr> <td><code>learnomy_progress_widget_max</code></td> <td>filter</td> <td><code>10</code></td> <td>The most in-progress courses the Course Progress widget lists.</td> <td><code>includes/widgets/class-course-progress-widget.php:73</code></td> </tr> <tr> <td><code>learnomy_widget_output</code></td> <td>filter</td> <td><code>$output, $args, $instance, $this->id_base</code></td> <td>The rendered HTML of the instructor widget.</td> <td><code>includes/widgets/class-instructor-widget.php:59</code> (10)</td> </tr> </tbody></table></div> <h2 id="related">Related<a class="heading-anchor" href="#related" aria-label="Link to this section" data-pagefind-ignore>#</a></h2> <ul> <li><a href="/docs/developer-guide/">Developer Guide</a></li> <li><a href="/docs/developer-guide/template-overrides/">Template Overrides</a></li> <li><a href="/docs/integrations/rest-api-and-app/">REST API and App</a></li> </ul> </div> <div class="lg:hidden mt-12 pt-8 border-t border-slate-200" data-pagefind-ignore> <nav class="text-sm" aria-label="Documentation" data-docnav> <div class="docnav__search" data-pagefind-ignore><div class="docsearch docsearch--sidebar" data-docsearch data-astro-cid-uufp3sb6> <label class="docsearch__field" for="ds-sidebar-input" data-astro-cid-uufp3sb6> <svg class="docsearch__icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-astro-cid-uufp3sb6><circle cx="11" cy="11" r="7" data-astro-cid-uufp3sb6></circle><path d="m20 20-3.5-3.5" data-astro-cid-uufp3sb6></path></svg> <span class="visually-hidden" data-astro-cid-uufp3sb6>Search documentation</span> <input id="ds-sidebar-input" type="search" class="docsearch__input" placeholder="Search docs" autocomplete="off" spellcheck="false" enterkeyhint="search" role="combobox" aria-expanded="false" aria-controls="ds-sidebar-list" aria-autocomplete="list" data-docsearch-input data-astro-cid-uufp3sb6> </label> <div class="docsearch__panel" id="ds-sidebar-list" role="listbox" aria-label="Search results" data-docsearch-panel hidden data-astro-cid-uufp3sb6></div> <p class="visually-hidden" role="status" aria-live="polite" data-docsearch-status data-astro-cid-uufp3sb6></p> </div> </div> <a href="/docs/" class="block font-semibold mb-2 text-slate-900 hover:text-brand"> Documentation home </a> <a href="/videos/" class="inline-flex items-center gap-1.5 mb-4 text-brand font-medium hover:underline"> <svg class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M10 8.64v6.72L15.27 12 10 8.64zM12 2a10 10 0 100 20 10 10 0 000-20z"></path></svg> Video library </a> <ul class="space-y-1 m-0 p-0 list-none"> <li> <details class="docnav__cat"> <summary class="docnav__summary">Getting Started</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/getting-started/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/getting-started/introduction/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Introduction to Learnomy </a> </li><li> <a href="/docs/getting-started/installation-activation/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Installation and Activation </a> </li><li> <a href="/docs/getting-started/setup-wizard/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Setup Wizard </a> </li><li> <a href="/docs/getting-started/launch-your-academy/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Launch Your Academy </a> </li><li> <a href="/docs/getting-started/admin-tour/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Admin Tour </a> </li><li> <a href="/docs/getting-started/admin-dashboard/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Admin Dashboard </a> </li><li> <a href="/docs/getting-started/enabling-features-modules/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Enabling Features and Modules </a> </li><li> <a href="/docs/getting-started/roles-and-capabilities/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Roles and Capabilities </a> </li><li> <a href="/docs/getting-started/pro-licence/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Your Pro Licence <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/getting-started/migrating-from-another-lms/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Migrating from Another LMS </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Courses and Content</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/courses/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/courses/creating-a-course/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Creating a Course </a> </li><li> <a href="/docs/courses/sections-and-lessons/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Sections and Lessons </a> </li><li> <a href="/docs/courses/lesson-content-types/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Lesson Content Types </a> </li><li> <a href="/docs/courses/embedding-video-and-content/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Embedding Video and External Content </a> </li><li> <a href="/docs/courses/course-completion-rules/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Completion Rules </a> </li><li> <a href="/docs/courses/course-prerequisites/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Prerequisites </a> </li><li> <a href="/docs/courses/course-difficulty-target-audience/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Difficulty and Target Audience </a> </li><li> <a href="/docs/courses/categories-and-tags/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Categories and Tags </a> </li><li> <a href="/docs/courses/pricing-and-access-models/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Pricing and Access Models </a> </li><li> <a href="/docs/courses/closed-pricing-model/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Closed Course Pricing </a> </li><li> <a href="/docs/courses/access-and-enrollment/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Access and Enrollment </a> </li><li> <a href="/docs/courses/invite-only-courses/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Invite-Only Courses </a> </li><li> <a href="/docs/courses/bulk-enrollment/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Bulk Enroll from a List </a> </li><li> <a href="/docs/courses/incoming-webhooks-external-enrollment/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Incoming Access Webhook </a> </li><li> <a href="/docs/courses/content-drip/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Content Drip <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/courses/course-catalog/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Catalog </a> </li><li> <a href="/docs/courses/course-reviews/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Reviews </a> </li><li> <a href="/docs/courses/course-seo-and-sharing/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course SEO and Sharing </a> </li><li> <a href="/docs/courses/blocks-shortcodes-widgets/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Blocks, Shortcodes and Widgets </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Quizzes and Grading</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/quizzes/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/quizzes/building-a-quiz/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Building a Quiz </a> </li><li> <a href="/docs/quizzes/question-types/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Question Types </a> </li><li> <a href="/docs/quizzes/rich-question-stems/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Rich Question Stems </a> </li><li> <a href="/docs/quizzes/question-bank/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Question Bank </a> </li><li> <a href="/docs/quizzes/group-by-category/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Group Questions by Subject </a> </li><li> <a href="/docs/quizzes/question-pools-and-timers/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Question Pools and Per-Question Timers <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/quizzes/quiz-modes/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Quiz Modes </a> </li><li> <a href="/docs/quizzes/taking-a-quiz/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Taking a Quiz </a> </li><li> <a href="/docs/quizzes/autosave-and-resume/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Large-exam Autosave and Resume </a> </li><li> <a href="/docs/quizzes/large-exam-map-and-flags/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Question Map and Flag for Review </a> </li><li> <a href="/docs/quizzes/grading-submissions/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Grading Submissions </a> </li><li> <a href="/docs/quizzes/exam-integrity/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Exam integrity signals </a> </li><li> <a href="/docs/quizzes/proctoring/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Quiz Proctoring </a> </li><li> <a href="/docs/quizzes/layouts/focused/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Focused </a> </li><li> <a href="/docs/quizzes/layouts/classic/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Classic </a> </li><li> <a href="/docs/quizzes/layouts/sectioned/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Sectioned exam layout <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/quizzes/layouts/conversational/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Conversational quiz layout <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/quizzes/layouts/review-board/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Review board exam layout <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Certificates</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/certificates/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/certificates/certificate-templates/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Certificate Templates </a> </li><li> <a href="/docs/certificates/issuing-and-verifying/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Issuing and Verifying Certificates </a> </li><li> <a href="/docs/certificates/download-and-print/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Download and Print a Certificate </a> </li><li> <a href="/docs/certificates/sharing-and-linkedin/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Share a Certificate on LinkedIn </a> </li><li> <a href="/docs/certificates/open-badges/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Open Badges <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/certificates/credly-integration/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Credly Integration <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/certificates/blockchain-verification/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Certificate Hash Verification <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">The Student Experience</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/students/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/students/student-account/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Student Account Hub </a> </li><li> <a href="/docs/students/taking-a-course/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Taking a Course </a> </li><li> <a href="/docs/students/notes-and-bookmarks/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Notes and Bookmarks <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/students/wishlist/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Wishlist </a> </li><li> <a href="/docs/students/course-search-autocomplete/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Search Autocomplete </a> </li><li> <a href="/docs/students/notifications/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Notifications </a> </li><li> <a href="/docs/students/certificates-and-billing/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Certificates and Billing </a> </li><li> <a href="/docs/students/managing-students/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Managing Students (Admin) </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Instructors and Earnings</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/instructors/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/instructors/becoming-an-instructor/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Becoming an Instructor </a> </li><li> <a href="/docs/instructors/instructor-dashboard/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Instructor Dashboard </a> </li><li> <a href="/docs/instructors/instructor-public-profile/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Instructor Public Profile </a> </li><li> <a href="/docs/instructors/instructor-students-roster/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Instructor Students Roster </a> </li><li> <a href="/docs/instructors/course-approval-workflow/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Approval Workflow </a> </li><li> <a href="/docs/instructors/commissions-and-earnings/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Commissions and Earnings </a> </li><li> <a href="/docs/instructors/stripe-connect-payouts/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Stripe Connect Payouts (Pro) <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/instructors/managing-instructors/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Managing Instructors </a> </li><li> <a href="/docs/instructors/solo-academy-mode/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Solo Academy Mode </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Commerce</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/commerce/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/commerce/commerce-overview/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Commerce Overview </a> </li><li> <a href="/docs/commerce/ways-to-make-money/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Ways to Make Money </a> </li><li> <a href="/docs/commerce/payment-gateways/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Payment Gateways </a> </li><li> <a href="/docs/commerce/checkout-and-purchase-flow/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Checkout and Purchase Flow </a> </li><li> <a href="/docs/commerce/coupons/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Coupons </a> </li><li> <a href="/docs/commerce/tax/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Tax (Flat Rate) </a> </li><li> <a href="/docs/commerce/memberships/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Membership Plans </a> </li><li> <a href="/docs/commerce/subscriptions/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Subscriptions </a> </li><li> <a href="/docs/commerce/subscription-lifecycle-pro/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Subscription Lifecycle: Pauses, Plan Changes, Dunning and Refunds <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/commerce/gift-codes/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Gift Codes and Team Seats <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/commerce/transactions/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Transactions </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Settings</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/settings/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/settings/settings-overview/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Settings Overview </a> </li><li> <a href="/docs/settings/general-settings/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> General Settings </a> </li><li> <a href="/docs/settings/pages-and-urls/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Pages and URL Slugs </a> </li><li> <a href="/docs/settings/layouts/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Layouts </a> </li><li> <a href="/docs/settings/labels/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Custom Labels </a> </li><li> <a href="/docs/settings/comments/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Comment Settings </a> </li><li> <a href="/docs/settings/reviews/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Course Reviews </a> </li><li> <a href="/docs/settings/custom-account-fields/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Custom Account Fields </a> </li><li> <a href="/docs/settings/emails-and-announcements/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Emails and Announcements </a> </li><li> <a href="/docs/settings/content-moderation/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Content Moderation </a> </li><li> <a href="/docs/settings/data-management/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Data Management </a> </li><li> <a href="/docs/settings/api-keys/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> API Keys </a> </li><li> <a href="/docs/settings/api-and-performance/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> API and Performance </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Integrations</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/integrations/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/integrations/community-companions/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Community Companions (BuddyNext and Jetonomy) </a> </li><li> <a href="/docs/integrations/wp-fusion/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> WP Fusion <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/woocommerce-store-bridge/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Sell Learnomy access with WooCommerce products <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/edd-store-bridge/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Sell Learnomy access with Easy Digital Downloads <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/rcp-store-bridge/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Give Learnomy access with Restrict Content Pro levels <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/paid-memberships-pro-bridge/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Give Learnomy access with Paid Memberships Pro levels <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/memberpress-bridge/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Give Learnomy access with MemberPress memberships <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/elementor-theme-builder/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Elementor Theme Builder <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/seo-plugin-handoff/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> SEO Plugin Handoff </a> </li><li> <a href="/docs/integrations/h5p-interactive-content/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> H5P Interactive Content <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/scorm-packages/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> SCORM Packages <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/xapi-learning-records/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> xAPI (Tin Can) Learning Records <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/lti-tool-provider/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> LTI 1.3 Tool Provider <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/qti-assessment-import/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> QTI Assessment Import <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/rest-api-and-app/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> REST API and App </a> </li><li> <a href="/docs/integrations/pwa-offline-mode/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> PWA and Offline Mode </a> </li><li> <a href="/docs/integrations/ai-agents-abilities-api/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> AI Agents and the Abilities API </a> </li><li> <a href="/docs/integrations/outgoing-webhooks/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Outgoing Webhooks </a> </li><li> <a href="/docs/integrations/webhook-events/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Webhook Events and Payloads <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/webhook-delivery-log/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Webhook Delivery Log <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/integrations/incoming-webhook-events/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Incoming Payment Webhook Log </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Reporting</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/reporting/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/reporting/analytics/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Analytics Dashboard <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/reporting/gradebook/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Gradebook <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/reporting/quiz-statistics/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Quiz Statistics Report </a> </li><li> <a href="/docs/reporting/quiz-category-breakdown/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Subject-wise Quiz Score Breakdown </a> </li><li> <a href="/docs/reporting/instructor-reports/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Instructor Reports <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/reporting/membership-analytics/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Membership Analytics <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/reporting/data-exports/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Data Exports (CSV) </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Pro Tools</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/pro-tools/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/pro-tools/pro-tools-overview/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Pro Tools Overview <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/frontend-builder/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Frontend Course Builder <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/assignments/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Assignments <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/advanced-quizzes/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Advanced Quiz Types <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/learning-paths/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Learning Paths <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/cohorts/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Cohorts <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/user-journeys/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> User Journeys <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/spaces/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Spaces <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/space-groups/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Space Groups <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/ai-authoring/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> AI Authoring <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/pro-tools/white-label/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> White Label <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li> </ul> </details> </li><li> <details class="docnav__cat" open> <summary class="docnav__summary">Developer Guide</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/developer-guide/" class="block -ml-px pl-4 py-1 border-l-2 border-transparent text-slate-500 hover:text-slate-900 hover:border-slate-300">Overview</a> </li> <li> <a href="/docs/developer-guide/hooks-reference/" aria-current="page" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-brand text-brand font-medium"> Hooks Reference </a> </li><li> <a href="/docs/developer-guide/hooks-reference-pro/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Hooks Reference (Pro) <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li><li> <a href="/docs/developer-guide/background-jobs/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Background Jobs </a> </li><li> <a href="/docs/developer-guide/wp-cli-commands/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> WP-CLI Commands </a> </li><li> <a href="/docs/developer-guide/registration-security/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Registration and Login Security </a> </li><li> <a href="/docs/developer-guide/payment-gateways/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Payment Gateways and Purchase Sources </a> </li><li> <a href="/docs/developer-guide/store-bridges/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Store bridges for developers <span class="ml-1 align-middle inline-block rounded bg-brand/10 text-brand text-[10px] font-semibold px-1.5 py-0.5">PRO</span> </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">FAQ</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/faq/faq/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Frequently Asked Questions </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">Troubleshooting</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/troubleshooting/troubleshooting/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Troubleshooting </a> </li><li> <a href="/docs/troubleshooting/admin-notices/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> Admin Notices Explained </a> </li> </ul> </details> </li><li> <details class="docnav__cat"> <summary class="docnav__summary">What's New</summary> <ul class="space-y-1 m-0 mt-1 p-0 list-none border-l border-slate-200"> <li> <a href="/docs/whats-new/whats-new-in-2-1-5/" class="block -ml-px pl-4 py-1 border-l-2 leading-snug transition-colors border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300"> What's New in 2.1.5 </a> </li> </ul> </details> </li> </ul> </nav> </div> </article> </div> </main> <script type="module">const e=document.querySelector("[data-tps]"),c=e?Array.from(e.querySelectorAll("[data-tps-slide]")):[];if(e&&c.length>1){const o=e.querySelector("[data-tps-current]"),l=window.matchMedia("(prefers-reduced-motion: reduce)").matches;let t=0,d,i=!1,n=!1;const a=s=>{t=(s+c.length)%c.length,c.forEach((u,v)=>u.hidden=v!==t),o&&(o.textContent=String(t+1))},r=()=>{clearInterval(d),!l&&i&&!n&&(d=window.setInterval(()=>a(t+1),7e3))};e.querySelector("[data-tps-prev]")?.addEventListener("click",()=>a(t-1)),e.querySelector("[data-tps-next]")?.addEventListener("click",()=>a(t+1)),e.addEventListener("mouseenter",()=>{n=!0,r()}),e.addEventListener("mouseleave",()=>{n=e.contains(document.activeElement),r()}),e.addEventListener("focusin",()=>{n=!0,r()}),e.addEventListener("focusout",s=>{n=e.contains(s.relatedTarget)||e.matches(":hover"),r()}),new IntersectionObserver(([s])=>{i=s.isIntersecting,r()}).observe(e)}</script> <footer class="border-t border-slate-200 bg-slate-50"> <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-10 lg:py-14"> <div class="mb-12 rounded-2xl ring-1 ring-slate-200 bg-white p-6 lg:p-8 flex flex-col lg:flex-row lg:items-center gap-6"> <div class="lg:flex-1"> <p class="eyebrow text-brand mb-1">Newsletter</p> <h2 class="text-lg font-bold text-slate-900 tracking-tight leading-snug">Build your academy on WordPress</h2> <p class="text-sm text-slate-600 leading-relaxed mt-1">One short email when something worth reading lands - LMS tutorials, course-selling tips, and Learnomy updates.</p> </div> <form action="/api/newsletter/" method="POST" class="flex flex-col sm:flex-row gap-2 w-full lg:w-auto" data-source="footer"> <input type="hidden" name="source" value="footer"> <label class="sr-only" for="news-email-footer">Email</label> <input type="email" name="email" id="news-email-footer" required placeholder="you@example.com" autocomplete="email" class="flex-1 lg:w-72 rounded-lg ring-1 ring-slate-300 bg-white px-4 py-2.5 text-sm text-slate-900 placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-brand transition"> <button type="submit" class="inline-flex items-center justify-center rounded-lg bg-brand hover:bg-brand-dark text-white px-6 py-2.5 text-sm font-semibold transition-colors shadow-sm whitespace-nowrap">Subscribe</button> </form> </div> <div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-8 lg:gap-8"> <div> <h2 class="text-xs font-mono uppercase tracking-wider text-slate-500 mb-4"> Features </h2> <ul class="space-y-2"> <li> <a href="/courses/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Course builder </a> </li><li> <a href="/quizzes/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Quizzes & grading </a> </li><li> <a href="/certificates/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Certificates </a> </li><li> <a href="/payments/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Payments & memberships </a> </li><li> <a href="/ways-to-make-money/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Ways to make money </a> </li><li> <a href="/instructors/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Instructor payouts </a> </li><li> <a href="/developers/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> REST API & apps </a> </li><li> <a href="/features/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> All features </a> </li> </ul> </div><div> <h2 class="text-xs font-mono uppercase tracking-wider text-slate-500 mb-4"> Solutions </h2> <ul class="space-y-2"> <li> <a href="/solutions/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> All solutions </a> </li><li> <a href="/use-cases/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Use case library </a> </li><li> <a href="/for-coaches/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> For coaches </a> </li><li> <a href="/for-academies/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> For academies </a> </li><li> <a href="/for-schools/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> For schools </a> </li><li> <a href="/for-corporate-training/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> For corporate training </a> </li><li> <a href="/for-marketplaces/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> For marketplaces </a> </li><li> <a href="/for-membership-sites/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> For membership sites </a> </li><li> <a href="/vs-hosted-platforms/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> vs hosted platforms </a> </li> </ul> </div><div> <h2 class="text-xs font-mono uppercase tracking-wider text-slate-500 mb-4"> Product </h2> <ul class="space-y-2"> <li> <a href="/free-vs-pro/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Free vs Pro </a> </li><li> <a href="/wordpress-lms-plugin/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> WordPress LMS plugin </a> </li><li> <a href="/compare/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Compare </a> </li><li> <a href="/alternatives/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Alternatives </a> </li><li> <a href="/best-free-wordpress-lms-plugin/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Best free WordPress LMS </a> </li><li> <a href="/videos/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Video library </a> </li><li> <a href="/blog/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Blog </a> </li><li> <a href="/reviews/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Reviews </a> </li><li> <a href="/partners/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Partners </a> </li><li> <a href="/media/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Media kit </a> </li><li> <a href="https://wbcomdesigns.com/release-notes/learnomy/" rel="noopener noreferrer" target="_blank" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Changelog </a> </li><li> <a href="https://wbcomdesigns.com/release-notes/learnomy-pro/" rel="noopener noreferrer" target="_blank" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Pro changelog </a> </li><li> <a href="https://wbcomdesigns.com/downloads/learnomy/" rel="noopener noreferrer" target="_blank" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Download Free </a> </li><li> <a href="https://wbcomdesigns.com/downloads/learnomy-pro/" rel="noopener noreferrer" target="_blank" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Get Learnomy Pro </a> </li> </ul> </div><div> <h2 class="text-xs font-mono uppercase tracking-wider text-slate-500 mb-4"> Documentation </h2> <ul class="space-y-2"> <li> <a href="/docs/getting-started/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Getting started </a> </li><li> <a href="/docs/courses/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Courses </a> </li><li> <a href="/docs/quizzes/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Quizzes </a> </li><li> <a href="/docs/commerce/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Commerce & memberships </a> </li><li> <a href="/docs/certificates/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Certificates </a> </li><li> <a href="/docs/instructors/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Instructors </a> </li><li> <a href="/docs/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> All docs </a> </li> </ul> </div><div> <h2 class="text-xs font-mono uppercase tracking-wider text-slate-500 mb-4"> Support </h2> <ul class="space-y-2"> <li> <a href="/docs/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Documentation hub </a> </li><li> <a href="/support/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Support </a> </li><li> <a href="/about/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> About us </a> </li><li> <a href="/contact/" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Contact </a> </li><li> <a href="https://wbcomdesigns.com/start-a-project/" rel="noopener noreferrer" target="_blank" class="text-sm text-slate-700 hover:text-brand transition-colors leading-snug"> Custom development </a> </li> </ul> </div> </div> <div class="mt-12 pt-8 border-t border-slate-200 flex items-baseline gap-4 flex-wrap"> <p class="text-xs font-mono uppercase tracking-wider text-slate-500 shrink-0">Sister sites</p> <ul class="flex items-center gap-x-5 gap-y-2 flex-wrap m-0 p-0 list-none"> <li> <a href="https://wbcomdesigns.com" target="_blank" rel="noopener noreferrer" class="text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> Wbcom Designs </a> </li><li> <a href="https://vapvarun.com" target="_blank" rel="noopener noreferrer" class="text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> Vapvarun </a> </li><li> <a href="https://brndle.com" target="_blank" rel="noopener noreferrer" class="text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> Brndle </a> </li> </ul> </div> <div class="mt-4 flex items-baseline gap-4 flex-wrap"> <p class="text-xs font-mono uppercase tracking-wider text-slate-500 shrink-0">Part of the Wbcom Designs family</p> <ul class="flex items-center gap-x-5 gap-y-2.5 flex-wrap m-0 p-0 list-none"> <li> <a href="https://buddynext.com" target="_blank" rel="noopener noreferrer" title="The self-hosted community engine for WordPress" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/buddynext.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> BuddyNext </a> </li><li> <a href="https://buddyxtheme.com" target="_blank" rel="noopener noreferrer" title="Free community theme, Pro when you outgrow it" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/buddyx.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> BuddyX </a> </li><li> <a href="https://reigntheme.com" target="_blank" rel="noopener noreferrer" title="Premium community theme. Add pieces, build anything" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/reign.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> Reign </a> </li><li> <a href="https://jetonomy.org" target="_blank" rel="noopener noreferrer" title="Community forum and Q&A for WordPress" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/jetonomy.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> Jetonomy </a> </li><li> <a href="https://eventonomy.org" target="_blank" rel="noopener noreferrer" title="Events and RSVPs for WordPress communities" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/eventonomy.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> Eventonomy </a> </li><li> <a href="https://listora.org" target="_blank" rel="noopener noreferrer" title="Directories and listings your members can browse" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/listora.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> Listora </a> </li><li> <a href="https://snipshare.org" target="_blank" rel="noopener noreferrer" title="Code sharing built for developer communities" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/snipshare.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> SnipShare </a> </li><li> <a href="https://wbadmanager.com" target="_blank" rel="noopener noreferrer" title="Ad placements that turn traffic into revenue" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/wb-ad-manager.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> WB Ad Manager </a> </li><li> <a href="https://wpcareerboard.com" target="_blank" rel="noopener noreferrer" title="A job board your community actually uses" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/wp-career-board.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> WP Career Board </a> </li><li> <a href="https://wpsellservices.com" target="_blank" rel="noopener noreferrer" title="Sell services with offers, orders, and payouts" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/wp-sell-services.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> WP Sell Services </a> </li><li> <a href="https://wpmediaverse.com" target="_blank" rel="noopener noreferrer" title="Photos, video, and media albums for members" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/mediaverse.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> MediaVerse </a> </li><li> <a href="https://wbcomdesigns.com/downloads/wordpress-gamification-plugin/" target="_blank" rel="noopener noreferrer" title="Points, badges, and rewards that keep members active" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/wb-gamification.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> WB Gamification </a> </li><li> <a href="https://wbcomdesigns.com/downloads/product-roadmap/" target="_blank" rel="noopener noreferrer" title="Public roadmaps with voting your users trust" class="inline-flex items-center gap-1.5 text-sm font-semibold text-slate-700 hover:text-brand transition-colors"> <img src="/brand/family/product-roadmap.svg" alt="" width="18" height="18" loading="lazy" class="w-[18px] h-[18px] shrink-0"> Product Roadmap </a> </li> </ul> </div> <div class="mt-12 pt-8 border-t border-slate-200 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4"> <div class="flex items-center gap-3"> <img src="/brand/learnomy-horizontal.svg" alt="Learnomy" width="116" height="28" class="h-7 w-auto opacity-90"> <span class="text-xs text-slate-500"> © 2026 learnomy.app · A <a href="https://wbcomdesigns.com/" class="underline hover:text-slate-700">Wbcom Designs</a> product </span> </div> <div class="flex items-center gap-4"> <a href="https://twitter.com/wbcomdesigns" rel="noopener" aria-label="X / Twitter" class="text-slate-500 hover:text-slate-700 transition-colors"> <svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"> <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path> </svg> </a> <a href="https://www.facebook.com/wbcomdesigns" rel="noopener" aria-label="Facebook" class="text-slate-500 hover:text-slate-700 transition-colors"> <svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"> <path d="M24 12c0-6.627-5.373-12-12-12S0 5.373 0 12c0 5.99 4.388 10.954 10.125 11.854V15.469H7.078V12h3.047V9.356c0-3.007 1.792-4.668 4.533-4.668 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874V12h3.328l-.532 3.469h-2.796v8.385C19.612 22.954 24 17.99 24 12z"></path> </svg> </a> <a href="https://www.youtube.com/@WbcomDesigns" rel="noopener" aria-label="YouTube" class="text-slate-500 hover:text-slate-700 transition-colors"> <svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"> <path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"></path> </svg> </a> <a href="https://www.linkedin.com/company/wbcomdesigns" rel="noopener" aria-label="LinkedIn" class="text-slate-500 hover:text-slate-700 transition-colors"> <svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"> <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.063 2.063 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"></path> </svg> </a> </div> <nav class="mt-6 pt-4 border-t border-slate-200 flex flex-wrap items-center gap-x-5 gap-y-2" aria-label="Legal"> <a href="/privacy/" class="text-xs text-slate-500 hover:text-slate-700 transition-colors">Privacy</a> <a href="/terms/" class="text-xs text-slate-500 hover:text-slate-700 transition-colors">Terms</a> <a href="https://wbcomdesigns.com/support/" rel="noopener" class="text-xs text-slate-500 hover:text-slate-700 transition-colors">Support</a> <a href="/contact/" class="text-xs text-slate-500 hover:text-slate-700 transition-colors">Contact</a> </nav> </div> </div> </footer> <script> (function () { var els = document.querySelectorAll('.reveal'); if (!els.length) return; if (!('IntersectionObserver' in window) || window.matchMedia('(prefers-reduced-motion: reduce)').matches) { els.forEach(function (el) { el.classList.add('is-in'); }); return; } var io = new IntersectionObserver(function (entries) { entries.forEach(function (e) { if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); } }); }, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 }); els.forEach(function (el) { io.observe(el); }); })(); </script> <script async src="https://announce.wbcomdesigns.com/v1/embed.js"></script> </body></html>