Codendesigner

LW Course Catalog - WordPress plugin โ€” display LearnWorlds courses on any page with a shortcode

LW Course Catalog - WordPress plugin โ€” display LearnWorlds courses on any page with a shortcode

Regular price $299.00 USD
Regular price Sale price $299.00 USD
Sale Sold out
LW Course Catalog โ€” Plugin Documentation
WordPress Plugin

LW Course Catalog

Display courses from one or two LearnWorlds schools on any WordPress page using a simple shortcode. Visitors browse on WordPress and are redirected to LearnWorlds to enroll and pay.

๐Ÿ“ฆ v1.4.4
๐Ÿ”ง WordPress 5.8+
๐Ÿ˜ PHP 7.4+
๐Ÿซ Supports 2 schools

โฌ‡๏ธ Installation

1
Upload the pluginIn WordPress admin go to Plugins โ†’ Add New โ†’ Upload Plugin
2
Select the zip fileChoose lw-course-catalog.zip and click Install Now
3
ActivateClick Activate Plugin after installation completes
4
Open settingsGo to Settings โ†’ LW Course Catalog to configure your credentials
โœ… No other plugins are required. The plugin is self-contained with its own caching, logging, and admin UI.

๐Ÿ”‘ Getting your LearnWorlds credentials

All three values you need are on one page inside your LearnWorlds school admin. Navigate to:

https://yourschool.com/author/settings_api
What to copy
Value Where to find it Notes
API URL The "API URL" field with a Copy button Looks like https://yourschool.com/admin/api/ โ€” copy it exactly as shown
Client ID Click the eye ๐Ÿ‘ icon to reveal, then Copy Required alongside the Access Token
Access Token Under "Access Tokens" section โ†’ click Create โ†’ eye icon โ†’ copy Recommended auth method. Long-lived, no expiry unless revoked.
Client Secret Click Copy next to the masked field Optional โ€” only needed if not using an Access Token
โ„น๏ธ The API URL must include the full path (/admin/api/). Do not use just the root domain โ€” the plugin uses the exact URL you provide to build all API calls.
โš ๏ธ If your school uses a custom domain (e.g. www.foodsurety.com), use that custom domain in the API URL โ€” not the .learnworlds.com subdomain.

โš™๏ธ Plugin settings

Go to Settings โ†’ LW Course Catalog โ†’ โš™๏ธ Settings tab. There are two school sections โ€” School A is required, School B is optional.

School A / School B fields
Field Required Description
API URL Yes Full API URL from LearnWorlds settings. Example: https://yourschool.com/admin/api/
Access Token โญ Recommended Long-lived token. Paste the full string. If provided, Client Secret is not needed.
Client ID Yes Required alongside Access Token for the Lw-Client request header.
Client Secret Optional Only used if no Access Token is provided. Plugin falls back to OAuth2 client credentials flow.
Cache settings
Field Default Description
Cache Duration 12 hours How often course data is re-fetched from LearnWorlds. Options: 1h, 3h, 6h, 12h, 24h. Shorter = fresher data, more API calls. Longer = faster page loads.
โ„น๏ธ Leave School B fields completely blank until your second school is ready. It will be automatically included once configured. The plugin will not show errors for an empty School B.
Status tab

The ๐Ÿ“Š Status tab shows the cache state for each school (how many minutes remain before the next auto-refresh), the current configured URLs, and two action buttons:

Button What it does
Refresh Cache Now Immediately clears the cache and re-fetches all courses from all configured schools
Test Connection & Re-fetch Same as above but also redirects you to the Debug Log tab to see the full fetch result

๐ŸŽจ Card design settings

Go to Settings โ†’ LW Course Catalog โ†’ ๐ŸŽจ Card Design tab. All settings apply globally to every course card on the site.

Display toggles
Show thumbnail

Toggle the course image on or off

Show description

Toggle the excerpt text on or off

Show price

Toggle the price badge on or off

Show categories

Toggle category badges on or off

Show Enroll button

Links directly to the payment/checkout page

Show Learn More button

Links to the course detail/landing page

