WordPress Integration Guide
Integrate SCORM functionality into your WordPress site using the AllureLMS SCORM API.
Table of Contents
- Overview
- Prerequisites
- Plugin Setup
- Shortcode Implementation
- Admin Interface
- User Progress Tracking
- Complete Example
Overview
This guide shows how to create a WordPress plugin that integrates with the SCORM API to:
- Upload and manage SCORM packages
- Display SCORM courses to learners
- Track learner progress
- Display completion certificates
Prerequisites
- WordPress 5.0+
- PHP 8.0+
- SCORM API account and API key
- Basic WordPress plugin development knowledge
Plugin Setup
1. Create Plugin Structure
wp-content/plugins/scorm-api-integration/
├── scorm-api-integration.php
├── includes/
│ ├── class-scorm-api-client.php
│ ├── class-scorm-admin.php
│ └── class-scorm-frontend.php
├── admin/
│ └── admin.php
└── public/
└── public.php
2. Main Plugin File
<?php
/**
* Plugin Name: SCORM API Integration
* Description: Integrate AllureLMS SCORM API with WordPress
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
define('SCORM_API_VERSION', '1.0.0');
define('SCORM_API_PLUGIN_DIR', plugin_dir_path(__FILE__));
require_once SCORM_API_PLUGIN_DIR . 'includes/class-scorm-api-client.php';
require_once SCORM_API_PLUGIN_DIR . 'includes/class-scorm-admin.php';
require_once SCORM_API_PLUGIN_DIR . 'includes/class-scorm-frontend.php';
class SCORM_API_Integration {
public function __construct() {
add_action('plugins_loaded', array($this, 'init'));
}
public function init() {
if (is_admin()) {
new SCORM_Admin();
} else {
new SCORM_Frontend();
}
}
}
new SCORM_API_Integration();
3. API Client Class
<?php
// includes/class-scorm-api-client.php
class SCORM_API_Client {
private $api_key;
private $base_url;
private $tenant_id;
public function __construct() {
$this->api_key = get_option('scorm_api_key');
$this->base_url = get_option('scorm_api_url', 'https://app.allureconnect.com');
$this->tenant_id = get_option('scorm_tenant_id');
}
public function upload_package($file_path, $uploaded_by) {
$filename = basename($file_path);
$file_size = filesize($file_path);
$mint = wp_remote_post($this->base_url . '/api/v1/packages/upload-url', array(
'headers' => array(
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode(array(
'tenant_id' => $this->tenant_id,
'uploaded_by' => $uploaded_by,
'filename' => $filename,
'file_size' => $file_size,
)),
'timeout' => 120,
));
if (is_wp_error($mint)) {
return false;
}
$ticket = json_decode(wp_remote_retrieve_body($mint), true);
if (empty($ticket['presigned_url'])) {
return false;
}
$put = wp_remote_request($ticket['presigned_url'], array(
'method' => 'PUT',
'headers' => isset($ticket['required_put_headers']) ? $ticket['required_put_headers'] : array(),
'body' => file_get_contents($file_path),
'timeout' => 600,
));
if (is_wp_error($put) || wp_remote_retrieve_response_code($put) >= 400) {
return false;
}
$proc = wp_remote_post($this->base_url . '/api/v1/packages/process', array(
'headers' => array(
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode(array(
'tenant_id' => $this->tenant_id,
'uploaded_by' => $uploaded_by,
'storage_path' => $ticket['storage_path'],
'original_filename' => $filename,
)),
'timeout' => 300,
));
if (is_wp_error($proc)) {
return false;
}
return json_decode(wp_remote_retrieve_body($proc), true);
}
public function launch_session($package_id, $user_id) {
$url = $this->base_url . '/api/v1/packages/' . $package_id . '/launch';
$response = wp_remote_post($url, array(
'headers' => array(
'X-API-Key' => $this->api_key,
'Content-Type' => 'application/json',
),
'body' => json_encode(array(
'user_id' => $user_id,
'session_id' => wp_generate_uuid4(),
)),
));
if (is_wp_error($response)) {
return false;
}
return json_decode(wp_remote_retrieve_body($response), true);
}
public function get_session($session_id) {
$url = $this->base_url . '/api/v1/sessions/' . $session_id;
$response = wp_remote_get($url, array(
'headers' => array(
'X-API-Key' => $this->api_key,
),
));
if (is_wp_error($response)) {
return false;
}
return json_decode(wp_remote_retrieve_body($response), true);
}
}
Shortcode Implementation
SCORM Player Shortcode
<?php
// includes/class-scorm-frontend.php
class SCORM_Frontend {
public function __construct() {
add_shortcode('scorm_player', array($this, 'scorm_player_shortcode'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
}
public function scorm_player_shortcode($atts) {
$atts = shortcode_atts(array(
'package_id' => '',
'width' => '100%',
'height' => '800px',
), $atts);
if (empty($atts['package_id'])) {
return '<p>Package ID is required</p>';
}
$user_id = get_current_user_id();
if (!$user_id) {
return '<p>Please log in to view this course</p>';
}
$client = new SCORM_API_Client();
$launch = $client->launch_session($atts['package_id'], $user_id);
if (!$launch) {
return '<p>Failed to launch course</p>';
}
// Store session ID in user meta
update_user_meta($user_id, 'scorm_session_' . $atts['package_id'], $launch['session_id']);
ob_start();
?>
<div class="scorm-player-container">
<iframe
src="<?php echo esc_url($launch['launch_url']); ?>"
width="<?php echo esc_attr($atts['width']); ?>"
height="<?php echo esc_attr($atts['height']); ?>"
frameborder="0"
allow="fullscreen"
title="SCORM Course"
></iframe>
</div>
<script>
// Poll for completion
setInterval(function() {
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=check_scorm_progress&session_id=<?php echo $launch['session_id']; ?>'
})
.then(response => response.json())
.then(data => {
if (data.completed) {
alert('Course completed!');
}
});
}, 10000);
</script>
<?php
return ob_get_clean();
}
public function enqueue_scripts() {
wp_enqueue_script('scorm-api', plugin_dir_url(__FILE__) . 'js/scorm-api.js', array('jquery'), '1.0.0', true);
}
}
Usage
// In WordPress post/page editor:
[scorm_player package_id="pkg_abc123" width="100%" height="800px"]
Admin Interface
Settings Page
<?php
// includes/class-scorm-admin.php
class SCORM_Admin {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_init', array($this, 'register_settings'));
}
public function add_admin_menu() {
add_menu_page(
'SCORM API',
'SCORM API',
'manage_options',
'scorm-api',
array($this, 'render_settings_page'),
'dashicons-book-alt',
30
);
}
public function register_settings() {
register_setting('scorm_api_settings', 'scorm_api_key');
register_setting('scorm_api_settings', 'scorm_api_url');
register_setting('scorm_api_settings', 'scorm_tenant_id');
}
public function render_settings_page() {
?>
<div class="wrap">
<h1>SCORM API Settings</h1>
<form method="post" action="options.php">
<?php settings_fields('scorm_api_settings'); ?>
<table class="form-table">
<tr>
<th><label for="scorm_api_url">API URL</label></th>
<td>
<input type="url" id="scorm_api_url" name="scorm_api_url"
value="<?php echo esc_attr(get_option('scorm_api_url')); ?>"
class="regular-text" />
</td>
</tr>
<tr>
<th><label for="scorm_api_key">API Key</label></th>
<td>
<input type="password" id="scorm_api_key" name="scorm_api_key"
value="<?php echo esc_attr(get_option('scorm_api_key')); ?>"
class="regular-text" />
</td>
</tr>
<tr>
<th><label for="scorm_tenant_id">Tenant ID</label></th>
<td>
<input type="text" id="scorm_tenant_id" name="scorm_tenant_id"
value="<?php echo esc_attr(get_option('scorm_tenant_id')); ?>"
class="regular-text" />
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
}
Package Upload Interface
public function render_upload_page() {
if (isset($_POST['upload_scorm'])) {
$file = $_FILES['scorm_file'];
$client = new SCORM_API_Client();
$result = $client->upload_package($file['tmp_name'], get_current_user_id());
if ($result) {
// Store package ID in WordPress
add_post_meta(get_the_ID(), 'scorm_package_id', $result['id']);
echo '<div class="notice notice-success"><p>Package uploaded successfully!</p></div>';
}
}
?>
<div class="wrap">
<h1>Upload SCORM Package</h1>
<form method="post" enctype="multipart/form-data">
<input type="file" name="scorm_file" accept=".zip" required />
<?php submit_button('Upload Package', 'primary', 'upload_scorm'); ?>
</form>
</div>
<?php
}
User Progress Tracking
AJAX Handler
add_action('wp_ajax_check_scorm_progress', 'check_scorm_progress');
add_action('wp_ajax_nopriv_check_scorm_progress', 'check_scorm_progress');
function check_scorm_progress() {
$session_id = sanitize_text_field($_POST['session_id']);
$client = new SCORM_API_Client();
$session = $client->get_session($session_id);
if ($session) {
// Update user meta
update_user_meta(
get_current_user_id(),
'scorm_progress_' . $session_id,
array(
'completion_status' => $session['completion_status'],
'score' => $session['score']['scaled'],
'time_spent' => $session['time_spent_seconds'],
)
);
wp_send_json_success(array(
'completed' => $session['completion_status'] === 'completed',
'score' => $session['score']['scaled'],
));
}
wp_send_json_error('Failed to get session');
}
Progress Display
function display_user_progress($user_id) {
$packages = get_posts(array(
'post_type' => 'scorm_course',
'posts_per_page' => -1,
));
foreach ($packages as $package) {
$package_id = get_post_meta($package->ID, 'scorm_package_id', true);
$session_id = get_user_meta($user_id, 'scorm_session_' . $package_id, true);
if ($session_id) {
$progress = get_user_meta($user_id, 'scorm_progress_' . $session_id, true);
?>
<div class="scorm-progress-item">
<h3><?php echo $package->post_title; ?></h3>
<p>Status: <?php echo $progress['completion_status']; ?></p>
<p>Score: <?php echo ($progress['score'] * 100); ?>%</p>
</div>
<?php
}
}
}
Complete Example
Full Plugin Structure
<?php
/**
* Complete SCORM API WordPress Plugin
*/
// Main plugin file with all components integrated
// See individual class files above for implementation
Custom Post Type for Courses
function register_scorm_course_post_type() {
register_post_type('scorm_course', array(
'labels' => array(
'name' => 'SCORM Courses',
'singular_name' => 'SCORM Course',
),
'public' => true,
'has_archive' => true,
'supports' => array('title', 'editor', 'thumbnail'),
));
}
add_action('init', 'register_scorm_course_post_type');
Best Practices
- Security: Always sanitize and validate user input
- Caching: Cache package metadata to reduce API calls
- Error Handling: Display user-friendly error messages
- Performance: Use AJAX for progress updates
- User Experience: Show loading states and progress indicators
Related Documentation
Last Updated: 2025-01-15