Template integration
Rendering your own output inside course and lesson pages.
How the templates are chosen
POM LMS supplies the single templates for both post types: a course template for course and a lesson template for lesson. They are applied through WordPress's single-template filter.
A theme can replace them the way it replaces any single template, by filtering the template later. Before you do, consider whether a hook does what you need — a replaced template stops receiving the plugin's improvements, and it becomes your job to apply the access checks the original performs.
The hooks inside the pages
Both templates fire the theme's standard post-single actions, so anything already written against POM Theme post singles works on courses and lessons:
| Action | Fires |
|---|---|
pom_before_post_single_content |
Before the course content |
pom_after_post_single_content |
After the course content |
pom_before_lesson_single_content |
Before the lesson content |
pom_after_lesson_single_content |
After the lesson content |
pom_after_post_single_footer |
After the post footer |
pom_after_post_single_author |
After the author area |
pom_after_post_single_nav |
After the previous/next navigation |
pom_after_post_single_comments |
After the comments |
The two lesson-specific actions are the ones to use for lesson features — a downloads list under the video, a notes panel, a call to action after the content.
Content hooks fire inside the accessible branch
The lesson content actions run where the lesson content is rendered, which is the branch reached by students who have access.
Do not rely on that for security. If your callback outputs anything derived from lesson content, check access yourself:
add_action( 'pom_after_lesson_single_content', function () {
$lesson_id = get_the_ID();
if ( ! pom_lms_user_can_access_lesson( $lesson_id ) ) {
return;
}
// Safe to render.
} );
A hook that fires in a template you did not write is not an access check. See The access control contract.
The subheader
Lesson pages print the course title in the subheader, through the theme's subheader hook. Course and lesson subheaders are otherwise the theme's, configured by the plugin's settings.
If you are adding to the subheader, do it through the theme's subheader hooks, and check the post type — a callback that assumes a lesson will fatally misbehave on a course.
The outline
The course outline — the progress bar, the sections, the lesson list, the back link — is rendered by the plugin. It is not a hookable structure: there is no action for "before a lesson row" or "after a section".
If you need a different outline, build your own from the queries in Queries and URL helpers, and apply the access helpers per lesson so disabled rows stay disabled.
Lessons load without a full page reload
Opening a lesson from the outline replaces the content rather than reloading the page, with a configurable overlay covering the transition.
That has one consequence for integrators: JavaScript bound on page load will not bind to content that arrives afterwards. Use delegated event handling on a stable ancestor rather than binding directly to elements inside the lesson content.
Styling
The course sidebar uses POM Theme's p-1 helper for 1rem padding. Custom template copies should use the theme's rem helper scale rather than retired pixel-named classes. Update the plugin and theme together; review saved content separately with wp pom migrate-spacing-helpers --dry-run when upgrading an older site.
Course and lesson pages are theme pages, so they inherit the theme's styles. Add your styles through the normal enqueue mechanism, conditioned on the post type:
if ( is_singular( [ 'course', 'lesson' ] ) ) {
// Enqueue.
}
What not to hook
Do not filter the rendered no-access output to substitute your own message. Site owners configure those texts per course, and an integration that overrides them creates a message nobody can find in the administration.
If a course needs different wording, that is a course field, not code.