Course visibility
Setting Default Description
Hide draft courses On โœ… Hides courses with status: draft. Has absolute priority โ€” a draft course is always hidden when this is on, regardless of the private setting.
Hide private courses On โœ… Hides courses with access: private. Only evaluated after the draft check passes.
โœ… When you save Card Design settings, the cache is automatically cleared. The change takes effect on the next page load โ€” no manual refresh needed.
Text & layout
Setting Default Description
Enroll button text Enroll Now Label on the primary CTA button. Can also be overridden per-shortcode.
Learn More button text Learn More Label on the secondary button. Can also be overridden per-shortcode.
Description length 20 words How many words to show in the course description excerpt (5โ€“100).
Courses per page 12 How many cards to show before Prev/Next pagination appears. Can be overridden per-shortcode with the per_page attribute.
Colours
Setting Default
Card background #ffffff
Enroll button background #2563eb
Enroll button text colour #ffffff
Learn More button background #f1f5f9
Learn More button text colour #1e293b

๐Ÿ” Draft & private filtering

The plugin uses Option C โ€” Draft takes absolute priority. A course goes through two gates in strict order. If it is rejected at gate 1 (draft), it never reaches gate 2 (private).

Course status + access
Hide draft setting
Hide private setting
Result
Published + Public
either
either
โœ… Always shown
Published + Private
either
ON
Published + Private
either
OFF
โœ… Shown
Draft + Public
ON
irrelevant
Draft + Private
ON
irrelevant
Draft + Private
OFF
ON
Draft + Private
OFF
OFF
โœ… Shown
โ„น๏ธ The key principle: Draft means "not ready for anyone". Private means "ready but restricted". If Hide Draft is on, draft status overrides everything โ€” even if private courses are being shown.

๐Ÿ“„ Pagination

API-side fetch (all courses)

On first load the plugin fetches every page of courses from LearnWorlds automatically. LearnWorlds returns 50 courses per API page. For a school with 424 courses this means 9 API requests, all made server-side and cached.

Pagination uses the meta.page and meta.totalPages fields from the LearnWorlds API response. The plugin keeps fetching until page === totalPages.

โš ๏ธ The first cache build on a large school (400+ courses) takes 15โ€“40 seconds. All subsequent page loads for every visitor are served from cache instantly.
Display-side pagination (Prev/Next)

After all courses are fetched and cached, they are displayed in pages controlled by the Courses per page setting (default: 12). Prev/Next buttons appear automatically below the grid when the total exceeds the per-page limit.

The category filter bar and pagination work together โ€” filtering resets to page 1 and the page count updates to reflect the filtered total.

Cache lifecycle
Event Cache behaviour
First page load after activation Cache is empty โ€” plugin fetches all courses and stores them
Subsequent page loads Served from cache instantly โ€” no API calls
Cache TTL expires (default 12h) WP-Cron automatically refreshes in the background
Settings saved Cache is busted immediately โ€” fresh fetch on next load
Card Design settings saved Cache is busted โ€” draft/private filter changes take effect
Manual Refresh Cache Now Immediate bust and re-fetch triggered from admin

๐Ÿงฉ Shortcode reference

Place [lw_course_catalog] on any WordPress page, post, or widget area. All attributes are optional โ€” defaults come from the Card Design settings.

Attribute Values Default Description
school both / a / b both Which school's courses to display
columns 1 โ€“ 4 3 Grid column count. Automatically collapses to 2 on tablet, 1 on mobile.
per_page Any number From settings Courses per page before pagination. Overrides the Card Design setting for this instance only.
category Category name โ€” Pre-filter to a single category. Example: category="Food Safety"
enroll_text Any text From settings Override the Enroll button label for this shortcode instance
more_text Any text From settings Override the Learn More button label for this shortcode instance
Examples
Basic โ€” all courses from both schools
[lw_course_catalog]
School A only, 2-column grid
[lw_course_catalog school="a" columns="2"]
Filter to a specific category, 6 per page
[lw_course_catalog category="Food Safety" per_page="6"]
Custom button text
[lw_course_catalog enroll_text="Buy Now" more_text="View Course"]
Full example combining multiple attributes
[lw_course_catalog school="a" columns="3" per_page="9" category="HACCP" enroll_text="Enroll Today"]
Button destinations
Button Destination
Learn More The course detail/landing page on LearnWorlds โ€” e.g. https://yourschool.com/course/intro-haccp
Enroll Now The payment page on LearnWorlds โ€” e.g. https://yourschool.com/payment?product_id=intro-haccp&type=course

