A custom Open edX XBlock for creating interactive HTML/CSS/JS content with learner interaction tracking and auto-grading.
This XBlock allows course authors to define custom HTML, CSS, and JavaScript content and automatically captures learner interactions in JSON format for grading, analytics, or state restoration.
- Custom HTML/CSS/JS Content: Authors define their own HTML, CSS, and JavaScript content in the Studio editor
- Learner Interaction Tracking: Captures learner interactions via the
submitInteraction(data)API - Auto-Grading: Optional automatic grading — either via author JavaScript or server-side answer matching
- Completion Tracking: Emits completion events when learners submit an interaction
- Feedback Display: Configurable correct/incorrect feedback with custom messages
- Previous Response: Optionally shows learners their previous response on return
- Test Grading: Studio includes a "Test Grading" panel to verify grading config before publishing
- Debug Mode: Staff-only debug panel showing block state
- Masquerade Support: Staff can view individual student state via Open edX's "View as Specific Learner"
- Python 3.11+
- Django 4.2 or 5.2
- Open edX (Redwood or later)
Add to your OPENEDX_EXTRA_PIP_REQUIREMENTS:
git+https://github.com/blend-ed/interactive-content-xblock.git@master
Add interactive_content_xblock to your course's Advanced Module List:
Settings → Advanced Settings → Advanced Module List
Add the InteractiveContentXBlock component to your course
Click "Edit" to open the Studio editor
Configure the following:
- HTML Content: The structure of your interactive element
- CSS Styles: Styling for your content
- JavaScript Code: Interactivity logic using
submitInteraction(data) - Grading Configuration: Answer matching mode, correct answer(s), and feedback messages
Use the
submitInteraction(data)function in your JavaScript to capture learner interactions:function submitAnswer(answer) { submitInteraction({ answer: answer, correct: answer === "Paris", timeSpent: Math.round((Date.now() - startTime) / 1000) }); }
Use the Test Grading panel in Studio to verify your grading config works before publishing.
Learners see the rendered HTML content with the author's CSS and JavaScript applied. The XBlock automatically provides the submitInteraction() function for capturing interactions.
- Display Name: The title shown to learners
- Weight: Points value for grading
- Enable Debug Mode: Show debug panel (staff only)
- Auto Grade Enabled: Enable automatic grading
- Show Feedback to Learners: Show correct/incorrect feedback after submission
- Show Previous Response: Show learners their previous response on return
- Grading Configuration: Answer matching mode (None / Single Answer / Multiple Fields), correct answer value(s), and feedback messages
There are two ways to grade interactions:
1. Author JavaScript provides correctness directly (recommended for most cases):
Include a correct boolean in the data passed to submitInteraction():
submitInteraction({
answer: "Paris",
correct: true,
timeSpent: 45
});The XBlock uses this directly — no server-side config needed. If you've set feedback messages in Grading Configuration, they'll be shown automatically.
2. Server-side answer matching:
Set "Auto Grade Enabled" to True and configure the Grading Configuration in Studio:
- Single Answer: Set the correct answer value. The server compares case-insensitively.
- Multiple Fields: Add field name / expected value pairs. Partial credit is awarded proportionally.
Configure feedback messages (Correct Feedback / Incorrect Feedback) to show custom responses.
The Studio editor can generate (and refine) the HTML, CSS, JavaScript and grading configuration from a natural-language description. The feature is off by default and entirely invisible until the platform configures it — no AI SDK is installed, no extra dependencies are pulled in, and unconfigured instances behave exactly as before.
Enable it by adding deployment settings (LMS/CMS XBLOCK_SETTINGS):
XBLOCK_SETTINGS:
InteractiveContentXBlock:
ai:
api_url: "https://api.openai.com/v1/chat/completions" # any OpenAI-compatible endpoint
api_key: "sk-..."
model: "gpt-4.1"
# optional:
extra_headers: {} # e.g. Portkey x-portkey-* routing headers
timeout: 60 # seconds
temperature: 0.7
max_tokens: 8192With this in place, the Studio editor shows a Generate with AI section: describe the content you want, click Generate, review the filled-in fields (use the Test Grading panel to verify), and Save. Check Refine current content to iterate on what's already in the editor instead of starting over. Nothing is persisted until Save, so you can regenerate freely. Only course staff can invoke the generation handler, and the API key never leaves the server.
Deployments with their own AI stack (gateway routing, per-organisation
credentials, credit accounting) can set provider to a dotted path of a
callable instead of api_url:
XBLOCK_SETTINGS:
InteractiveContentXBlock:
ai:
provider: "myplugin.ai.generate_for_interactive_xblock"The callable is invoked as provider(prompt=..., config=..., context=...)
(context carries usage_id, user_id and username) and must
return the raw LLM response text.
Staff can view individual student state using the platform's built-in masquerade feature ("View as Specific Learner"). This works because the XBlock sets show_in_read_only_mode = True. Bulk data exports are available through the Open edX instructor dashboard.
pip install -e . # development install
make requirements # full dev environmenttox -e py312-django52 # Django 5.2
tox -e py312-django42 # Django 4.2
pytest tests/test_interactive_content_xblock.py # specific file
pytest tests/test_interactive_content_xblock.py::TestInteractiveContentXBlock::test_method_name # single testtox -e quality # pylint, pycodestyle, pydocstyle, isortInstall in development mode:
cd interactive-content-xblock pip install -e .
Add to Tutor mounts:
tutor mounts add /path/to/interactive-content-xblock
Create a Tutor plugin (
touch $(tutor plugins printroot)/mount_interactive_content_xblock.py):from tutor import hooks hooks.Filters.MOUNTED_DIRECTORIES.add_item(("openedx", "interactive_content_xblock"))
Enable and build:
tutor plugins enable mount_interactive_content_xblock tutor images build openedx-dev tutor dev start -d
This is the default content when you add a new block:
<div class="quiz">
<h3>Sample Quiz</h3>
<p>What is the capital of France?</p>
<div class="options">
<button onclick="submitAnswer('Paris')">Paris</button>
<button onclick="submitAnswer('London')">London</button>
<button onclick="submitAnswer('Berlin')">Berlin</button>
</div>
</div>var startTime = Date.now();
function submitAnswer(answer) {
submitInteraction({
answer: answer,
correct: answer === "Paris",
timeSpent: Math.round((Date.now() - startTime) / 1000)
});
}Copyright © 2026 Blend-ed.
Interactive Content XBlock is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the LICENSE file in this repository for the full license text.
Maintainer: zameel7.