Both buttons open in a new tab. No payment or registration happens on WordPress โ€” everything is handled by LearnWorlds.

๐Ÿ”Ž Debug log

Go to Settings โ†’ LW Course Catalog โ†’ ๐Ÿ” Debug Log tab. The log records every step of the API fetch process โ€” authentication, pagination, filtering, and caching.

Log levels
Level Colour What it means
ERROR ๐Ÿ”ด Red Something failed โ€” authentication error, API error, or network problem. Always investigate these.
WARN ๐ŸŸก Yellow A non-fatal issue โ€” e.g. School B not configured, or a fallback was used.
INFO ๐Ÿ”ต Blue Normal progress messages โ€” token obtained, page fetched, courses cached.
DEBUG โšซ Gray Detailed technical data โ€” exact URLs called, raw API meta, field names. Useful for diagnosing image or pagination issues.
Actions
Action Description
Run Connection Test Clears the cache and triggers a fresh fetch from all configured schools. All steps are logged in real time. Use this after changing credentials.
Clear Log Removes all log entries. The log automatically keeps the most recent 200 entries.
Filter buttons Show only Errors, Warnings, Info, or Debug entries. Useful for quickly spotting problems.
Reading a successful fetch log

After a successful connection test you should see entries like this (newest first in the log):

INFO  [School A] โœ… Fetch complete. Total courses: 412 across 9 pages
INFO  [School A] Page 9 done: 24 items, 4 skipped, has_more=NO, total=412
INFO  [School A] Page 8 done: 50 items, 6 skipped, has_more=YES, total=388
...
INFO  [School A] Page 1 done: 50 items, 10 skipped, has_more=YES, total=40
INFO  [School A] Using static access token
INFO  [School A] Starting API fetch

๐Ÿ› ๏ธ Troubleshooting

โš ๏ธ No courses shown at all
Check the Settings tab โ€” ensure the API URL, Client ID, and Access Token are all filled in correctly. Then go to the Debug Log tab and click Run Connection Test. Read the ERROR entries to see exactly what failed.
โš ๏ธ Only 40โ€“50 courses showing instead of 400+
This was a pagination bug fixed in v1.4.2. Update to v1.4.4 and run a Connection Test. The log should show "Fetch complete. Total courses: 400+" across multiple pages.
โš ๏ธ Page 2 of the catalog is empty
This was a display pagination bug fixed in v1.4.0. Update to v1.4.4. The JS now controls all card visibility โ€” no conflict with server-side class names.
โš ๏ธ Auth failed โ€” HTTP 404 error
The API URL is incorrect. It must include the full path: https://yourschool.com/admin/api/. Do not use the root domain alone. Copy it exactly from LearnWorlds Settings โ†’ Developers โ†’ API.
โš ๏ธ Course images not showing
Check the Debug Log โ†’ expand the "Raw page 1 response" DEBUG entry โ†’ look at the "first_course" field โ€” it lists all field names in the API response. The plugin tries 15 image field name variants. If none match, let us know the exact field name shown and it can be added.
โš ๏ธ Draft or private courses still appearing
Go to Card Design tab, check the relevant hide option, and save. The cache auto-clears on save. If still showing, run a manual Connection Test to force a full re-fetch with the new filter applied.
โš ๏ธ Enroll button going to the wrong page
The enroll URL is built from the course slug and package ID returned by the API. Check the Debug Log for the raw course data to verify the slug. If LearnWorlds provides a payment_url field directly, the plugin uses that instead.
โš ๏ธ Settings not saving
Your WordPress user must have the manage_options capability (Administrator role). Lower-level roles cannot save plugin settings.
โ„น๏ธ For persistent issues, share the full Debug Log (especially ERROR and DEBUG entries) with your developer. The log contains the exact API responses needed to diagnose any problem.
View full details
  • 100% Satisfaction Unlimited revisions until you're thrilled
  • Fast Turnaround Most projects shipped in 7โ€“14 days
  • Secure Payment Encrypted checkout & milestone billing
  • Free Consultation 30-min strategy call before you book